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

  $Archive: /njcl_v2rmi/src/com/novell/service/file/nw/calls/ObjectNameImpl.java $
  $Revision: 17 $
  $Modtime: 1/05/01 2:43p $

  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.file.nw.calls;

import java.rmi.RemoteException;

import com.novell.java.lang.IntegerBuffer;

import com.novell.service.jncp.NSIException;

import com.novell.service.session.SessionException;
import com.novell.service.session.xplat.CallsService;
import com.novell.service.jncpv2r.net.NetService;

/** @internal
 * Novell object name support class
 *
 * <p>This class extends the ObjectName class by adding the objectId and
 * providing name to objectId and ObjectId to name conversions.
 * </p>
 *
 */

public class ObjectNameImpl extends ObjectName
{

   private CallsService callsService;
   private NetService netService;
   private boolean sessionIsNDS;
   private int objectId;

/* **************************************************************************
* public constructors (published)
****************************************************************************/

   /**
    * Minimum constructor
    *
    * <p>Construct this object.  The object name and objectId is currently
    * unknown.  The getName method will return null until the setName method
    * is called.  The objectId will be set to -1.
    * </p>
    * @param callsService         Calls service for NWCalls functions.
    * @param netService          Calls service for NWNet functions.
    * @param sessionIsNDS        flag indicating is session is bindery or NDS.    
    */

   public ObjectNameImpl(
      CallsService callsService, 
      NetService netService, 
      boolean sessionIsNDS)
   {
      this(null, -1, callsService, netService, sessionIsNDS);
   }

   /**
    * Object Name known constructor
    *
    * <p>Construct this object, with the objectId currently unknown.  The
    * getObjectId method will return -1, until the setObjectId method is
    * called.
    * </p>
    *
    * @param name                Object Name
    * @param callsService         Calls service for NWCalls functions.
    * @param netService          Calls service for NWNet functions.
    * @param sessionIsNDS        flag indicating is session is bindery or NDS.    
    */

   public ObjectNameImpl(
      String name,
      CallsService callsService, 
      NetService netService, 
      boolean sessionIsNDS)
   {
      this(name, -1, callsService, netService, sessionIsNDS);
   }

   /**
    * ObjectId known constructor
    *
    * <p>Construct this object, with the object name currently unknown.  The
    * getName method will return null until the setName method is called.
    * </p>
    * @param objectId            object ID
    * @param callsService         Calls service for NWCalls functions.
    * @param netService          Calls service for NWNet functions.
    * @param sessionIsNDS        flag indicating is session is bindery or NDS.    
    */

   public ObjectNameImpl(
      int objectId,
      CallsService callsService, 
      NetService netService, 
      boolean sessionIsNDS)
   {
      this(null, objectId, callsService, netService, sessionIsNDS);
   }

   /**
    * Full Constructor
    *
    * <p>The name and objectId state will be set to the values of the
    * corrisponding input parameters.
    * </p>
    * @param name                object name
    * @param objectId            object ID
    * @param callsService         Calls service for NWCalls functions.
    * @param netService          Calls service for NWNet functions.
    * @param sessionIsNDS        flag indicating is session is bindery or NDS.    
    */

   public ObjectNameImpl(
      String name, 
      int objectId,
      CallsService callsService, 
      NetService netService, 
      boolean sessionIsNDS)
   {
      super(name);
      this.objectId = objectId;
      this.callsService = callsService;
      this.netService = netService;
      this.sessionIsNDS = sessionIsNDS;
   }

/* **************************************************************************
* public accessors (overridden from superclass, not published)
****************************************************************************/

   /**
    * Sets the Object Name.
    *
    * <p>Sets the Object Name.  This method will  cause the nds name to Id
    * conversion to be attempted (NWDSMapNameToID).  objectId will be set to
    * the conversion value if the conversion is successfull, it will be set
    * to -1 otherwise.
    * </p>
    *
    * @param name                The object name
    *
    * @see #nameToObjectId
    */

   public void setName(String name)
   {
      super.setName(name);
      if (name != null)
      {
         try
         {
            setObjectId(
               nameToObjectId(
                  name, 
                  callsService, 
                  netService, 
                  sessionIsNDS));
         } catch (NSIException nsie)
         {
            setObjectId(-1);
         }
      }
   }

/* **************************************************************************
* public accessors
****************************************************************************/

   /**
    * Gets the object ID
    *
    * <p>This method returns the current value of object ID.  This
    * is only intended to be used by jndi name space providers and should not
    * be used by the application layer.  At present, the value of objectID
    * is actually set by a native method in the namespace provider, and this
    * method is used to convert the object ID to a name, which is
    * what the user application layer is concerned about.
    * </p>
    *
    * @return                    The current value of objectId
    */

   public int getObjectId()
   {
      return objectId;
   }

   /**
    * Sets the object ID
    *
    * <p>This method sets the current value of object ID.  This
    * is only intended to be used by jndi name space providers and should not
    * be used by the application layer.
    * </p>
    *
    * @param objectId            The value to set objectId to
    */

