alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.editor;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Arrays;
import java.util.ArrayList;

/**
* Token context defines the environment in which only a limited set
* of tokens can be used. This set can be retrieved by calling
* the getTokenIDs() method. The context can contain other
* contexts which means that the context can possibly switch
* into one of its children contexts during lexing.
* The child context can also have other children that can
* work in the same way.
* In this way context-paths can be created. They describe
* the way how was the token lexically recognized.
* The context can be retrieved when the syntax-class is known
* using the get method.
* 
*
* @author Miloslav Metelka
* @version 1.00
*/

public class TokenContext {

    private static final TokenContext[] EMPTY_CHILDREN = new TokenContext[0];

    private final String namePrefix;

    private final TokenContext[] children;

    private final HashMap pathCache = new HashMap(37);

    private final ArrayList tokenIDList = new ArrayList();

    private final ArrayList tokenCategoryList = new ArrayList();

    private TokenID[] tokenIDs;

    private TokenCategory[] tokenCategories;

    private TokenContextPath contextPath;

    private TokenContextPath[] allContextPaths;

    private TokenContextPath[] lastContextPathPair;

    public TokenContext(String namePrefix) {
        this(namePrefix, EMPTY_CHILDREN);
    }

    /** Construct new token-context.
    * @param namePrefix name that will prefix all the token-ids names.
    * @param children child token contexts.
    */
    public TokenContext(String namePrefix, TokenContext[] children) {
        if (namePrefix == null) {
            throw new IllegalArgumentException("Name prefix must be non-null."); // NOI18N
        }

        this.namePrefix = namePrefix.intern();
        this.children = (children != null) ? children : EMPTY_CHILDREN;

        contextPath = TokenContextPath.get(new TokenContext[] { this });
    }

    /** Get the prefix that this context adds to the name of its tokens. */
    public String getNamePrefix() {
        return namePrefix;
    }

    /** Get the children contexts of this context. It returns empty-array
    * if there are no children.
    */
    public TokenContext[] getChildren() {
        return children;
    }

    /** Add token-id to the set of token-ids that belong to this context. */
    protected void addTokenID(TokenID tokenID) {
        synchronized (tokenIDList) {
            tokenIDList.add(tokenID);
            tokenIDs = null;

            // Check whether there's a valid and new category for this token-id
            TokenCategory tcat = tokenID.getCategory();
            if (tcat != null && tokenCategoryList.indexOf(tcat) < 0) {
                tokenCategoryList.add(tcat);
                tokenCategories = null;
            }
        }
    }

    /** Add all static-final token-id fields declared
    * in this token-context using Class.getDeclaredFields() call.
    */
    protected void addDeclaredTokenIDs() throws IllegalAccessException, SecurityException {
        Field[] fields = this.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            int flags = Modifier.STATIC | Modifier.FINAL;
            if ((fields[i].getModifiers() & flags) == flags
                    && TokenID.class.isAssignableFrom(fields[i].getType())
               ) {
                addTokenID((TokenID)fields[i].get(null));
            }
        }
    }

    /** Get the token-ids that belong to this token-context. It doesn't
    * return the children's token-ids.
    */
    public TokenID[] getTokenIDs() {
        if (tokenIDs == null) {
            synchronized (tokenIDList) {
                tokenIDs = (TokenID[])tokenIDList.toArray(new TokenID[tokenIDList.size()]);
            }
        }

        return tokenIDs;
    }

    /** Get the token-categories that belong to this token-context. It doesn't
    * return the children's token-categories.
    */
    public TokenCategory[] getTokenCategories() {
        if (tokenCategories == null) {
            synchronized (tokenCategoryList) {
                tokenCategories = (TokenCategory[])tokenCategoryList.toArray(
                                      new TokenCategory[tokenCategoryList.size()]);
            }
        }

        return tokenCategories;
    }

    /** Get the context path for this token-context. */
    public TokenContextPath getContextPath() {
        return contextPath;
    }

    /** Get the context path for this token-context that is derived
    * from the path of one of the children.
    */
    public TokenContextPath getContextPath(TokenContextPath childPath) {
        if (childPath == null) {
            return contextPath;
        }

        TokenContextPath[] lastPair = lastContextPathPair;
        if (lastPair == null || lastPair[0] != childPath) {
            synchronized (pathCache) {
                lastPair = (TokenContextPath[])pathCache.get(childPath);
                if (lastPair == null) {
                    // Build the array of contexts
                    TokenContext[] origContexts = childPath.getContexts();
                    TokenContext[] contexts = new TokenContext[origContexts.length + 1];
                    System.arraycopy(origContexts, 0, contexts, 0, origContexts.length);
                    contexts[origContexts.length] = this;

                    TokenContextPath path = TokenContextPath.get(contexts);

                    lastPair = new TokenContextPath[] { childPath, path };
                    pathCache.put(childPath, lastPair);
                }
                lastContextPathPair = lastPair;
            }
        }

        return lastPair[1];
    }

    /** Get all the context paths for this token-context including
    * itself as the first one and all its children.
    */
    public TokenContextPath[] getAllContextPaths() {
        if (allContextPaths == null) {
            ArrayList cpList = new ArrayList();
            cpList.add(getContextPath());

            for (int i = 0; i < children.length; i++) {
                TokenContextPath[] childPaths = children[i].getAllContextPaths();
                for (int j = 0; j < childPaths.length; j++) {
                    cpList.add(getContextPath(childPaths[j]));
                }
            }

            allContextPaths = new TokenContextPath[cpList.size()];
            cpList.toArray(allContextPaths);
        }

        return allContextPaths;
    }

}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.