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

  $Archive: /njcl_v2/src/com/novell/service/nds/naming/net/NetSchemaContainerDirContext.java $
  $Revision: 4 $
  $Modtime: 8/11/99 11:49a $
 
  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.

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

package com.novell.service.nds.naming.net;


import java.util.*;

import javax.naming.*;
import javax.naming.directory.*;

import  com.sun.jndi.toolkit.ctx.*;

import com.novell.service.nds.*;
import com.novell.service.nds.naming.*;


/** @internal
 * This class contains code common to NetAttributeDefinitionsDirContext,
 * NetClassDefinitionsDirContext and NetSyntaxDefinitionsDirContext
 * and is subclassed by each.
 */
public abstract class NetSchemaContainerDirContext
      extends NetSchemaDirContext
{
   /**
    * Constructor.
    *
    * @param objectName    Distinguished name of this object
    * @param baseClass     NDS class name
    * @param environment properties to be set in this objects environment
    */
   protected NetSchemaContainerDirContext (
         String objectName,
         String baseClass,
         NetEnvironment environment)
      throws NamingException
   {
      super (objectName, baseClass, environment);
   }

   /* ***********************************************************************
    * protected toolkit Context methods
    ************************************************************************/

   /**
    * Binds the existing object in obj to the specified name.
    * <p>This results in the creation of a new NDS Attribute or Class
    * Definition.
    * <p>The obj param must be of type NetAttributeDefinitionDirContext or
    * NetClassDefinitionDirContext.
    * <p>The name of the new class or attribute must be unique within the
    * Directory Schema attribute or class definitions.
    * <p>New names should be cleared through Developer Support
    * to guarantee uniqueness.
    */
   protected void schema_bind (
         String name,
         Object obj,
         Continuation cont)
      throws NamingException
   {
      // See if newName exists
      if (exists (name))
      {
         cont.setError (this, name);
         throw cont.fillInException (new NameAlreadyBoundException ());
      }

      Attributes attrs;

      if (! (obj instanceof SchemaAttribute) &&
          ! (obj instanceof SchemaClass))
      {
         // Wrong type to bind
         cont.setError (this, name);
         throw cont.fillInException (new NamingException ());
      }
      else
      {
         // Ensure expanded attributes flag is default
//         Properties p = new Properties ();
         String oldExpandedAttrs =
               environment.getClassAttributesLevelString ();

//         p.put (NdsEnvironment.CLASS_ATTRIBUTE_LEVEL,
//               NdsEnvironment.DEFAULT_DEFS);

//         environment.addToEnvironment (p);
         environment.addToEnvironment (
               NdsEnvironment.CLASS_ATTRIBUTE_LEVEL,
               NdsEnvironment.DEFAULT_DEFS);

         try
         {
            // Get attributes
            attrs = ((DirContext)obj).getAttributes ("", null);

            // re-set expanded attributes flag.
            environment.addToEnvironment (
                  NdsEnvironment.CLASS_ATTRIBUTE_LEVEL, oldExpandedAttrs);
         }
         catch (NamingException e)
         {
            // re-set expanded attributes flag.
            environment.addToEnvironment (
                  NdsEnvironment.CLASS_ATTRIBUTE_LEVEL, oldExpandedAttrs);

            cont.setError (this, name);
            throw cont.fillInException (e);
         }
      }

      schema_createSubcontext (name, attrs, cont);
   }

   /**
    *
    */
   protected void schema_rebind (
         String name,
         Object obj,
         Continuation cont)
      throws NamingException
   {
      // See if name currently exists
      if (exists (name))
      {
         // Name exists, remove binding.
         schema_unbind (name, cont);
      }
      // Bind new object
      schema_bind (name, obj, cont);
   }

   /**
    * Since there are no references bound at this level, the behavior
    * of unbind is identical to destroySubcontext
    */
   protected void schema_unbind (
         String name,
         Continuation cont)
      throws NamingException
   {
      schema_destroySubcontext (name, cont);
   }

   /**
    *
    */
   protected void schema_rename (
         String oldName,
         Name newName,
         Continuation cont)
      throws NamingException
   {
      // Bind to newName.  Must call p_bind because newName hasn't
      // been resolved yet.
      p_bind (newName, a_lookup (oldName, cont), cont);

      // Delete old binding
      schema_unbind (oldName, cont);
   }

   /**
    * Since attributes are an integral part of an Attribute/Class Definition,
    * this is not supported.
    */
   protected Context schema_createSubcontext (
         String name,
         Continuation cont)
      throws NamingException
   {
      cont.setError (this, name);
      throw cont.fillInException (new OperationNotSupportedException ());
   }

   /* ***********************************************************************
    * protected toolkit DirContext methods
    ************************************************************************/

   /**
    * No attributes at this level, not supported
    */
   protected void schema_modifyAttributes (
         int mod_op,
         Attributes attrs,
         Continuation cont)
      throws NamingException
   {
      cont.setError (this, "");
      throw cont.fillInException (new OperationNotSupportedException ());
   }

   /**
    * No attributes at this level, not supported
    */
   protected void schema_modifyAttributes (
         ModificationItem[] mods,
         Continuation cont)
      throws NamingException
   {
      cont.setError (this, "");
      throw cont.fillInException (new OperationNotSupportedException ());
   }

   /**
    * If attrs is null, schema_bind is called, otherwise,
    * schema_createSubcontext is called with the incoming attribute set
    *
    * @see schema_bind
    * @see schema_createSubcontext
    */
   protected void schema_bind (
         String name,
         Object obj,
         Attributes attrs,
         Continuation cont)
      throws NamingException
   {
      if (null == attrs)
      {
         // Bind as is, using attributes in obj
         schema_bind (name, obj, cont);
      }
      else
      {
         // Create new binding using specified attributes
         schema_createSubcontext (name, attrs, cont);
      }
   }

   /**
    *
    */
   protected void schema_rebind (
         String name,
         Object obj,
         Attributes attrs,
         Continuation cont)
      throws NamingException
   {
      if (null == attrs)
      {
         Attributes as;

         // Ensure expanded attributes flag is false
//         Properties p = new Properties ();
         String oldExpandedAttrs =
               environment.getClassAttributesLevelString ();

//         p.put (NdsEnvironment.CLASS_ATTRIBUTE_LEVEL,
//               NdsEnvironment.DEFAULT_DEFS);

//         environment.addToEnvironment (p);

          environment.addToEnvironment (
               NdsEnvironment.CLASS_ATTRIBUTE_LEVEL,
               NdsEnvironment.DEFAULT_DEFS);

         try
         {
            // Get attributes
            as = getAttributes (name);

            // re-set expanded attributes flag.
            environment.addToEnvironment (
                  NdsEnvironment.CLASS_ATTRIBUTE_LEVEL, oldExpandedAttrs);
         }
         catch (NamingException e)
         {
            // re-set expanded attributes flag.
            environment.addToEnvironment (
                  NdsEnvironment.CLASS_ATTRIBUTE_LEVEL, oldExpandedAttrs);

            cont.setError (this, name);
            throw cont.fillInException (e);
         }

         if (exists (name) && null != as)
         {
            // Re-call with attribute set from existing binding
            schema_rebind (name, obj, as, cont);
         }
         else
         {
            // Either 'name' doesn't exists as a binding or its object
            // has no attributes, call rebind to use attributes from obj
            schema_rebind (name, obj, cont);
         }
      }
      else
      {
         if (exists (name))
         {
            schema_unbind (name, cont);
         }
         // Create binding using specified attributes
         schema_createSubcontext (name, attrs, cont);
      }
   }

   /* ***********************************************************************
    * Utility methods
    ************************************************************************/

   /**
    * Returns a hashtable of attribute id's / attributes.
    * This is called by NetSchemaDirContext.a_getAttributes
    */
   protected Hashtable getAttrItems ()
         throws NamingException
   {
      // Containers have no attributes as of yet.  Return empty table
      Hashtable ret = new Hashtable ();
      return ret;
   }

   /* ***********************************************************************
    * Abstract methods
    ************************************************************************/

   /**
    * Returns true if the named class/attr def exists
    * This is called by various create/delete/bind type methods.
    */
   protected abstract boolean exists (String name);


} /* NetSchemaContainerDirContext */