   public void setObjectId(int objectId)
   {
      this.objectId = objectId;
   }

/* **************************************************************************
* public static conversion methods
****************************************************************************/

   /**
    * Given an objectName object return the objectId
    *
    * <p>If the objectName is an instance of BinderyName, use the
    * BinderyNameImpl's static conversion method, otherwise, use this
    * classes static conversion method
    * </p>
    *
    * @param objectName          The objectName to convert.
    *
    * @return                    The corrisponding objectId.
    *
    * @exception                 com.novell.service.jncp.NSIException
    */

   public static int nameToObjectId(
      ObjectName name, 
      CallsService callsService, 
      NetService netService, 
      boolean sessionIsNDS)
      throws NSIException
   {
      if (name instanceof BinderyName)
         return BinderyNameImpl.nameToObjectId(
                                       name.getName(),
                                       ((BinderyName)name).getType(),
                                       callsService);
      else
         return ObjectNameImpl.nameToObjectId(
                                 name.getName(), 
                                 callsService,
                                 netService,
                                 sessionIsNDS);
   }

   /**
    * Given an object name return the objectId
    *
    * <p>Converts from the given object name to the an objectId.
    * </p>
    *
    * @param name                The object name desired
    * @param callsService         Calls service for NWCalls functions.
    * @param netService          Calls service for NWNet functions.
    * @param sessionIsNDS        flag indicating is session is bindery or NDS.    
    *
    * @return                    The corrisponding objectId.
    *
    * @exception                 com.novell.service.jncp.NSIException
    */

   public static int nameToObjectId(
      String name, 
      CallsService callsService, 
      NetService netService, 
      boolean sessionIsNDS)
      throws NSIException
   {
      // first try to obtain an NDS id
      try
      {
         if (sessionIsNDS)
         {
            IntegerBuffer objectId = new IntegerBuffer();
            netService.mapNameToID(name, objectId);
            return objectId.intValue();
         }
      }
      catch(Exception e)
      {
         if(!BinderyName.isNameType(name)) //If not bindery name
         {
            if(e instanceof NSIException)
               throw (NSIException)e;
            else
               throw new NSIException("Check Root Cause", e);
         }
      }

      return nameToObjectId(new BinderyName(name, true),
         callsService, netService, sessionIsNDS);
   }

   /**
    * Given an objectID, return an ObjectName object
    *
    * <p>Converts objectId to a name and type and instantiates an
    * ObjectNameImpl object if the connection is to a NDS server.  If the
    * connection is not to a NDS server, an attempt for a BinderyNameImpl
    * will be made.
    * </p>
    *
    * @param objectId            The desired objectId
    * @param callsService         Calls service for NWCalls functions.
    * @param netService          Calls service for NWNet functions.
    * @param sessionIsNDS        flag indicating is session is bindery or NDS.    
    *
    * @return                    ObjectNameImpl if NDS connection,
    *                            BinderyNameImpl otherwise.
    *
    * @exception                 com.novell.service.jncp.NSIException
    * @see com.novell.service.file.nw.calls.BinderyNameImpl
    */

   public static ObjectName objectIdToObjectName(
      int objectId,
      CallsService callsService, 
      NetService netService, 
      boolean sessionIsNDS)
      throws NSIException
   {
      /*
         If an objectId has not been set (like in the case of archiverID in
         DirectoryEntryInforImpl) it will be 0.  The natives do not check for
         0 and do bad things (corrupt memory), so, check it here and throw
         an exception
      */
      if (objectId == 0)
         throw new NSIException();

      /*
         First try the the bindery interface to convert the id, if it fails
         then try nds.
      */
      NSIException nsie = null;

      if (sessionIsNDS)
      {
         try
         {
            StringBuffer name = new StringBuffer();

            netService.mapIDToName(objectId, name);

            ObjectNameImpl oni = new ObjectNameImpl(
                                          name.toString(), 
                                          callsService,
                                          netService,
                                          sessionIsNDS);
            oni.setObjectId(objectId);

            return oni;
         }
         catch (NSIException e)
         {
            nsie = e;
         }
         catch (SessionException e2)
         {
            throw new NSIException(e2.getMessage(), 0, e2);
         }
         catch (RemoteException e2)
         {
            throw new NSIException(e2.getMessage(), 0, e2);
         }
      }

      try
      {
         return BinderyNameImpl.objectIdToBinderyName(objectId, callsService);
      }
      catch (NSIException e)
      {
         nsie = e;
      }

      int ccode = nsie.getCCode();
      if (ccode == 0x89fc)
      {
         return new ObjectName("");
      }

      throw nsie;
   }

   public static int swap32(int unswapped)
   {
      int[] arr = new int[4];

      for (int i = 3; i >= 0; i--)
      {
         arr[i] = (unswapped >>> (i * 8)) & 0xFF;
         if (arr[i] < 0)
            arr[i] = arr[i] & 0x7F + 0x80;
      }

      return ((arr[0] << 24) +
              (arr[1] << 16) +
              (arr[2] <<  8) +
               arr[3]);
   }
}