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

  $Archive: /njcl_v2/src/com/novell/service/nds/NdsNetAddress.java $
  $Revision: 8 $
  $Modtime: 10/15/99 3:38p $
 
  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;


import java.io.Serializable;

import java.util.Enumeration;
import java.util.Vector;

import com.novell.service.schema.SchemaValue;
import com.novell.service.schema.SchemaComposite;


/**
 * Provides access to values of the NetAddress attribute.
 * It is used for network addresses in the NetWare environment.
 * The address type indicates the type of communications protocol
 * used (IPX, AppleTalk, IP, OSI NSAP, etc.).
 *
 * <p>For two values of Net Address to match, the type, length,
 * and value of the address must match. The address length is
 * the number of bytes. The address itself is stored as a binary
 * string, which is the literal value of the address.
 *
 * <p>Matching Rules: Equality</p>
 *
 * @see NdsSyntaxId
 */
public class NdsNetAddress
   implements NdsAttributeValue, SchemaComposite, Cloneable, Serializable
{
   /**
    * No NetWare address type provided.
    *
    * <p>(TYPE_NONE   = 0x00000000)</p>
    */
   public static final int TYPE_NONE   = 0x00000000;

   /**
    * NetWare address type is IPX.
    *
    * <p>(TYPE_NONE   = 0x00000001)</p>
    *
    * Format of address:  nn nn nn nn aa aa aa aa aa aa pp pp
    *    where nn is a network address byte, aa is a node address byte
    *    and pp is a port
    */
   public static final int TYPE_IPX    = 0x00000001;

   /**
    * NetWare address type is DDP.
    *
    * <p>(TYPE_IPX   = 0x00000003)</p>
    */
   public static final int TYPE_DDP    = 0x00000003;

   /**
    * NetWare address type is ASP.
    *
    * <p>(TYPE_ASP   = 0x00000004)</p>
    */
   public static final int TYPE_ASP    = 0x00000004;

   /**
    * NetWare address type is UDP.
    *
    * <p>(TYPE_UDP   = 0x00000008)</p>
    *
    * Format of address: pp pp aa aa aa aa
    *    where pp is a port byte and aa is an address byte.
    */
   public static final int TYPE_UDP    = 0x00000008;

   /**
    * NetWare address type is TCP.
    *
    * <p>(TYPE_TCP   = 0x00000009)</p>
    */
   public static final int TYPE_TCP    = 0x00000009;

   /**
    * NetWare address type is UDP6.
    *
    * <p>(TYPE_UDP6   = 0x0000000A)</p>
    */
   public static final int TYPE_UDP6   = 0x0000000A;

   /**
    * NetWare address type is TCP6.
    *
    * <p>(TYPE_TCP6   = 0x0000000B)</p>
    */
   public static final int TYPE_TCP6   = 0x0000000B;

   /**
    * NetWare address type is WILD.
    *
    * <p>(TYPE_WILD   = 0x00008000)</p>
    */
   public static final int TYPE_WILD   = 0x00008000;

   private static final int matchingRules = equality;

   private static String[] compositeIds;

   static
   {
      compositeIds = new String[3];
      compositeIds[0] = "type";
      compositeIds[1] = "length";
      compositeIds[2] = "address";
   }

  /**
   * @internal
   */
   protected int type;

  /**
   * @internal
   */
   protected byte[] address;

   private String name;


   /**
   * Constructs an NdsNetAddress object based on the specified
   * type and address variables.
   * 
   * @param type    The address type to be stored as a long value.
   *                IPX = 0, IP = 1, OSI NSAP = 4, AppleTalk = 5, etc.
   * @param address The literal value of the address to be stored as
   *                a byte array.
   */
   public NdsNetAddress (
         long type,
         byte[] address)
   {
      this ("", type, address);
   }

  /**
   * @internal
   */
   protected NdsNetAddress ()
   {
      this.type = -1;
   }

   private NdsNetAddress (
         String name,
         long type,
         byte[] address)
   {
      this.type = (int) (type & INT_MASK);
      this.address = (byte[]) address.clone ();
      this.name = name;
   }

  /**
   * @internal
   */
   protected NdsNetAddress (
         NdsNetAddress aNetAddress)
   {
      this.type = aNetAddress.type;
      this.address = aNetAddress.address;
      this.name = aNetAddress.name;
   }


   // ******************** SchemaValue Interface ********************

  /**
   * Compares two objects for ordering, or compares two strings
   * lexicographically.
   *
   * The compareTo method does not apply to the NdsNetAddress syntax
   * because this syntax does not support the ordering and substrings
   * matching rules.
   */
   public int compareTo (
         Object anObject)
      throws Exception
   {
      throw (new Exception ());
   }

  /**
   * Compares two Objects for equality. The equals method compares
   * this object value with the value of the reference object in
   * the anObject parameter.
   *
   * <p>The equals method implements the most discriminating possible
   * equivalence relation on objects; that is, for any reference values
   * X and Y, this method returns TRUE if and only if X and Y refer to
   * the same object (X==Y has the value TRUE).</p>
   * 
   * @param anObject The reference object with which to compare.
   *
   * @return A boolean set to TRUE if and only if the argument is not
   *         NULL and is an NDS integer object that contains the
   *         same value as this object, otherwise set to FALSE.
   */
   public boolean equals (
         Object anObject)
   {
      if ((anObject != null) && (anObject instanceof NdsNetAddress))
      {
         byte[] anotherAddress;
         NdsNetAddress anotherNetAddress;

         anotherNetAddress = (NdsNetAddress) anObject;
         if (this.type != anotherNetAddress.getType ())
         {
            return (false);
         }
         if (this.address.length != anotherNetAddress.getLength ())
         {
            return (false);
         }
         anotherAddress = anotherNetAddress.getAddress ();
         for (int i = 0; i < address.length; i++)
         {
            if (address[i] != anotherAddress[i])
            {
               return (false);
            }
         }
         return (true);
      }
      return (false);
   }

  /**
   * @internal
   */
   public String getName ()
   {
      return (name);
   }

  /**
   * @internal
   */
   public String getSyntaxId ()
   {
      return (NdsSyntaxId.NET_ADDRESS);
   }


   // ******************** SchemaComposite Interface ********************

  /**
   * Returns the number of elements in this sequence.
   *
   * @return The number of elements in this sequence as an int.
   */
   public int count ()
   {
      return (compositeIds.length);
   }

   /**
   * Returns a SchemaValue object based on the given passed-in
   * string containing the element value. The SchemaValue object
   * is a Java language data type.
   *
   * @param compositeId The passed-in string containing the element
   *                    value.
   *
   * @return The SchemaValue object containing the type, length
   *         and address, or NULL.
   */
   public SchemaValue getValue (
         String compositeId)
   {
      if (compositeId.equalsIgnoreCase (compositeIds[0]))
      {
         // getType ();
         return (new NdsInteger (compositeIds[0], type));
      }
      else if (compositeId.equalsIgnoreCase (compositeIds[1]))
      {
         // getLength ();
         return (new NdsInteger (compositeIds[1], address.length));
      }
      else if (compositeId.equalsIgnoreCase (compositeIds[2]))
      {
         // getAddress ();
/*
         return (new SchemaElement (
                        compositeIds[2],
                        address.clone (),
                        "byte[]"));
*/
      }
      return (null);
   }

  /**
   * Returns an enumeration of element IDs in this composite.
   *
   * @return An enumeration of element IDs.
   */
   public Enumeration getValueIds ()
   {
      Vector vector = new Vector ();

      for (int i=0; i<compositeIds.length; i++)
         vector.addElement(compositeIds[i]);
      return (vector.elements ());
   }

  /**
   * Returns an enumeration of element values in this composite.
   *
   * @return An enumeration of element values (type and address
   *         length).
   */
   public Enumeration getValues ()
   {
      Vector values = new Vector ();

      values.addElement (new NdsInteger (compositeIds[0], type));
      values.addElement (new NdsInteger (compositeIds[1], address.length));
/*
      values.addElement (new SchemaElement (
                                    compositeIds[2],
                                    address.clone (),
                                    "byte[]"));
*/
      return (values.elements ());
   }


   // ******************** NdsAttributeValue Interface ********************

  /**
   * Compares two Objects using the approximate matching rule.
   * 
   * The approximate method does not apply to the NdsNetAddress
   * syntax because this syntax does not support the approximate
   * equals matching rule.
   */
   public boolean approximate (
         Object anObject)
      throws Exception
   {
      throw (new Exception ());
   }

  /**
   * Returns the int that represents this NDS syntax ID.
   *
   * @return The syntax ID as an int.
   */
   public int getNdsSyntaxId ()
   {
      return (NdsSyntaxId.NET_ADDRESS_ID);
   }

  /**
   * Checks to see if this object supports the specified
   * matching rules. The NetAddress syntax supports only
   * the Equality matching rule.
   *
   * @param matchingRules The set of matching rules to check.
   *
   * @return A Boolean set to TRUE if the matching rules for this
   *         object are equal to the matchingRules parameter.
   */
   public boolean supportsMatchingRules (
         int matchingRules)
   {
      if ((matchingRules & this.matchingRules) == matchingRules)
      {
         return (true);
      }
      return (false);
   }


   // ******************** Object Class ********************

  /**
   * Creates a new object of the same class as this object. It
   * then initializes each of the new object's fields by assigning
   * them the same value as the corresponding fields in this object.
   * No constructor is called.
   *
   * @return A clone of this object instance containing the cloned
   *         syntax.
   */
   public Object clone ()
   {
      try
      {
         NdsNetAddress netAddress = (NdsNetAddress) super.clone ();

         netAddress.type = this.type;
         netAddress.address = (byte[]) this.address.clone ();

         netAddress.name = this.name;

         return (netAddress);
      }
      catch (CloneNotSupportedException e)
      {
         // this shouldn't happen, since we are Cloneable
         throw (new InternalError ());
      }

   } /* clone () */

  /**
   * Generates a string representation of the object. It
   * returns a string that textually represents the object.
   * The result should be a concise but informative
   * representation that is easy to read.
   *
   * @return The String representation of the object.
   */
   public String toString ()
   {
      return (String.valueOf (type) + ";" + address.length + ";" );
   }


   // ******************** NdsNetAddress Class ********************

  /**
   * Returns the long value of Net Address type stored in the
   * NDS attribute.
   *
   * @return The long value of Net Address type.
   */
   public long getType ()
   {
      return (type & INT_MASK);
   }

  /**
   * Returns the length of the Net Address.
   * 
   * @return The long value of Net Address length.
   */
   public long getLength ()
   {
      return (address.length & INT_MASK);
   }

  /**
   * Returns the byte array of Net Address values stored in
   * the NDS attribute.
   *
   * @return The byte array of address values.
   */
   public byte[] getAddress ()
   {
      return ((byte[]) address.clone ());
   }

} /* NdsNetAddress */


