/* **************************************************************************

  $Archive: /njcl_v2/src/com/novell/service/file/nw/naming/SchemaClassDef.java $
  $Revision: 11 $
  $Modtime: 2/22/00 5:16p $
 
  Copyright (c) 1998 Novell, Inc.  All Rights Reserved.

  THIS WORK IS  SUBJECT  TO  U.S.  AND  INTERNATIONAL  COPYRIGHT  LAWS  AND
  TREATIES.   NO  PART  OF  THIS  WORK MAY BE  USED,  PRACTICED,  PERFORMED
  COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,  ABRIDGED, CONDENSED,
  EXPANDED,  COLLECTED,  COMPILED,  LINKED,  RECAST, TRANSFORMED OR ADAPTED
  WITHOUT THE PRIOR WRITTEN CONSENT OF NOVELL, INC. ANY USE OR EXPLOITATION
  OF THIS WORK WITHOUT AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO
  CRIMINAL AND CIVIL LIABILITY.

****************************************************************************/

/*
   As you add attribute values (attribute IDs) do the following in this file:

      1. Go to the setNodesAttrIds method and add the new attribute ID string
         to the nodesAttrIds array under the appropriate dscontext.

      2. Go to the setNodesAttrIds method and add a new attribute
         Definition name string("* Definitions") to the attrDefNames array
         under the appropriate dscontext. These must be at the same index as
         their corrisponding attrids index in step 1.  (the name used in this
         step must be the same as the name used in SchemaAttrDef step 3)

      3. Go to SchemaAttrDef.java and do the list at the top of that file.

      If you are modifying this file for a different name space, do the
      following:

      1. Add your needed _CLASSDEF static final int assignments.  Prefix
         these variable names with the name of your source contexts, and keep
         sequential running values starting at 0.

      2. Go to the SchemaCDNCEnumerator class (bottom of file) and add
         names for your source dscontexts in the names data member.  The index
         of the array element that you place these in must be the same value
         as the _CLASSDEF value defined in step 1. (keep them in the same
         order).

      3. Go to the SchemaClassDef(DSContext) constructor and put in
         your checking for your dscontexts and calling setNodesAttrIds with
         the appropriate _CLASSDEF values defined in step 1.
*/

package com.novell.service.file.nw.naming;

import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Hashtable;

import javax.naming.*;
import javax.naming.Binding;
import javax.naming.NamingEnumeration;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.NameClassPair;
import javax.naming.NameNotFoundException;
import javax.naming.NameParser;
import javax.naming.NamingException;
import javax.naming.OperationNotSupportedException;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.AttributeModificationException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;

import com.novell.utility.naming.NamingEnumerator;

import com.novell.utility.naming.directory.NAttributes;

import com.novell.service.file.nw.calls.DirectoryEntryInfoImpl;
import com.novell.service.file.nw.calls.DirectorySpaceInfoImpl;
import com.novell.service.file.nw.calls.EAEnumeratorImpl;
//import com.novell.service.file.nw.calls.NSInfoEnumeratorImpl;
import com.novell.service.file.nw.calls.TrusteeEnumeratorImpl;
import com.novell.service.file.nw.calls.VolumeInfoImpl;
import com.novell.service.file.nw.calls.VolumeRestrictionEnumeratorImpl;
import com.novell.service.file.nw.calls.VolumeUtilizationImpl;
import com.novell.service.file.nw.calls.EffectiveRightsImpl;

/**@internal
 * This class is the class definition schema context for the file system
 * provider.  This means that the attributes of this context describe
 * or define how a particular file system context behaves, and what
 * attributes are available from the respective context.
 *
 * <p>This is the schema DirContext that is returned from all File
 * System contexts' getSchemaClassDefinition() method.
 *
 * <p>For example, on the class definition schema context that defines
 * VolumeDirContext, there is an attribute called "Valid Attribute ID List"
 * which contains multiple strings that specify the valid attribute IDs which
 * can be accessed from a VolumeDirContext.
 * </p>
 *
 * @see com.novell.service.file.nw.naming.DirEntryDirContext#c_getSchemaClassDefinition
 * @see com.novell.service.file.nw.naming.FileSystemInitialDirContext#c_getSchemaClassDefinition
 */
