/*
 * Copyright 1999-2002 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 com.sun.jndi.toolkit.dir;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.spi.*;
import java.util.*;

/**
 * A sample service provider that implements a hierarchical directory in memory.
 * Every operation begins by doing a lookup on the name passed to it and then
 * calls a corresponding "do<OperationName>" on the result of the lookup. The
 * "do<OperationName>" does the work without any further resolution (it assumes
 * that it is the target context).
 */

public class HierMemDirCtx implements DirContext {

    static private final boolean debug = false;
    private static final NameParser defaultParser = new HierarchicalNameParser();

    protected Hashtable myEnv;
    protected Hashtable bindings;
    protected Attributes attrs;
    protected boolean ignoreCase = false;
    protected NamingException readOnlyEx = null;
    protected NameParser myParser = defaultParser;

    private boolean alwaysUseFactory;

    public void close() throws NamingException {
        myEnv = null;
        bindings = null;
        attrs = null;
    }

    public String getNameInNamespace() throws NamingException {
        throw new OperationNotSupportedException(
            "Cannot determine full name");
    }

    public HierMemDirCtx() {
        this(null, false, false);
    }

    public HierMemDirCtx(boolean ignoreCase) {
        this(null, ignoreCase, false);
    }

    public HierMemDirCtx(Hashtable environment, boolean ignoreCase) {
        this(environment, ignoreCase, false);
    }

    protected HierMemDirCtx(Hashtable environment, boolean ignoreCase,
        boolean useFac) {
        myEnv = environment;
        this.ignoreCase = ignoreCase;
        init();
        this.alwaysUseFactory = useFac;
    }

    private void init() {
        attrs = new BasicAttributes(ignoreCase);
        bindings = new Hashtable(11, 0.75f);
    }

    public Object lookup(String name) throws NamingException {
        return lookup(myParser.parse(name));
    }

    public Object lookup(Name name) throws NamingException {
        return doLookup(name, alwaysUseFactory);
    }

    public Object doLookup(Name name, boolean useFactory)
        throws NamingException {

        Object target = null;
        name = canonizeName(name);

        switch(name.size()) {
        case 0:
            // name is empty, caller wants this object
            target = this;
            break;

        case 1:
            // name is atomic, caller wants one of this object's bindings
            target = bindings.get(name);
            break;

        default:
            // name is compound, delegate to child context
            HierMemDirCtx ctx = (HierMemDirCtx)bindings.get(name.getPrefix(1));
            if(ctx == null) {
                target = null;
            } else {
                target = ctx.doLookup(name.getSuffix(1), false);
            }
            break;
        }

        if(target == null) {
            throw new NameNotFoundException(name.toString());
        }

        if (useFactory) {
            try {
                return DirectoryManager.getObjectInstance(target,
                    name, this, myEnv,
                    (target instanceof HierMemDirCtx) ?
                    ((HierMemDirCtx)target).attrs : null);
            } catch (NamingException e) {
                throw e;
            } catch (Exception e) {
                NamingException e2 = new NamingException(
                    "Problem calling getObjectInstance");
                e2.setRootCause(e);
                throw e2;
            }
        } else {
            return target;
        }
    }

    public void bind(String name, Object obj) throws NamingException {
        bind(myParser.parse(name), obj);
    }

    public void bind(Name name, Object obj) throws NamingException {
        doBind(name, obj, null, alwaysUseFactory);
    }

    public void bind(String name, Object obj, Attributes attrs)
            throws NamingException {
        bind(myParser.parse(name), obj, attrs);
    }

    public void bind(Name name, Object obj, Attributes attrs)
            throws NamingException {
        doBind(name, obj, attrs, alwaysUseFactory);
    }

    protected void doBind(Name name, Object obj, Attributes attrs,
        boolean useFactory) throws NamingException {
        if (name.isEmpty()) {
            throw new InvalidNameException("Cannot bind empty name");
        }

        if (useFactory) {
            DirStateFactory.Result res = DirectoryManager.getStateToBind(
                obj, name, this, myEnv, attrs);
            obj = res.getObject();
            attrs = res.getAttributes();
        }

        HierMemDirCtx ctx= (HierMemDirCtx) doLookup(getInternalName(name), false);
        ctx.doBindAux(getLeafName(name), obj);

        if (attrs != null && attrs.size() > 0) {
            modifyAttributes(name, ADD_ATTRIBUTE, attrs);
        }
    }

