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

  $Archive: /njcl_v2rmi/src/com/novell/service/nds/naming/net/NetClassDefinitionDirContext.java $
  $Revision: 14 $
  $Modtime: 1/05/01 3:59p $
 
  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.NdsClassDefinition;
import com.novell.service.nds.NdsClassDefinitionInfo;
import com.novell.service.nds.naming.*;

import com.novell.service.jncp.NSIException;
import com.novell.service.jncpv2r.net.*;

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


/** @internal
 * Represents a single NSD Class Definition.
 * <p> Attributes include:
 * <p> Object Super Classes
 * <p> Object Containment Classes
 * <p> Object Naming Attributes
 * <p> Object Mandatory Attributes
 * <p> Object Optional Attributes
 * <p> ASN1Name
 * <p> Flags (this may contain one or more of the following)
 * <p>
 * <p>SchemaClassDirContext.DS_CONTAINER_CLASS
 * <p>SchemaClassDirContext.DS_EFFECTIVE_CLASS
 * <p>SchemaClassDirContext.DS_NONREMOVABLE_CLASS
 * <p>SchemaClassDirContext.DS_AMBIGUOUS_NAMING
 * <p>SchemaClassDirContext.DS_AMBIGUOUS_CONTAINMENT
 */
public class NetClassDefinitionDirContext
   extends NetSchemaDefinitionDirContext
   implements NdsClassDefinition, SchemaClass
{
   /**
    *
    */
   private NetClassInfo classInfo;


   /**
    * Constructor.
    *
    * @param objectName    Distinguished name of this object
    * @param classInfo     Class information (attributes)
    * @param environment properties to be set in this objects environment
    *
   protected NetClassDefinitionDirContext (
         String objectName,
         String baseClass,
         NetEnvironment environment)
      throws NamingException
   {
      super (objectName, baseClass, environment);

   } *  */

   /**
    * Constructor.
    *
    * @param objectName    Distinguished name of this object
    * @param info          NetClassDefinitionRawAttributeInfo
    * @param environment properties to be set in this objects environment
    */
   protected NetClassDefinitionDirContext (
         String objectName,
         NetClassInfo classInfo,
         NetEnvironment environment)
      throws NamingException
   {
      super (objectName, Schema.SCHEMA_CLASS, environment);

      this.classInfo = classInfo;
   }

   /* ***********************************************************************
    * protected Toolkit DirContext methods
    ************************************************************************/

   /**
    *
    */
   protected Attributes c_getAttributes (
         Name name,
         String[] attrIds,
         Continuation cont) 
      throws NamingException
   {
      if (!name.isEmpty ())
      {
         cont.setError (this, name);
         throw (cont.fillInException (new InvalidNameException ()));
      }

      Attributes result;

      if (null == attrIds)
      {
         result = getAttributes ();
      }
      else
      {
         Attributes attributes = getAttributes ();
         Attribute attribute;

         result = new NAttributes (true);

         for (int i = 0; i < attrIds.length; i++)
         {
            if ((attribute = attributes.get (attrIds[i])) != null)
            {
               result.put (attribute);
            }
         }
      }
      return (result);

   } /* c_getAttributes () */

   /**
    * Currently, the only modifications clients can make to existing
    * class definitions is the addition of Object Optional Attributes.
    * No other characteristic of the object-class definition can be changed.
    *
    */
   protected void schema_modifyAttributes (
         int mod_op,
         Attributes attrs,
         Continuation cont)
      throws NamingException
   {
      NamingEnumeration ae = attrs.getAll ();
      Attribute attr = null;
      NamingException ne = null;
      boolean failed = false;

      if (ae == null)
      {
         // No attributes to modify, return
         return;
      }

      switch (mod_op)
      {
         case ADD_ATTRIBUTE:
         {
            // For each attribute in set
            while (ae.hasMoreElements ())
            {
               attr = (Attribute) ae.next ();
               if (false == (attr.getID ().equalsIgnoreCase
                  (ATTR_OBJECT_OPTIONAL_ATTRIBUTES)))
               {
                  failed = true;
                  break;
               }
               try
               {
                  int cCode;
                  Enumeration e = attr.getAll ();
                  NetBuffer optionalAttrs =
                                    new NetBuffer (getService (),
                                    NetJNI.DSV_MODIFY_CLASS_DEF,
                                    NetJNI.DEFAULT_MESSAGE_LEN);

                  // For each value in attribute
                  while (e.hasMoreElements ())
                  {
                     String s = ((NdsDistinguishedName)e.nextElement ()).
                           getDistinguishedName ();
                     // Add attribute name
                     optionalAttrs.putAttributeName (s);
                  }

                  // Call native to modify
                  getService().modifyClassDef (
                           classInfo.getName (),
                           optionalAttrs.getHandle ());
               }
               catch (Exception e)
               {
                  ne = new NamingException ();
                  ne.setRootCause (e);
                  failed = true;
               }
            }

            break;
         }

         case REPLACE_ATTRIBUTE:
         case REMOVE_ATTRIBUTE:
         {
            failed = true;
         }
      }

      if (failed)
      {
         // Pack unmodified attrs into exception
         AttributeModificationException ame =
               new AttributeModificationException ();
         Vector failedModsVec = new Vector();

         ModificationItem[] failedMods;
         ModificationItem fmod;

         if (null != attr)
         {
            fmod = new ModificationItem(mod_op, attr);
            failedModsVec.addElement(fmod);
         }

         while (ae.hasMoreElements ())
         {
            fmod = new ModificationItem(mod_op, attr);
            failedModsVec.addElement(fmod);
         }

         int failedModCount = failedModsVec.size ();
         failedMods = new ModificationItem[failedModCount];
         for (int i = 0; i < failedModCount; i++)
            failedMods[i] = (ModificationItem) failedModsVec.elementAt(i);

         ame.setUnexecutedModifications (failedMods);
         cont.setError (this, "");
         if (null != ne)
         {
            ame.setRootCause (ne);
         }
         throw (cont.fillInException (ame));
      }

      cont.setSuccess ();
      return;

   } /* schema_modifyAttributes */

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

   /**
    * Returns an instance of this object through the factory
    */
   protected Object getInstance ()
      throws NamingException
   {
      return (factory.getContextInstance (
                           getDistinguishedName (),
                           classInfo,
                           environment));
   }

   /**
    *
    */
   protected Hashtable getAttrItems ()
      throws NamingException
   {

//NOTE: NetSchemaDirContext.a_getAttributes() not used

      throw (new NamingException ());
   }

   /**
    *
    */
   private Attributes getAttributes ()
      throws NamingException
   {
      Attributes attributes = new NAttributes (true);

      switch (classInfo.getType ())
      {
         case NetJNI.DS_FULL_CLASS_DEFS:
         {

//NOTE: DS_FULL_CLASS_DEFS not implemented

         }

         case NetJNI.DS_EXPANDED_CLASS_DEFS:
         case NetJNI.DS_CLASS_DEFS:
         {
            Attribute attribute;
            String[] values;

            // Build Super Class Names
            if ((values = classInfo.getSuperClasses ()) != null)
            {
               attribute = new BasicAttribute (ATTR_OBJECT_SUPER_CLASSES);
               for (int i = 0; i < values.length; i++)
               {
                  attribute.add (new NdsDistinguishedName (values[i]));
               }
               attributes.put (attribute);
            }

            // Build Containment Class Names
            if ((values = classInfo.getContainmentClasses ()) != null)
            {
               attribute = new BasicAttribute (ATTR_OBJECT_CONTAINMENT_CLASSES);
               for (int i = 0; i < values.length; i++)
               {
                  attribute.add (new NdsDistinguishedName (values[i]));
               }
               attributes.put (attribute);
            }

            // Build Naming Attribute Names 
            if ((values = classInfo.getNamingAttributes ()) != null)
            {
               attribute = new BasicAttribute (ATTR_OBJECT_NAMING_ATTRIBUTES);
               for (int i = 0; i < values.length; i++)
               {
                  attribute.add (new NdsDistinguishedName (values[i]));
               }
               attributes.put (attribute);
            }

            // Build Mandatory Attribute Names
            if ((values = classInfo.getMandatoryAttributes ()) != null)
            {
               attribute = new BasicAttribute (ATTR_OBJECT_MANDATORY_ATTRIBUTES);
               for (int i = 0; i < values.length; i++)
               {
                  attribute.add (new NdsDistinguishedName (values[i]));
               }
               attributes.put (attribute);
            }
      
            // Build Optional Attribute Names
            if ((values = classInfo.getOptionalAttributes ()) != null)
            {
               attribute = new BasicAttribute (ATTR_OBJECT_OPTIONAL_ATTRIBUTES);
               for (int i = 0; i < values.length; i++)
               {
                  attribute.add (new NdsDistinguishedName (values[i]));
               }
               attributes.put (attribute);
            }
         }

         case NetJNI.DS_INFO_CLASS_DEFS:
         {
            // Build Schema Flags attribute
            attributes.put (
                           ATTR_FLAGS,
                           new NdsInteger (classInfo.getClassFlags ()));

            // Build asn1name attribute
            attributes.put (
                           ATTR_ASN1NAME,
                           new NdsOctetString (classInfo.getASN1ID ()));
         }

      } /* switch () */

      return (attributes);

   } /* getAttributes () */


   // ******************** NdsClassDefinition Interface ********************

   /**
    *
    */
   public NdsClassDefinitionInfo getClassInfo ()
      throws NSIException
   {
      return (classInfo);
   }

} /* NetClassDefinitionDirContext */