public class SchemaClassDef implements DirContext
{
   // DSContext types
   public static final int INITIAL_CLASSDEF     = 0;
   public static final int VOLDIR_CLASSDEF      = 1;
   public static final int DIRECTORY_CLASSDEF   = 2;
   public static final int FILE_CLASSDEF        = 3;

   public static final String INITIAL_DIRCONTEXT = "Initial";
   public static final String VOLUME_DIRCONTEXT = "Volume";
   public static final String DIRECTORY_DIRCONTEXT = "Directory";
   public static final String FILE_DIRCONTEXT = "File";

   private String[] nodesAttrIds = null;
   private String[] attrDefNames = null;
   private String[] implemented = null;
   private boolean staticSchemaTree = true;
   private int contextType = -1;

   private String distinguishedName;

   private FSEnvironment environment;

   // this constructor is called from Schema
   public SchemaClassDef(FSEnvironment environment)
   {
      this.environment = environment;
   }

   // this constructor is called from this module and Schema
   public SchemaClassDef(int dsContextType, FSEnvironment environment)
   {
      this(environment);

      this.staticSchemaTree = false;

      setNodesAttrIds(dsContextType);
   }

   /*
      This is the constructor that should be called from
      DSContext.getSchemaClassDef.  The caller should pass in "this"
      (himself) as the ctx parameter.
   */

   public SchemaClassDef(DirContext ctx, FSEnvironment environment)
   {
      this(environment);

      this.staticSchemaTree = false;

      if (ctx instanceof FileSystemInitialDirContext)
      {
         setNodesAttrIds(INITIAL_CLASSDEF);
         return;
      }

      if (ctx instanceof VolumeDirContext)
      {
         setNodesAttrIds(VOLDIR_CLASSDEF);
         return;
      }

      if (ctx instanceof DirectoryDirContext)
      {
         setNodesAttrIds(DIRECTORY_CLASSDEF);
         return;
      }

      if (ctx instanceof FileDirContext)
      {
         setNodesAttrIds(FILE_CLASSDEF);
         return;
      }
   }

   public int getContextType()
   {
      return contextType;
   }


   // ******************** Context Interface ********************

   /** @internal
    *
    */
   public String getNameInNamespace ()
      throws NamingException
   {
      return (distinguishedName);
   }

   public NamingEnumeration list(String name)
      throws NamingException
   {
      if (name == null || name.length() == 0)
      {
         NamingEnumeration rvalue = null;
         if (staticSchemaTree)
            rvalue = new SchemaCDNCEnumerator();
         else
            rvalue = new NamingEnumerator();
         return rvalue;
      }
      else
         return (NamingEnumeration)
            objectFromName(name, Schema.NCP_OBJECT);
   }

   public NamingEnumeration list(Name name)
      throws NamingException
   {
      return list(name.toString());
   }

   public NamingEnumeration listBindings(String name)
      throws NamingException
   {
      if (name == null || name.length() == 0)
      {
         NamingEnumeration rvalue = null;
         if (staticSchemaTree)
            rvalue = new SchemaCDBindingEnumerator(environment);
         else
            rvalue = new NamingEnumerator();
         return rvalue;
      }
      else
         return (NamingEnumeration)
            objectFromName(name, Schema.BINDING_OBJECT);
   }

   public NamingEnumeration listBindings(Name name)
      throws NamingException
   {
      return listBindings(name.toString());
   }

   public Object lookup(String name) throws NamingException
   {
      if (name == null || name.length() == 0)
         return this;

      return objectFromName(name, Schema.LOOKUP_OBJECT);
   }

   public Object lookup(Name name) throws NamingException
   {
      return lookup(name.toString());
   }

   public NameParser getNameParser(String name) throws
      NamingException
   {
      if (name == null || name.length() == 0)
         return new FileSystemNameParser(
                        environment.getServerName(), 
                        true);

      return (NameParser)
         objectFromName(name, Schema.NP_OBJECT);
   }

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

   public String composeName (
         String name,
         String prefix)
      throws NamingException
   {
      Name fullName;

      fullName = composeName(
                                 new CompositeName(name),
                                 new CompositeName(prefix));
      return fullName.toString();
   }

   public Name composeName (
         Name name,
         Name prefix)
      throws NamingException
   {
      Name res = (Name)prefix.clone();

      if (name == null)
      {
         return res;
      }
      res.addAll(name);

      return res;
   }

   public Hashtable getEnvironment()
      throws NamingException
   {
      return environment.getEnvironment(true);
   }

