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

  $Archive: /njcl_v2/src/com/novell/service/nds/naming/net/NetAttributes.java $
  $Revision: 15 $
  $Modtime: 1/28/00 12:40p $

  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.novell.service.jncp.*;

import com.novell.service.nds.naming.NdsEnvironment;
import com.novell.service.nds.naming.NdsNamingExceptionFactory;

import com.novell.service.session.SessionException;

import com.novell.service.jncpv2.net.*;
import com.novell.service.jncpv2.net.NetAttrRecord;
import com.novell.service.jncpv2.net.NetAttrRecordEnumerator;

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


/** @internal
 * This object will be constructed by our DirContext implementation,
 * getAttributes() method. The state of attrs will depend on which
 * getAttributes() method was invoked. If a getAttributes() with an attrIds[]
 * String array parameter is used, then the keys portion of attrs will be
 * copied into.
 */
public final class NetAttributes extends NAttributes
{
   private String objectName;
   private NetEnvironment environment;


   /**
    *
    */
   protected NetAttributes (
         String objectName,
         NetEnvironment environment,
         String[] attributeNames)
      throws NamingException
   {
      super (true);

      NetAttributeEnumerator attributeEnumerator;

      this.objectName = objectName;
      this.environment = environment;

      // enumerate specific attributes
      attributeEnumerator = new NetAttributeEnumerator (
                                    objectName,
                                    environment,
                                    attributeNames);

      while (attributeEnumerator.hasMore ())
      {
         super.put ((Attribute) attributeEnumerator.next ());
      }

   } /* NetAttributes () */

} /* NetAttributes */


// ******************** NetAttributeEnumerator ********************

/**
 *
 */
class NetAttributeEnumerator implements NamingEnumeration
{
   private static NdsNamingExceptionFactory exceptionFactory =
       new NdsNamingExceptionFactory ();


   private String objectName;
   private NetEnvironment environment;
   private NetService service;

   private int infoType;
   private boolean allAttributes;
   private NetBuffer attributeBuffer;

   private int attributeCount;
   private NetIterationHandle iterationHandle;
   private NetBuffer objectInfo;


   private Enumeration records;

   private NetAttrRecord nextAttrRecord;


   /**
    *
    */
   NetAttributeEnumerator (
         String objectName,
         NetEnvironment environment,
         String[] attributeNames)
      throws NamingException
   {
      boolean allAttributes;
      String level = environment.getObjectAttributeLevel ();

      this.objectName = objectName;
      this.environment = environment;
      this.service = environment.getService ();

      try
      {
         if (level.equals (NdsEnvironment.OBJECT_ATTR_NAMES))
         {
            infoType = NetJNI.DS_ATTRIBUTE_NAMES;
         }
         else
         {
            infoType = NetJNI.DS_ATTRIBUTE_VALUES;
         }

         if (attributeNames == null)
         {
            this.allAttributes = true;
            attributeBuffer = new NetBuffer ();
         }
         else
         {
            this.allAttributes = false;
            attributeBuffer = new NetBuffer (
                                       service,
                                       NetJNI.DSV_READ,
                                       environment.getBatchSize ());

            // put attributeNames in NdsBuffer
            for (int i = 0; i < attributeNames.length; i++)
            {
               if (attributeNames[i] != null)
               {
                  attributeBuffer.putAttributeName (attributeNames[i]);
               }
            }
         }

         records = new NetAttrRecordEnumerator (service, objectName, infoType, attributeBuffer, environment.getBatchSize ());

         nextAttrRecord = getNextAttrRecord ();
      }
      catch (NSIException e)
      {
         NamingException ne = exceptionFactory.getNamingException (e);
         throw (ne);
      }

   } /* NetAttributeEnumerator () */

   /**
    *
    */
   private NetAttrRecord getNextAttrRecord ()
      throws NamingException, NSIException
   {
      if (records.hasMoreElements ())
      {
         return ((NetAttrRecord) records.nextElement ());
      }
      return (null);
   }

   /**
    *
    */
   public boolean hasMoreElements ()
   {
      return (nextAttrRecord != null);
   }

   public boolean hasMore ()
      throws NamingException
   {
      return (nextAttrRecord != null);
   }

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

   } /* nextElement () */

   /**
    *
    */
   public Object next ()
      throws NamingException
   {
      try
      {
         NetAttribute attribute;

         attribute = new NetAttribute (objectName, environment, nextAttrRecord);
         nextAttrRecord = getNextAttrRecord ();

         // handle attribute values in multiple iterations
         while (attribute.equalsApproximate (nextAttrRecord))
         {
            attribute.add (nextAttrRecord);
            nextAttrRecord = getNextAttrRecord ();
         }
         return (attribute);
      }
      catch (NSIException e)
      {
         NamingException ne = exceptionFactory.getNamingException (e);
         throw (ne);
      }

   } /* next () */

   /**
    *
    */
   public void close ()
      throws NamingException
   {
      // No code is necessary here. The underlying C code processes
      // the iteration handle. All results are returned at once.
   }

} /* NetAttributeEnumerator */


// ******************** NetAttributeIdEnumerator ********************

/**
 *
 */
class NetAttributeIdEnumerator implements Enumeration
{
   Enumeration list;

   NetAttributeIdEnumerator (
         Enumeration e)
   {
      list = e;
   }

   public boolean hasMoreElements ()
   {
   return list.hasMoreElements ();
   }

   public Object nextElement ()
   {
      return (list.nextElement ());
   }

   public String next ()
   {
      return ((String) list.nextElement ());
   }

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

} /* NetAttributeIdEnumerator */