    protected void doBindAux(Name name, Object obj) throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        if (bindings.get(name) != null) {
            throw new NameAlreadyBoundException(name.toString());
        }
        if(obj instanceof HierMemDirCtx) {
            bindings.put(name, obj);
        } else {
            throw new SchemaViolationException(
                "This context only supports binding objects of it's own kind");
        }
    }

    public void rebind(String name, Object obj) throws NamingException {
        rebind(myParser.parse(name), obj);
    }

    public void rebind(Name name, Object obj) throws NamingException {
        doRebind(name, obj, null, alwaysUseFactory);
    }

    public void rebind(String name, Object obj, Attributes attrs)
            throws NamingException {
        rebind(myParser.parse(name), obj, attrs);
    }

    public void rebind(Name name, Object obj, Attributes attrs)
            throws NamingException {
        doRebind(name, obj, attrs, alwaysUseFactory);
    }

    protected void doRebind(Name name, Object obj, Attributes attrs,
        boolean useFactory) throws NamingException {
        if (name.isEmpty()) {
            throw new InvalidNameException("Cannot rebind empty name");
        }

        if (useFactory) {
            DirStateFactory.Result res = DirectoryManager.getStateToBind(
                obj, name, this, myEnv, attrs);
            obj = res.getObject();
            attrs = res.getAttributes();
        }

        HierMemDirCtx ctx= (HierMemDirCtx) doLookup(getInternalName(name), false);
        ctx.doRebindAux(getLeafName(name), obj);

        //
        // attrs == null -> use attrs from obj
        // attrs != null -> use attrs
        //
        // %%% Strictly speaking, when attrs is non-null, we should
        // take the explicit step of removing obj's attrs.
        // We don't do that currently.

        if (attrs != null && attrs.size() > 0) {
            modifyAttributes(name, ADD_ATTRIBUTE, attrs);
        }
    }

    protected void doRebindAux(Name name, Object obj) throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }
        if(obj instanceof HierMemDirCtx) {
            bindings.put(name, obj);

        } else {
            throw new SchemaViolationException(
                "This context only supports binding objects of it's own kind");
        }
    }

    public void unbind(String name) throws NamingException {
        unbind(myParser.parse(name));
    }

    public void unbind(Name name) throws NamingException {
        if (name.isEmpty()) {
            throw new InvalidNameException("Cannot unbind empty name");
        } else {
            HierMemDirCtx ctx=
                (HierMemDirCtx) doLookup(getInternalName(name), false);
            ctx.doUnbind(getLeafName(name));
        }
    }

    protected void doUnbind(Name name) throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        bindings.remove(name);  // attrs will also be removed along with ctx
    }

    public void rename(String oldname, String newname)
            throws NamingException {
         rename(myParser.parse(oldname), myParser.parse(newname));
    }

    public void rename(Name oldname, Name newname)
            throws NamingException {

        if(newname.isEmpty() || oldname.isEmpty()) {
            throw new InvalidNameException("Cannot rename empty name");
        }

        if (!getInternalName(newname).equals(getInternalName(oldname))) {
            throw new InvalidNameException("Cannot rename across contexts");
        }

        HierMemDirCtx ctx =
            (HierMemDirCtx) doLookup(getInternalName(newname), false);
        ctx.doRename(getLeafName(oldname), getLeafName(newname));
    }

    protected void doRename(Name oldname, Name newname) throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        oldname = canonizeName(oldname);
        newname = canonizeName(newname);

        // Check if new name exists
        if (bindings.get(newname) != null) {
            throw new NameAlreadyBoundException(newname.toString());
        }

        // Check if old name is bound
        Object oldBinding = bindings.remove(oldname);
        if (oldBinding == null) {
            throw new NameNotFoundException(oldname.toString());
        }

        bindings.put(newname, oldBinding);
    }

    public NamingEnumeration list(String name) throws NamingException {
        return list(myParser.parse(name));
    }

    public NamingEnumeration list(Name name) throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false);
        return ctx.doList();
    }

    protected NamingEnumeration doList () throws NamingException {
        return new FlatNames(bindings.keys());
    }


    public NamingEnumeration listBindings(String name) throws NamingException {
        return listBindings(myParser.parse(name));
    }

    public NamingEnumeration listBindings(Name name) throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx)doLookup(name, false);
        return ctx.doListBindings(alwaysUseFactory);
    }

    protected NamingEnumeration doListBindings(boolean useFactory)
        throws NamingException {
        return new FlatBindings(bindings, myEnv, useFactory);
    }

    public void destroySubcontext(String name) throws NamingException {
        destroySubcontext(myParser.parse(name));
    }

    public void destroySubcontext(Name name) throws NamingException {
        HierMemDirCtx ctx =
            (HierMemDirCtx) doLookup(getInternalName(name), false);
        ctx.doDestroySubcontext(getLeafName(name));
    }

    protected void doDestroySubcontext(Name name) throws NamingException {

        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }
        name = canonizeName(name);
        bindings.remove(name);
    }

    public Context createSubcontext(String name) throws NamingException {
        return createSubcontext(myParser.parse(name));
    }

    public Context createSubcontext(Name name) throws NamingException {
        return createSubcontext(name, null);
    }

    public DirContext createSubcontext(String name, Attributes attrs)
            throws NamingException {
        return createSubcontext(myParser.parse(name), attrs);
    }

    public DirContext createSubcontext(Name name, Attributes attrs)
            throws NamingException {
        HierMemDirCtx ctx =
            (HierMemDirCtx) doLookup(getInternalName(name), false);
        return ctx.doCreateSubcontext(getLeafName(name), attrs);
    }

    protected DirContext doCreateSubcontext(Name name, Attributes attrs)
        throws NamingException {
        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        name = canonizeName(name);

        if (bindings.get(name) != null) {
            throw new NameAlreadyBoundException(name.toString());
        }
        HierMemDirCtx newCtx = createNewCtx();
        bindings.put(name, newCtx);
        if(attrs != null) {
            newCtx.modifyAttributes("", ADD_ATTRIBUTE, attrs);
        }
        return newCtx;
    }


    public Object lookupLink(String name) throws NamingException {
        // This context does not treat links specially
        return lookupLink(myParser.parse(name));
    }

    public Object lookupLink(Name name) throws NamingException {
        // Flat namespace; no federation; just call string version
        return lookup(name);
    }

    public NameParser getNameParser(String name) throws NamingException {
        return myParser;
    }

    public NameParser getNameParser(Name name) throws NamingException {
        return myParser;
    }

    public String composeName(String name, String prefix)
            throws NamingException {
        Name result = composeName(new CompositeName(name),
                                  new CompositeName(prefix));
        return result.toString();
    }

    public Name composeName(Name name, Name prefix)
            throws NamingException {
        name = canonizeName(name);
        prefix = canonizeName(prefix);
        Name result = (Name)(prefix.clone());
        result.addAll(name);
        return result;
    }

    public Object addToEnvironment(String propName, Object propVal)
            throws NamingException {
        myEnv = (myEnv == null) ?
            new Hashtable(11, 0.75f) : (Hashtable)myEnv.clone();

        return myEnv.put(propName, propVal);
    }

    public Object removeFromEnvironment(String propName)
            throws NamingException {
        if (myEnv == null)
            return null;

        myEnv = (Hashtable)myEnv.clone();
        return myEnv.remove(propName);
    }

    public Hashtable getEnvironment() throws NamingException {
        if (myEnv == null) {
            return new Hashtable(5, 0.75f);
        } else {
            return (Hashtable)myEnv.clone();
        }
    }

    public Attributes getAttributes(String name)
       throws NamingException {
       return getAttributes(myParser.parse(name));
    }

    public Attributes getAttributes(Name name)
        throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false);
        return ctx.doGetAttributes();
    }

    protected Attributes doGetAttributes() throws NamingException {
        return (Attributes)attrs.clone();
    }

    public Attributes getAttributes(String name, String[] attrIds)
        throws NamingException {
        return getAttributes(myParser.parse(name), attrIds);
    }

    public Attributes getAttributes(Name name, String[] attrIds)
        throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false);
        return ctx.doGetAttributes(attrIds);
    }

    protected Attributes doGetAttributes(String[] attrIds)
        throws NamingException {

        if (attrIds == null) {
            return doGetAttributes();
        }
        Attributes attrs = new BasicAttributes(ignoreCase);
        Attribute attr = null;
            for(int i=0; i<attrIds.length; i++) {
                attr = this.attrs.get(attrIds[i]);
                if (attr != null) {
                    attrs.put(attr);
                }
            }
        return attrs;
    }

    public void modifyAttributes(String name, int mod_op, Attributes attrs)
        throws NamingException   {
        modifyAttributes(myParser.parse(name), mod_op, attrs);
    }

    public void modifyAttributes(Name name, int mod_op, Attributes attrs)
        throws NamingException {

        if (attrs == null || attrs.size() == 0) {
            throw new IllegalArgumentException(
                "Cannot modify without an attribute");
        }

        // turn it into a modification Enumeration and pass it on
        NamingEnumeration attrEnum = attrs.getAll();
        ModificationItem[] mods = new ModificationItem[attrs.size()];
        for (int i = 0; i < mods.length && attrEnum.hasMoreElements(); i++) {
            mods[i] = new ModificationItem(mod_op, (Attribute)attrEnum.next());
        }

        modifyAttributes(name, mods);
    }

    public void modifyAttributes(String name, ModificationItem[] mods)
        throws NamingException   {
        modifyAttributes(myParser.parse(name), mods);
    }

    public void modifyAttributes(Name name, ModificationItem[] mods)
        throws NamingException {
        HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false);
        ctx.doModifyAttributes(mods);
    }

    protected void doModifyAttributes(ModificationItem[] mods)
        throws NamingException {

        if (readOnlyEx != null) {
            throw (NamingException) readOnlyEx.fillInStackTrace();
        }

        applyMods(mods, attrs);
    }

    protected static Attributes applyMods(ModificationItem[] mods,
        Attributes orig) throws NamingException {

        ModificationItem mod;
        Attribute existingAttr, modAttr;
        NamingEnumeration modVals;

        for (int i = 0; i < mods.length; i++) {
            mod = mods[i];
            modAttr = mod.getAttribute();

            switch(mod.getModificationOp()) {
            case ADD_ATTRIBUTE:
                if (debug) {
                    System.out.println("HierMemDSCtx: adding " +
                                       mod.getAttribute().toString());
                }
                existingAttr = orig.get(modAttr.getID());
                if (existingAttr == null) {
                    orig.put((Attribute)modAttr.clone());
                } else {
                    // Add new attribute values to existing attribute
                    modVals = modAttr.getAll();
                    while (modVals.hasMore()) {
                        existingAttr.add(modVals.next());
                    }
                }
                break;
            case REPLACE_ATTRIBUTE:
                if (modAttr.size() == 0) {
                    orig.remove(modAttr.getID());
                } else {
                    orig.put((Attribute)modAttr.clone());
                }
                break;
            case REMOVE_ATTRIBUTE:
                existingAttr = orig.get(modAttr.getID());
                if (existingAttr != null) {
                    if (modAttr.size() == 0) {
                        orig.remove(modAttr.getID());
                    } else {
                        // Remove attribute values from existing attribute
                        modVals = modAttr.getAll();
                        while (modVals.hasMore()) {
                            existingAttr.remove(modVals.next());
                        }
                        if (existingAttr.size() == 0) {
                            orig.remove(modAttr.getID());
                        }
                    }
                }
                break;
            default:
                throw new AttributeModificationException("Unknown mod_op");
            }
        }

        return orig;
    }

    public NamingEnumeration search(String name,
                                    Attributes matchingAttributes)
        throws NamingException {
        return search(name, matchingAttributes, null);
    }

    public NamingEnumeration search(Name name,
                                    Attributes matchingAttributes)
        throws NamingException {
            return search(name, matchingAttributes, null);
    }

     public NamingEnumeration search(String name,
                                    Attributes matchingAttributes,
                                    String[] attributesToReturn)
        throws NamingException {
        return search(myParser.parse(name), matchingAttributes,
            attributesToReturn);
    }

     public NamingEnumeration search(Name name,
                                    Attributes matchingAttributes,
                                    String[] attributesToReturn)
         throws NamingException {

        HierMemDirCtx target = (HierMemDirCtx) doLookup(name, false);

        SearchControls cons = new SearchControls();
        cons.setReturningAttributes(attributesToReturn);

        return new LazySearchEnumerationImpl(
            target.doListBindings(false),
            new ContainmentFilter(matchingAttributes),
            cons, this, myEnv,
            false); // alwaysUseFactory ignored because objReturnFlag == false
    }

    public NamingEnumeration search(Name name,
                                    String filter,
                                    SearchControls cons)
        throws NamingException {
        DirContext target = (DirContext) doLookup(name, false);

        SearchFilter stringfilter = new SearchFilter(filter);
        return new LazySearchEnumerationImpl(
            new HierContextEnumerator(target,
                (cons != null) ? cons.getSearchScope() :
                SearchControls.ONELEVEL_SCOPE),
            stringfilter,
            cons, this, myEnv, alwaysUseFactory);
    }

     public NamingEnumeration search(Name name,
                                    String filterExpr,
                                    Object[] filterArgs,
                                    SearchControls cons)
            throws NamingException {

        String strfilter = SearchFilter.format(filterExpr, filterArgs);
        return search(name, strfilter, cons);
    }

    public NamingEnumeration search(String name,
                                    String filter,
                                    SearchControls cons)
        throws NamingException {
        return search(myParser.parse(name), filter, cons);
    }

    public NamingEnumeration search(String name,
                                    String filterExpr,
                                    Object[] filterArgs,
                                    SearchControls cons)
            throws NamingException {
        return search(myParser.parse(name), filterExpr, filterArgs, cons);
    }

    // This function is called whenever a new object needs to be created.
    // this is used so that if anyone subclasses us, they can override this
    // and return object of their own kind.
    protected HierMemDirCtx createNewCtx() throws NamingException {
        return new HierMemDirCtx(myEnv, ignoreCase);
    }

    // If the supplied name is a composite name, return the name that
    // is its first component.
    protected Name canonizeName(Name name) throws NamingException {
        Name canonicalName = name;

        if(!(name instanceof HierarchicalName)) {
            // If name is not of the correct type, make copy
            canonicalName = new HierarchicalName();
            int n = name.size();
            for(int i = 0; i < n; i++) {
                canonicalName.add(i, name.get(i));
            }
        }

        return canonicalName;
    }

     protected Name getInternalName(Name name) throws NamingException {
         return (name.getPrefix(name.size() - 1));
     }

     protected Name getLeafName(Name name) throws NamingException {
         return (name.getSuffix(name.size() - 1));
     }


     public DirContext getSchema(String name) throws NamingException {
        throw new OperationNotSupportedException();
    }

     public DirContext getSchema(Name name) throws NamingException {
        throw new OperationNotSupportedException();
    }

     public DirContext getSchemaClassDefinition(String name)
        throws NamingException {
        throw new OperationNotSupportedException();
    }

    public DirContext getSchemaClassDefinition(Name name)
            throws NamingException {
        throw new OperationNotSupportedException();
    }

    // Set context in readonly mode; throw e when update operation attempted.
    public void setReadOnly(NamingException e) {
        readOnlyEx = e;
    }

    // Set context to support case-insensitive names
    public void setIgnoreCase(boolean ignoreCase) {
        this.ignoreCase = ignoreCase;
    }

    public void setNameParser(NameParser parser) {
        myParser = parser;
    }

    // Class for enumerating name/class pairs
    private class FlatNames implements NamingEnumeration {
        Enumeration names;

        FlatNames (Enumeration names) {
            this.names = names;
        }

        public boolean hasMoreElements() {
            try {
                return hasMore();
            } catch (NamingException e) {
                return false;
            }
        }

        public boolean hasMore() throws NamingException {
            return names.hasMoreElements();
        }

        public Object nextElement() {
            try {
                return next();
            } catch (NamingException e) {
                throw new NoSuchElementException(e.toString());
            }
        }

        public Object next() throws NamingException {
            Name name = (Name)names.nextElement();
            String className = bindings.get(name).getClass().getName();
            return new NameClassPair(name.toString(), className);
        }

        public void close() {
            names = null;
        }
    }

   // Class for enumerating bindings
    private final class FlatBindings extends FlatNames {
        private Hashtable bds;
        private Hashtable env;
        private boolean useFactory;

        FlatBindings(Hashtable bindings, Hashtable env, boolean useFactory) {
            super(bindings.keys());
            this.env = env;
            this.bds = bindings;
            this.useFactory = useFactory;
        }

        public Object next() throws NamingException {
            Name name = (Name)names.nextElement();

            HierMemDirCtx obj = (HierMemDirCtx)bds.get(name);

            Object answer = obj;
            if (useFactory) {
                Attributes attrs = obj.getAttributes(""); // only method available
                try {
                    answer = DirectoryManager.getObjectInstance(obj,
                        name, HierMemDirCtx.this, env, attrs);
                } catch (NamingException e) {
                    throw e;
                } catch (Exception e) {
                    NamingException e2 = new NamingException(
                        "Problem calling getObjectInstance");
                    e2.setRootCause(e);
                    throw e2;
                }
            }

            return new Binding(name.toString(), answer);
        }
    }

    public class HierContextEnumerator extends ContextEnumerator {
        public HierContextEnumerator(Context context, int scope)
            throws NamingException {
                super(context, scope);
        }

        protected HierContextEnumerator(Context context, int scope,
            String contextName, boolean returnSelf) throws NamingException {
            super(context, scope, contextName, returnSelf);
        }

        protected NamingEnumeration getImmediateChildren(Context ctx)
            throws NamingException {
                return ((HierMemDirCtx)ctx).doListBindings(false);
        }

        protected ContextEnumerator newEnumerator(Context ctx, int scope,
            String contextName, boolean returnSelf) throws NamingException {
                return new HierContextEnumerator(ctx, scope, contextName,
                    returnSelf);
        }
    }
}

    // CompundNames's HashCode() method isn't good enough for many string.
    // The only prupose of this subclass is to have a more discerning
    // hash function. We'll make up for the performance hit by caching
    // the hash value.