   public Object addToEnvironment(String propName, Object propVal)
      throws NamingException
   {
      return (environment.addToEnvironment(propName, propVal));
   }

   public Object removeFromEnvironment(String propName)
      throws NamingException
   {
      return (environment.removeFromEnvironment(propName));
   }

   /* methods that don't just throw an exception (but do nothing) */

   /* methods that just throw an exception */

   public void bind(String name, Object obj) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void bind(Name name, Object obj) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void rebind(String name, Object obj) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void rebind(Name name, Object obj) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void unbind(String name) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void unbind(Name name) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void rename(String oldName, String newName)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void rename(Name oldName, Name newName) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void destroySubcontext(String name) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void destroySubcontext(Name name) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public Context createSubcontext(String name) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public Context createSubcontext(Name name) 
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public Object lookupLink(String name) 
      throws NamingException
   {
      return (lookup (name));
   }

   public Object lookupLink(Name name) 
      throws NamingException
   {
      return (lookup (name));
   }

   public void close ()
      throws NamingException
   {
      // ... no close necessary
   }

/* **************************************************************************
*  DSContext implementation
****************************************************************************/

   /* methods that actually do something */

   public Attributes getAttributes(String name)
      throws NamingException
   {
      return getAttributes(name, null);
   }

   public Attributes getAttributes(Name name)
      throws NamingException
   {
      return getAttributes(name.toString(), null);
   }

   public Attributes getAttributes(String name, String[] attrIds)
      throws NamingException
   {
      if (name == null || name.length() == 0)
      {
         Attributes attrSet = new NAttributes(true);

         if (staticSchemaTree)
            return attrSet;         // there are no attributes at this level

         if (attrIds == null)
         {
            /* they want the whole list */
            if (nodesAttrIds != null)
            {
               BasicAttribute attr = new BasicAttribute(FSSchema.MANDATORY_ATTRIBUTE_IDS);
               for (int i=0; i < nodesAttrIds.length; i++)
                  attr.add(new String(nodesAttrIds[i]));
               attrSet.put(attr);

               for (int i=0; i < nodesAttrIds.length; i++)
               {
                  attr = new BasicAttribute(nodesAttrIds[i]);
                  attr.add(new String(attrDefNames[i]));
                  attrSet.put(attr);
               }
            }

            if (implemented != null)
            {
               BasicAttribute attr = new BasicAttribute(FSSchema.INTERFACES_IMPLEMENTED);
               for (int i=0; i < implemented.length; i++)
                  attr.add(new String(implemented[i]));
               attrSet.put(attr);
            }
         }else
         {
            /* find which ones they want */
            for (int i=0; i < attrIds.length; i++)
            {
               if (attrIds[i].equalsIgnoreCase(FSSchema.MANDATORY_ATTRIBUTE_IDS))
               {
                  BasicAttribute attr = new BasicAttribute(FSSchema.MANDATORY_ATTRIBUTE_IDS);
                  if (nodesAttrIds != null)
                  {
                     for (int j=0; j < nodesAttrIds.length; j++)
                        attr.add(new String(nodesAttrIds[j]));
                     attrSet.put(attr);
                  }
               }

               if (nodesAttrIds != null)
               {
                  for (int j=0; j < nodesAttrIds.length; j++)
                  {
                     if (attrIds[i].equalsIgnoreCase(nodesAttrIds[j]))
                     {
                        BasicAttribute attr = new BasicAttribute(nodesAttrIds[j]);
                        attr.add(new String(attrDefNames[j]));
                        attrSet.put(attr);
                        break;
                     }
                  }
               }

               if (attrIds[i].equalsIgnoreCase(FSSchema.INTERFACES_IMPLEMENTED))
               {
                  BasicAttribute attr = new BasicAttribute(FSSchema.INTERFACES_IMPLEMENTED);
                  if (implemented != null)
                  {
                     for (int j=0; j < implemented.length; j++)
                        attr.add(new String(implemented[j]));
                     attrSet.put(attr);
                  }
               }
            }
         }
         return attrSet;
      }
      else
         return (Attributes)objectFromName(name, Schema.AS_OBJECT);
   }

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

   /* methods that don't just throw an exception (but do nothing) */

   /* methods that just throw an exception */

