/*
 * Copyright 1994-2003 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.tools.java;

import java.util.Hashtable;
import java.io.PrintStream;
import java.util.Enumeration;

/**
 * A class to represent identifiers.<p>
 *
 * An identifier instance is very similar to a String. The difference
 * is that identifier can't be instanciated directly, instead they are
 * looked up in a hash table. This means that identifiers with the same
 * name map to the same identifier object. This makes comparisons of
 * identifiers much faster.<p>
 *
 * A lot of identifiers are qualified, that is they have '.'s in them.
 * Each qualified identifier is chopped up into the qualifier and the
 * name. The qualifier is cached in the value field.<p>
 *
 * Unqualified identifiers can have a type. This type is an integer that
 * can be used by a scanner as a token value. This value has to be set
 * using the setType method.<p>
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 *
 * @author      Arthur van Hoff
 */

public final
class Identifier implements Constants {
    /**
     * The hashtable of identifiers
     */
    static Hashtable hash = new Hashtable(3001, 0.5f);

    /**
     * The name of the identifier
     */
    String name;

    /**
     * The value of the identifier, for keywords this is an
     * instance of class Integer, for qualified names this is
     * another identifier (the qualifier).
     */
    Object value;

    /**
     * The Type which corresponds to this Identifier.  This is used as
     * cache for Type.tClass() and shouldn't be used outside of that
     * context.
     */
    Type typeObject = null;

    /**
     * The index of INNERCLASS_PREFIX in the name, or -1 if none.
     */
    private int ipos;

    /**
     * Construct an identifier. Don't call this directly,
     * use lookup instead.
     * @see Identifier.lookup
     */
    private Identifier(String name) {
        this.name = name;
        this.ipos = name.indexOf(INNERCLASS_PREFIX);
    }

    /**
     * Get the type of the identifier.
     */
    int getType() {
        return ((value != null) && (value instanceof Integer)) ?
                ((Integer)value).intValue() : IDENT;
    }

    /**
     * Set the type of the identifier.
     */
    void setType(int t) {
        value = new Integer(t);
        //System.out.println("type(" + this + ")=" + t);
    }

    /**
     * Lookup an identifier.
     */
    public static synchronized Identifier lookup(String s) {
        //System.out.println("lookup(" + s + ")");
        Identifier id = (Identifier)hash.get(s);
        if (id == null) {
            hash.put(s, id = new Identifier(s));
        }
        return id;
    }

    /**
     * Lookup a qualified identifier.
     */
    public static Identifier lookup(Identifier q, Identifier n) {
        // lookup("", x) => x
        if (q == idNull)  return n;
        // lookup(lookupInner(c, ""), n) => lookupInner(c, lookup("", n))
        if (q.name.charAt(q.name.length()-1) == INNERCLASS_PREFIX)
            return lookup(q.name+n.name);
        Identifier id = lookup(q + "." + n);
        if (!n.isQualified() && !q.isInner())
            id.value = q;
        return id;
    }

    /**
     * Lookup an inner identifier.
     * (Note:  n can be idNull.)
     */
    public static Identifier lookupInner(Identifier c, Identifier n) {
        Identifier id;
        if (c.isInner()) {
            if (c.name.charAt(c.name.length()-1) == INNERCLASS_PREFIX)
                id = lookup(c.name+n);
            else
                id = lookup(c, n);
        } else {
            id = lookup(c + "." + INNERCLASS_PREFIX + n);
        }
        id.value = c.value;
        return id;
    }

    /**
     * Convert to a string.
     */
    public String toString() {
        return name;
    }

    /**
     * Check if the name is qualified (ie: it contains a '.').
     */
    public boolean isQualified() {
        if (value == null) {
            int idot = ipos;
            if (idot <= 0)
                idot = name.length();
            else
                idot -= 1;      // back up over previous dot
            int index = name.lastIndexOf('.', idot-1);
            value = (index < 0) ? idNull : Identifier.lookup(name.substring(0, index));
        }
        return (value instanceof Identifier) && (value != idNull);
    }

    /**
     * Return the qualifier. The null identifier is returned if
     * the name was not qualified.  The qualifier does not include
     * any inner part of the name.
     */
    public Identifier getQualifier() {
        return isQualified() ? (Identifier)value : idNull;
    }