final class HierarchicalName extends CompoundName {
    private int hashValue = -1;

    // Creates an empty name
    HierarchicalName() {
        super(new Enumeration() {
            public boolean hasMoreElements() {return false;}
            public Object nextElement() {throw new NoSuchElementException();}
        },
            HierarchicalNameParser.mySyntax);
    }

    HierarchicalName(Enumeration comps, Properties syntax) {
        super(comps, syntax);
    }

    HierarchicalName(String n, Properties syntax) throws InvalidNameException {
        super(n, syntax);
    }

    // just like String.hashCode, only it pays no attention to length
    public int hashCode() {
        if (hashValue == -1) {

            String name = toString().toUpperCase();
            int len = name.length();
            int off = 0;
            char val[] = new char[len];

            name.getChars(0, len, val, 0);

            for (int i = len; i > 0; i--) {
                hashValue = (hashValue * 37) + val[off++];
            }
        }

        return hashValue;
    }

    public Name getPrefix(int posn) {
        Enumeration comps = super.getPrefix(posn).getAll();
        return (new HierarchicalName(comps, mySyntax));
    }

    public Name getSuffix(int posn) {
        Enumeration comps = super.getSuffix(posn).getAll();
        return (new HierarchicalName(comps, mySyntax));
    }

    public Object clone() {
        return (new HierarchicalName(getAll(), mySyntax));
    }

    private static final long serialVersionUID = -6717336834584573168L;
}

// This is the default name parser (used if setNameParser is not called)
final class HierarchicalNameParser implements NameParser {
    static final Properties mySyntax = new Properties();
    static {
        mySyntax.put("jndi.syntax.direction", "left_to_right");
        mySyntax.put("jndi.syntax.separator", "/");
        mySyntax.put("jndi.syntax.ignorecase", "true");
        mySyntax.put("jndi.syntax.escape", "\\");
        mySyntax.put("jndi.syntax.beginquote", "\"");
        //mySyntax.put("jndi.syntax.separator.ava", "+");
        //mySyntax.put("jndi.syntax.separator.typeval", "=");
        mySyntax.put("jndi.syntax.trimblanks", "false");
    };

    public Name parse(String name) throws NamingException {
        return new HierarchicalName(name, mySyntax);
    }
}