   public void modifyAttributes(String name, int mod_op, Attributes attrs)
      throws NamingException
   {
      throw new AttributeModificationException();
   }

   public void modifyAttributes(Name name, int mod_op, Attributes attrs)
      throws NamingException
   {
      throw new AttributeModificationException();
   }

   public void modifyAttributes(String name, ModificationItem[] mods)
      throws NamingException
   {
      throw new AttributeModificationException();
   }

   public void modifyAttributes(Name name, ModificationItem[] mods)
      throws NamingException
   {
      throw new AttributeModificationException();
   }

   public void bind(String name, Object obj, Attributes attrs)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void bind(Name name, Object obj, Attributes attrs)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void rebind(String name, Object obj, Attributes attrs)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public void rebind(Name name, Object obj, Attributes attrs)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public DirContext createSubcontext(String name,
                     Attributes attrs)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public DirContext createSubcontext(Name name,
                     Attributes attrs)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   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();
   }

   /* *************** searches *************** */

   public NamingEnumeration search(
      String name,
      Attributes matchingAttributes)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public NamingEnumeration search(
      Name name,
      Attributes matchingAttributes)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public NamingEnumeration search(
      String name,
      Attributes matchingAttributes,
      String[] attributesToReturn)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public NamingEnumeration search(
      Name name,
      Attributes matchingAttributes,
      String[] attributesToReturn)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public NamingEnumeration search(
      String name,
      String filter,
      SearchControls cons)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public NamingEnumeration search(
      Name name,
      String filter,
      SearchControls cons)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public NamingEnumeration search(
      String name,
      String filterExpr,
      Object [] filterArgs,
      SearchControls cons)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

   public NamingEnumeration search(
      Name name,
      String filterExpr,
      Object [] filterArgs,
      SearchControls cons)
      throws NamingException
   {
      throw new OperationNotSupportedException();
   }

