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

  $Archive: /njcl_v2rmi/src/com/novell/service/nds/NdsReplicaPointer.java $
  $Revision: 9 $
  $Modtime: 11/15/00 3: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.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 Replica Pointer attribute.
 * It is used for attributes whose values represent partition
 * replicas.
 *
 * <p>Each value of this syntax is composed of five parts:
 * <ol><li>The complete name of the server that stores the replica.
 * <li>A value describing the capabilities of this copy of the
 * partition: master, secondary, read-only or subordinate reference.
 * <li>A value indicating the current state of the replica (new,
 * dying, locked, changing state, splitting, joining, moving).
 * <li>A number representing the replica (all replicas of a
 * partition have different numbers that are assigned when the
 * replicas are created).
 * <li>A referral containing a count of the addresses and
 * one or more network addresses that hint at the node at
 * which the  server probably resides. Since servers are accessible
 * over different protocols, the server may have an address for
 * each supported protocol.
 * </ol>
 * <p>The matching rules for values of Replica Pointer are based
 * on the replica server name field only, and are the same as
 * those for Distinguished Name.
 * 
 * <p>Matching Rules: Equality</p>
 * 
 * @see NdsSyntaxId
 */
public class NdsReplicaPointer 
   implements NdsAttributeValue, SchemaComposite, Cloneable, Serializable
{
   private static final int matchingRules = equality;

   private static String[] compositeIds;

   static
   {
      compositeIds = new String[5];
      compositeIds[0] = "serverName";
      compositeIds[1] = "replicaType";
      compositeIds[2] = "replicaNumber";
      compositeIds[3] = "count";
      compositeIds[4] = "replicaAddressHint";
   }

  /**
   * @internal
   */
   protected String serverName;

  /**
   * @internal
   */
   protected int replicaType;

  /**
   * @internal
   */
   protected int replicaNumber;

  /**
   * @internal
   */
   protected NdsNetAddress[] replicaAddressHint;

   private String name;

  /**
   * Constructs an NdsReplicaPointer object based on the specified
   * serverName, replicaType, replicaNumber, and
   * replicaAddressHint parameters.
   * 
   * @param serverName         The name of the server storing the
   *                           replica stored as a String value.
   * @param replicaType        The replica type (master, secondary,
   *                           read-only, subordinate reference)
   *                           stored as an int.
   * @param replicaNumber      The replica number stored as an int.
   * @param replicaAddressHint The referral to the replica address stored
   *                           as a NdsNetAddress object array.
   */
   public NdsReplicaPointer (
         String serverName,
         int replicaType,
         int replicaNumber,
         NdsNetAddress[] replicaAddressHint)
   {
      this ("", serverName, replicaType, replicaNumber, replicaAddressHint);
   }

  /**
   * @internal
   */
   protected NdsReplicaPointer ()
   {
      this.replicaType = -1;
      this.replicaNumber = -1;
   }

   private NdsReplicaPointer (
         String name,
         String serverName,
         int replicaType,
         int replicaNumber,
         NdsNetAddress[] replicaAddressHint)
   {
      this.serverName = serverName;
      this.replicaType = replicaType;
      this.replicaNumber = replicaNumber;
      this.replicaAddressHint = (NdsNetAddress[]) replicaAddressHint.clone ();
      this.name = name;
   }

  /**
   * @internal
   */
   protected NdsReplicaPointer (
         NdsReplicaPointer aReplicaPointer)
   {
      this.serverName = aReplicaPointer.serverName;
      this.replicaType = aReplicaPointer.replicaType;
      this.replicaNumber = aReplicaPointer.replicaNumber;
      this.replicaAddressHint = aReplicaPointer.replicaAddressHint;
      this.name = aReplicaPointer.name;
   }


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

  /**
   * Compares two objects for ordering, or compares two strings
   * lexicographically.
   *
   * The compareTo method does not apply to the Replica Pointer
   * 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 NdsReplicaPointer))
      {
         NdsReplicaPointer anotherReplicaPointer;

         anotherReplicaPointer = (NdsReplicaPointer) anObject;

         if (false == serverName.equals (anotherReplicaPointer.serverName))
         {
            return (false);
         }
         if (replicaType == anotherReplicaPointer.replicaType)
         {
            return (false);
         }
         if (replicaNumber == anotherReplicaPointer.replicaNumber)
         {
            return (false);
         }
         if (replicaAddressHint.length == anotherReplicaPointer.replicaAddressHint.length)
         {
            return (false);
         }
         return (true);
      }
      return (false);
   }

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

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


   // ******************** 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 serverName,
   *         replicaType and replicaNumber, or NULL.
   */
   public SchemaValue getValue (
         String compositeId)
   {
      if (compositeId.equalsIgnoreCase (compositeIds[0]))
      {
         // getServerName ();
         return (new NdsString (compositeIds[0], serverName));
      }
      else if (compositeId.equalsIgnoreCase (compositeIds[1]))
      {
         // getReplicaType ();
         return (new NdsInteger (compositeIds[1], replicaType));
      }
      else if (compositeId.equalsIgnoreCase (compositeIds[1]))
      {
         // getReplicaNumber ();
         return (new NdsInteger (compositeIds[2], replicaNumber));
      }
      else if (compositeId.equalsIgnoreCase (compositeIds[1]))
      {
         // getCount ();
         return (new NdsInteger (
                        compositeIds[3],
                        replicaAddressHint.length));
      }
      else if (compositeId.equalsIgnoreCase (compositeIds[1]))
      {
         // getReplicaAddressHint ();
/*
         return (new SchemaElement (
                        compositeIds[1],
                        new Integer (address.length),
                        "Integer"));
*/
      }
      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 this sequence's values.
    *
    * @return An enumeration of this sequence's values.
    */
   public Enumeration getValues ()
   {
      Vector values = new Vector ();

      values.addElement (new NdsString (compositeIds[0], serverName));
      values.addElement (new NdsInteger (compositeIds[1], replicaType));
      values.addElement (new NdsInteger (compositeIds[2], replicaNumber));
      values.addElement (new NdsInteger (
                                 compositeIds[3],
                                 replicaAddressHint.length));
/*
      values.addElement (new SchemaElement (
                                    compositeIds[1],
                                    new Integer (address.length),
                                    "Integer"));
*/
      return (values.elements ());

   }


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

  /**
   * Compares two Objects using the approximate matching rule.
   * 
   * The approximate method does not apply to the Replica Pointer
   * 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 the NDS syntax ID.
   *
   * @return The syntax ID as an int.
   */
   public int getNdsSyntaxId ()
   {
      return (NdsSyntaxId.REPLICA_POINTER_ID);
   }

  /**
   * Checks to see if this object supports the specified
   * matching rules. The Replica Pointer 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);
      else
         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
      {
         NdsReplicaPointer replica = (NdsReplicaPointer) super.clone ();

         replica.serverName = this.serverName;
         replica.replicaType = this.replicaType;
         replica.replicaNumber = this.replicaNumber;
         replica.replicaAddressHint = 
                     (NdsNetAddress[]) this.replicaAddressHint.clone ();

         replica.name = this.name;

         return (replica);
      }
      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 (serverName + ";"
                  + String.valueOf (replicaType) + ";"
                  + String.valueOf (replicaNumber) + ";"
                  + String.valueOf (replicaAddressHint.length) + ";"
                  );
   }


   // ******************** NdsReplicaPointer Class ********************

  /**
   * Returns the server name as a String.
   *
   * @return The server name string.
   */
   public String getServerName ()
   {
      return (serverName);
   }

  /**
   * Returns the replica type as an int.
   *
   * @return The replica type.
   */
   public int getReplicaType ()
   {
      return (replicaType);
   }

  /**
   * Returns the replica number as an int.
   *
   * @return The replica number.
   */
   public int getReplicaNumber ()
   {
      return (replicaNumber);
   }

  /**
   * Returns the length of the replicaAddressHint as an int.
   *
   * @return The length of the replicaAddressHint.
   */
   public int getCount ()
   {
      return (replicaAddressHint.length);
   }

  /**
   * Returns the replicaAddressHint array as a Net Address
   * array.
   *
   * @return The replicaAddressHint array.
   */
   public NdsNetAddress[] getReplicaAddressHint ()
   {
      return ((NdsNetAddress[]) replicaAddressHint.clone ());
   }

} /* NdsReplicaPointer */