    /**
     * Return the unqualified name.
     * In the case of an inner name, the unqualified name
     * will itself contain components.
     */
    public Identifier getName() {
        return isQualified() ?
            Identifier.lookup(name.substring(((Identifier)value).name.length() + 1)) : this;
    }

    /** A space character, which precedes the first inner class
     *  name in a qualified name, and thus marks the qualification
     *  as involving inner classes, instead of merely packages.<p>
     *  Ex:  <tt>java.util.Vector. Enumerator</tt>.
     */
    public static final char INNERCLASS_PREFIX = ' ';

    /* Explanation:
     * Since much of the compiler's low-level name resolution code
     * operates in terms of Identifier objects.  This includes the
     * code which walks around the file system and reports what
     * classes are where.  It is important to get nesting information
     * right as early as possible, since it affects the spelling of
     * signatures.  Thus, the low-level import and resolve code must
     * be able Identifier type must be able to report the nesting
     * of types, which implied that that information must be carried
     * by Identifiers--or that the low-level interfaces be significantly
     * changed.
     */

    /**
     * Check if the name is inner (ie: it contains a ' ').
     */
    public boolean isInner() {
        return (ipos > 0);
    }

    /**
     * Return the class name, without its qualifier,
     * and with any nesting flattened into a new qualfication structure.
     * If the original identifier is inner,
     * the result will be qualified, and can be further
     * decomposed by means of <tt>getQualifier</tt> and <tt>getName</tt>.
     * <p>
     * For example:
     * <pre>
     * Identifier id = Identifier.lookup("pkg.Foo. Bar");
     * id.getName().name      =>  "Foo. Bar"
     * id.getFlatName().name  =>  "Foo.Bar"
     * </pre>
     */
    public Identifier getFlatName() {
        if (isQualified()) {
            return getName().getFlatName();
        }
        if (ipos > 0 && name.charAt(ipos-1) == '.') {
            if (ipos+1 == name.length()) {
                // last component is idNull
                return Identifier.lookup(name.substring(0,ipos-1));
            }
            String n = name.substring(ipos+1);
            String t = name.substring(0,ipos);
            return Identifier.lookup(t+n);
        }
        // Not inner.  Just return the same as getName()
        return this;
    }

    public Identifier getTopName() {
        if (!isInner())  return this;
        return Identifier.lookup(getQualifier(), getFlatName().getHead());
    }

    /**
     * Yet another way to slice qualified identifiers:
     * The head of an identifier is its first qualifier component,
     * and the tail is the rest of them.
     */
    public Identifier getHead() {
        Identifier id = this;
        while (id.isQualified())
            id = id.getQualifier();
        return id;
    }

    /**
     * @see getHead
     */
    public Identifier getTail() {
        Identifier id = getHead();
        if (id == this)
            return idNull;
        else
            return Identifier.lookup(name.substring(id.name.length() + 1));
    }

    // Unfortunately, the current structure of the compiler requires
    // that the resolveName() family of methods (which appear in
    // Environment.java, Context.java, and ClassDefinition.java) raise
    // no exceptions and emit no errors.  When we are in resolveName()
    // and we find a method that is ambiguous, we need to
    // unambiguously mark it as such, so that later stages of the
    // compiler realize that they should give an ambig.class rather than
    // a class.not.found error.  To mark it we add a special prefix
    // which cannot occur in the program source.  The routines below
    // are used to check, add, and remove this prefix.
    // (part of solution for 4059855).

    /**
     * A special prefix to add to ambiguous names.
     */
    private static final String ambigPrefix = "<<ambiguous>>";

    /**
     * Determine whether an Identifier has been marked as ambiguous.
     */
    public boolean hasAmbigPrefix() {
        return (name.startsWith(ambigPrefix));
    }

    /**
     * Add ambigPrefix to `this' to make a new Identifier marked as
     * ambiguous.  It is important that this new Identifier not refer
     * to an existing class.
     */
    public Identifier addAmbigPrefix() {
        return Identifier.lookup(ambigPrefix + name);
    }

    /**
     * Remove the ambigPrefix from `this' to get the original identifier.
     */
    public Identifier removeAmbigPrefix() {
        if (hasAmbigPrefix()) {
            return Identifier.lookup(name.substring(ambigPrefix.length()));
        } else {
            return this;
        }
    }
}