/* **************************************************************************
*  Helper methods
****************************************************************************/

   public static int typeFromName(String attrid)
   {
      for (int i = 0; i < SchemaCDNCEnumerator.names.length; i++)
      {
         if (SchemaCDNCEnumerator.names[i].equalsIgnoreCase(attrid))
            return i;
      }
      return -1;  // not a name that i know about
   }

   public static Object getEnumeration(int type, FSEnvironment environment)
      throws NamingException
   {
      if (type == Schema.NCP_OBJECT)
         return new SchemaCDNCEnumerator();
      if (type == Schema.BINDING_OBJECT)
         return new SchemaCDBindingEnumerator(environment);
      throw new InvalidNameException();
   }

   private Object objectFromName(String name, int returnType)
      throws NamingException
   {
      int type = typeFromName(name);
      if (type == -1)                        // no attrid of this name
         throw new NameNotFoundException();

      switch (returnType)
      {
         case Schema.NCP_OBJECT:     // name class pair enumeration
            return new NamingEnumerator();
         case Schema.BINDING_OBJECT: // binding enumeration
            return new NamingEnumerator();
         case Schema.LOOKUP_OBJECT:
         case Schema.AS_OBJECT:
            DirContext ctx = new SchemaClassDef(type, environment);

            if (returnType == Schema.LOOKUP_OBJECT)
               return ctx;
            return ctx.getAttributes("");
         case Schema.NP_OBJECT:     // nameparser
            return new FileSystemNameParser(
                           environment.getServerName(), 
                           true);
         default:
            throw new InvalidNameException();
      }
   }

   /**
    * Determine the type of node this should be
    *
    * <p>The SchemaClassDef class is used for a multi role.  First,
    * it is used as the 2nd layer of the static schema tree.  The
    * Schema class is the root of the tree, and one object of this
    * class named "Class Definitions" is, in effect, linked to to root.  This
    * second layer, "Class Definitions" object is of contextType staticSchemaTree.
    * it has no attributes associated with it, and the various methods will
    * watch for this staticSchemaTree contextType and act accordingly.
    * </p>
    * <p>Secondly, it is used as the 3rd layer, under the "Class Definitions"
    * node in the static schema tree.  This level will represent the actual
    * unique source DSContexts from the normal file system context tree.
    * The various _CLASSDEF values will be used in the class to determine
    * which set of attributes to work on.
    * </p>
    * <p>Thirdly, the various DSContexts that implement the getSchemaClassDef
    * methods will instantiate an object of this class to return to the user
    * application layer.  The constructor that takes a DSContext for a
    * parameter will be used for this purpose.
    * @param <i>type</i>             (in)The context type to setup
    *
    */

   private void setNodesAttrIds(int type)
   {
      /*
         The nodesAttrIds array is a list of all valid attribute ids of the
         source dscontext.

         The attrDefNames array is a list of the SchemaClassDef
         names that will be found at the 3rd level of the schema tree under
         attribute definitions.  The names in this array should corrispond
         (index to index) with the nodesAttrIds array.
      */

      contextType = type;
      switch (type)
      {
         case INITIAL_CLASSDEF:
            distinguishedName = FSSchema.CLASS_DEFINITIONS;
            implemented = new String[3];
            implemented[0] = "javax.naming.Context";
            implemented[1] = "javax.naming.Referenceable";
            implemented[2] = "javax.naming.directory.DirContext";
            break;

         case VOLDIR_CLASSDEF:
            distinguishedName = FSSchema.CLASS_DEFINITIONS + "/" + VOLUME_DIRCONTEXT;
            nodesAttrIds = new String[8];
            nodesAttrIds[0] = VolumeInfoImpl.ATTRIBUTE_ID;
            nodesAttrIds[1] = VolumeUtilizationImpl.ATTRIBUTE_ID;
            nodesAttrIds[2] = VolumeRestrictionEnumeratorImpl.ATTRIBUTE_ID;

            nodesAttrIds[3] = DirectorySpaceInfoImpl.ATTRIBUTE_ID;

            nodesAttrIds[4] = DirectoryEntryInfoImpl.ATTRIBUTE_ID;
            nodesAttrIds[5] = EAEnumeratorImpl.ATTRIBUTE_ID;
            nodesAttrIds[6] = TrusteeEnumeratorImpl.ATTRIBUTE_ID;
            nodesAttrIds[7] = EffectiveRightsImpl.ATTRIBUTE_ID;


            attrDefNames = new String[8];
            attrDefNames[0] = VolumeInfoImpl.SCHEMA_BINDING_NAME;
            attrDefNames[1] = VolumeUtilizationImpl.SCHEMA_BINDING_NAME;
            attrDefNames[2] = VolumeRestrictionEnumeratorImpl.SCHEMA_BINDING_NAME;

            attrDefNames[3] = DirectorySpaceInfoImpl.SCHEMA_BINDING_NAME;

            attrDefNames[4] = DirectoryEntryInfoImpl.SCHEMA_BINDING_NAME;
            attrDefNames[5] = EAEnumeratorImpl.SCHEMA_BINDING_NAME;
            attrDefNames[6] = TrusteeEnumeratorImpl.SCHEMA_BINDING_NAME;
            attrDefNames[7] = EffectiveRightsImpl.SCHEMA_BINDING_NAME;

            implemented = new String[8];
            implemented[0] = "javax.naming.Context";
            implemented[1] = "javax.naming.Referenceable";
            implemented[2] = "javax.naming.directory.DirContext";
            implemented[3] = "com.novell.java.io.DataAccessable";
            implemented[4] = "com.novell.java.io.NFile";
            implemented[5] = "com.novell.service.file.nw.NetwareVolume";
            implemented[6] = "com.novell.service.file.nw.NetwareDirectory";
            implemented[7] = "com.novell.service.file.nw.Netwarefile";
            break;

         case DIRECTORY_CLASSDEF:
            distinguishedName = FSSchema.CLASS_DEFINITIONS + "/" + DIRECTORY_DIRCONTEXT;
            nodesAttrIds = new String[5];
            nodesAttrIds[0] = DirectorySpaceInfoImpl.ATTRIBUTE_ID;

            nodesAttrIds[1] = DirectoryEntryInfoImpl.ATTRIBUTE_ID;
            nodesAttrIds[2] = EAEnumeratorImpl.ATTRIBUTE_ID;
            nodesAttrIds[3] = TrusteeEnumeratorImpl.ATTRIBUTE_ID;
            nodesAttrIds[4] = EffectiveRightsImpl.ATTRIBUTE_ID;

            attrDefNames = new String[5];
            attrDefNames[0] = DirectorySpaceInfoImpl.SCHEMA_BINDING_NAME;

            attrDefNames[1] = DirectoryEntryInfoImpl.SCHEMA_BINDING_NAME;
            attrDefNames[2] = EAEnumeratorImpl.SCHEMA_BINDING_NAME;
            attrDefNames[3] = TrusteeEnumeratorImpl.SCHEMA_BINDING_NAME;
            attrDefNames[4] = EffectiveRightsImpl.SCHEMA_BINDING_NAME;


            implemented = new String[7];
            implemented[0] = "javax.naming.Context";
            implemented[1] = "javax.naming.Referenceable";
            implemented[2] = "javax.naming.directory.DirContext";
            implemented[3] = "com.novell.java.io.DataAccessable";
            implemented[4] = "com.novell.java.io.NFile";
            implemented[5] = "com.novell.service.file.nw.NetwareDirectory";
            implemented[6] = "com.novell.service.file.nw.Netwarefile";
            break;

         case FILE_CLASSDEF:
            distinguishedName = FSSchema.CLASS_DEFINITIONS + "/" + FILE_DIRCONTEXT;
            nodesAttrIds = new String[4];
            nodesAttrIds[0] = DirectoryEntryInfoImpl.ATTRIBUTE_ID;
            nodesAttrIds[1] = EAEnumeratorImpl.ATTRIBUTE_ID;
            nodesAttrIds[2] = TrusteeEnumeratorImpl.ATTRIBUTE_ID;
            nodesAttrIds[3] = EffectiveRightsImpl.ATTRIBUTE_ID;

            attrDefNames = new String[4];
            attrDefNames[0] = DirectoryEntryInfoImpl.SCHEMA_BINDING_NAME;
            attrDefNames[1] = EAEnumeratorImpl.SCHEMA_BINDING_NAME;
            attrDefNames[2] = TrusteeEnumeratorImpl.SCHEMA_BINDING_NAME;
            attrDefNames[3] = EffectiveRightsImpl.SCHEMA_BINDING_NAME;

            implemented = new String[6];
            implemented[0] = "javax.naming.Context";
            implemented[1] = "javax.naming.Referenceable";
            implemented[2] = "javax.naming.directory.DirContext";
            implemented[3] = "com.novell.java.io.DataAccessable";
            implemented[4] = "com.novell.java.io.NFile";
            implemented[5] = "com.novell.service.file.nw.Netwarefile";
            break;
      }
   }
}

/* *************************************************************************/

class SchemaCDNCEnumerator implements NamingEnumeration
{
   private final String classDef =
         "com.novell.service.file.nw.naming.SchemaClassDef";

   public final static String[] names =
      {
         "Initial Context Definitions",
         "Volume Definitions",
         "Directory Definitions",
         "File Definitions"
      };

   private int index = 0;
   private boolean moreElements = true;

   public boolean hasMoreElements()
   {
      return moreElements;
   }

   public boolean hasMore()
      throws NamingException
   {
      return moreElements;
   }

   public Object nextElement()
   {
      try
      {
         return next();
      } catch (NamingException ne)
      {
         throw new RuntimeException(ne.getMessage());
      }
   }

   public Object next()
      throws NamingException
   {
      if (!moreElements)
         throw new NoSuchElementException();
      NameClassPair rvalue = new NameClassPair(names[index++], classDef, true);
      if (index >= names.length)
         moreElements = false;
      return rvalue;
   }

   /**
    *
    */
   public void close ()
      throws NamingException
   {
   }

}


/* *************************************************************************/

class SchemaCDBindingEnumerator implements NamingEnumeration
{
   private int index = 0;
   private boolean moreElements = true;
   private FSEnvironment environment;

   public SchemaCDBindingEnumerator(FSEnvironment environment)
   {
      this.environment = environment;
   }

   public boolean hasMoreElements()
   {
      return moreElements;
   }

   public boolean hasMore()
      throws NamingException
   {
      return moreElements;
   }

   public Object nextElement()
   {
      try
      {
         return next();
      } catch (NamingException ne)
      {
         throw new RuntimeException();
      }
   }

   public Object next()
      throws NamingException
   {
      if (!moreElements)
         throw new NoSuchElementException();

      Binding rvalue = new Binding(
                           SchemaCDNCEnumerator.names[index],
                           new SchemaClassDef(index++, environment),
                           true);

      if (index >= SchemaCDNCEnumerator.names.length)
         moreElements = false;
      return rvalue;
   }

   /**
    *
    */
   public void close ()
      throws NamingException
   {
   }

}


