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

  $Archive: /njcl_v2rmi/src/com/novell/service/file/nw/VolumeRestriction.java $
  $Revision: 16 $
  $Modtime: 1/12/01 4:10p $
 
  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;

import com.novell.service.rfc1960.SearchStringComponent;
import com.novell.service.rfc1960.Rfc1960Parser;

/** 
 * Provides for attribute values of volume restrictions associated with
 * a given Volume.
 * 
 * <p>This class results in a mutable object. For versitility, code block
 * synchronization has been implemented in the various jndi search and 
 * modify methods of this class's implementation to provide for thread 
 * safe operation.
 * </p>
 * <p>If you have a code segment of multi-threaded application that 
 * uses get methods of this class, and there is a potential of another
 * thread randomly using corresponding set methods of this class,
 * you should enclose the calls to the get methods of this class in a 
 * synchronized code block.
 * </p>
 * <p>If you have a code segment of  a multi-threaded application that 
 * uses set methods of this class, and there is a potential of another
 * thread randomly using corresponding get methods of this class,
 * you should enclose the calls to the set methods of this class in a 
 * synchronized code block.
 * </p>
 * @see VolumeRestrictionEnumerator
 */
 
public class VolumeRestriction implements Cloneable, java.io.Serializable
{
/* **************************************************************************
   jndi naming interface defines
****************************************************************************/

   /**
    * Attribute ID of VolumeRestriction.
    *
    * <p>(ATTRIBUTE_ID = "Volume Restrictions")
    * </p>
    */

   public static final String ATTRIBUTE_ID = "Volume Restriction";

   /**
    * Schema Name of VolumeRestriction.
    *
    * <p>(SCHEMA_BINDING_NAME = ATTRIBUTE_ID + " Definition")
    * </p>
    */

   public static final String SCHEMA_BINDING_NAME = 
         ATTRIBUTE_ID + " Definition";

   /**
    * Schema Syntax of VolumeRestriction.
    *
    * <p>(COMPARE_SYNTAX_STRING = 
    *       "(" +
    *       SearchStringComponent.EQUALS_STRING + "," +
    *       SearchStringComponent.PRESENT_STRING + "," +
    *       SearchStringComponent.SUBSTRING_STRING + 
    *       ")")
    * </p>
    */

   public static final String COMPARE_SYNTAX_STRING = 
         new String(
               "(" +
               SearchStringComponent.EQUALS_STRING + "," +
               SearchStringComponent.PRESENT_STRING + "," +
               SearchStringComponent.SUBSTRING_STRING + 
               ")");

/* **************************************************************************
   compareString field name defines
****************************************************************************/

   /**
    * The Name compare field.
    *
    * <p>(NAME_FIELD = "Name")
    * </p>
    * @see #setCompareString
    * @see #equals
    */

   public static final String NAME_FIELD = new String("Name");

   /**
    * The Restriction compare field.
    *
    * <p>(RESTRICTION_FIELD = "Restriction")
    * </p>
    * @see #setCompareString
    * @see #equals
    */

   public static final String RESTRICTION_FIELD = new String ("Restriction");

   /**
    * The InUse compare field.
    *
    * <p>(INUSE_FIELD = "InUse")
    * </p>
    * @see #setCompareString
    * @see #equals
    */

   public static final String INUSE_FIELD = new String("InUse");


/* **************************************************************************
   VolumeRestriction state data members
****************************************************************************/

   private String name;
   private int objectId;
   private int restriction;
   private int inUse;


   private String compareString;
   private Rfc1960Parser ssParser = null;
   private boolean firstParser = true;


/* **************************************************************************
* Constructors
****************************************************************************/

   /**
    * Creates a Default VolumeRestriction Constructor with no
    * parameters.
    */

   public VolumeRestriction()
   {
   }
       
   /**
    * Creates a full VolumeRestriction Constructor object with all possible
    * state parameters, and initializes the object to the values of these
    * parameters.
    *
    * @param name        The name data members value.
    * @param restriction The restriction data members value.
    * @param inUse       The inUse data members value.
    */

   public VolumeRestriction(String name, int restriction, int inUse)
   {
      this.name = name;
      this.restriction = restriction;
      this.inUse = inUse;
   }   

   /**
    * Creates a VolumeRestriction Constructor object with only the
    * name parameter known, and initializes the object to the values
    * of theis parameter.
    * 
    * <p>All other data members are set to NULL or zero. The actual
    * name parameter reference will be stored by this object (it will
    * not be cloned). Later modifications to to this references 
    * state will be reflected in this object.</p>
    *
    * @param name The name data members value.
    */
    
   public VolumeRestriction(String name)
   {
      this(name, 0, 0);
   }

/* **************************************************************************
   Public Accessor methods
****************************************************************************/

   /**
    * Returns a reference to this object's name field.
    *
    * <p>If you modify the state of the returned object, it will
    * be reflected in this object.</p>
    *
    * @return The current value of this object's name field.
    */

   public String getName()
   {
      return(name);
   }

   /**
    * Sets the value of this object's name field.
    *
    * <p>The actual parameter reference will be stored by this object
    * (it will not be cloned). Later modifications to to this reference's
    * state will be reflected in this object.</p>
    *
    * @param value  The new value of the name field.
    */

   public void setName(String value)
   {
      name = value;
   }

   /**
    * Returns the restriction field of this Object.
    *
    * @return The current value of this object's restriction field
    * in 4K pieces.
    */

   public int getRestriction()
   {
      return(restriction);
   }

   /**
    * Sets the restriction field of this Object.
    *
    * @param value The new value of this object's restriction field
    * in 4K pieces.
    */

   public void setRestriction(int value)
   {
      restriction = value;
   }

   /**
    * Returns the inUse field of this Object.
    *
    * @return The current value of this object's inUse field
    * in 4K pieces.
    */

   public int getInUse()
   {
      return(inUse);
   }

   /**
    * Sets the inUse field of this Object.
    *
    * @param value The new value of this object's inUse field
    * in 4K pieces.
    */

   public void setInUse(int value)
   {
      inUse = value;
   }

   /**
    * Returns the objectId field of this Object.
    *
    * <p>This method should only be used by name space provider spi code.
    * </p>
    *
    * @return The current value of this object's objectId field.
    */

   public int getObjectId()
   {
      return(objectId);
   }

   /**
    * Sets the objectId field of this Object.
    *
    * <p>This method should only be used by name space provider spi code.
    * </p>
    *
    * @param value The new value of this object's objectId field.
    */

   public void setObjectId(int value)
   {
      objectId = value;
   }

/* **************************************************************************
 public compareString support methods
****************************************************************************/

   /**
    * Sets the compare string value for the compare fields.
    * 
    * <p>The compare string uses the RFC1960 (LDAP) search string format 
    * and is used to allow individual compares on the name, restriction,
    * and inUse fields. If the string passed in is not a valid RFC1960
    * formated string, this method will throw an IllegalArgumentException.
    * If the compareString value is NULL, RFC1960 formatted compares will
    * be disabled.
    *
    * <p>The names of these fields have taken the names of their 
    * corresponding methods minus the get or set prefix. Given the following 
    * string:
    *
    * <p><i>   "(&(Name=*printer*)(ObjectId>=2)(Rights>=128))"</i>
    *
    * <p>The equals method will return TRUE if the name contains the
    * substring printer, the objectId is not 2, and the rights are set
    * to be able to modify (TA_MODIFY). If the approximate operator type
    * is used on the Rights field the various bits of the operand value
    * are checked, and if any of them are set, equals will return TRUE.
    * For example: "(Rights~=3) returns TRUE if either the TA_READ or
    * TA_WRITE bits are set regardless of what other bits might be set.
    * </p>
    *
    * @param compareString The RFC1960 formatted search string. NULL 
    *                      disables this compare functionality.
    *
    * @exception IllegalArgumentException if the string passed in is not
    * a valid RFC1960 formatted string.
    *
    * @see #equals
    * @see #NAME_FIELD
    * @see #RESTRICTION_FIELD
    * @see #INUSE_FIELD
    */
    
   public void setCompareString(String compareString)
   {
      firstParser = true;
      if (compareString != null)
      {
         this.compareString = new String(compareString);
         ssParser = new Rfc1960Parser(compareString);
      }else
      {
         this.compareString = null;
         ssParser = null;
      }
   }

   /**
    * Returns the current value of the compareString.
    *
    * @return The current value of compareString.
    *
    * @see #setCompareString
    */
    
   public String getCompareString()
   {
      return compareString;
   }


   /**
    * Returns the RFC1960 Search String parser for the compare string.
    * 
    * <p>A Rfc1960Parser object that was instantiated with the compareString
    * last set by the setCompareString method is returned.</p>
    *
    * @return The Rfc1960Parser for the current compare String.
    *         NULL is returned if the compare string has not been set.
    */
    
   public Rfc1960Parser getSearchStringParser()
   {
      if (firstParser)
      {
         firstParser = false;
         return ssParser;
      }else
      {
         if (compareString == null)
            return null;
         return new Rfc1960Parser(compareString);
      }
   }

/* *************************************************************************
* overridden Object methods
***************************************************************************/

   /**
    * Compares the input object against this object for equality.
    * 
    * <p>If the input object has a RFC1960 compare string, this method
    * will do the comparision based on the commands in the compare string.
    * If the operationType is illegal for the data type being compared, an 
    * IllegalArmumentException will be thrown.</p>
    *
    * @param obj The object to compare.
    *
    * @return A boolean set to TRUE if the objects are equal,
    *         otherwise FALSE is returned.
    *
    * @exception IllegalArgumentException IF the operationType is illegal
    *            for the data type being compared.
    *
    * @see #setCompareString
    * @see #NAME_FIELD
    * @see #RESTRICTION_FIELD
    * @see #INUSE_FIELD
    */
    
   public boolean equals(Object obj)
   {
      if(obj == null || !(obj instanceof VolumeRestriction))
         return false;
      VolumeRestriction vr = (VolumeRestriction)obj;

      Rfc1960Parser ssp = vr.getSearchStringParser();
      if (ssp == null)
      {
         // do a simple compare

         if (obj == this)
            return true;

         if (!SearchStringComponent.compareStringsEqual(vr.getName(), getName()))
            return false;

         if (vr.getRestriction() != restriction)
            return false;

         if (vr.getInUse() != inUse)
            return false;

         return true;      
      }

      while (ssp.hasMoreElements())
      {
         SearchStringComponent ssc = ssp.next();
         String name = ssc.getAttributeId();
         boolean compared = false;

         if (name.equals(NAME_FIELD))
         {
            compared =ssc.compareString(
                              ssc.getOperationType(), 
                              ssc.operandReplacement() ?
                                 vr.getName() :
                                 ssc.getOperand(),
                              this.name,
                              true);
         }else
         {
         if (name.equals(RESTRICTION_FIELD))
         {
            compared = ssc.compareInt(
                              ssc.getOperationType(), 
                              ssc.operandReplacement() ?
                                 vr.getRestriction() :
                                 Integer.parseInt(ssc.getOperand()),
                              restriction);
         }else
         {
         if (name.equals(INUSE_FIELD))
         {
            compared = ssc.compareInt(
                              ssc.getOperationType(), 
                              ssc.operandReplacement() ?
                                 vr.getInUse() :
                                 Integer.parseInt(ssc.getOperand()),
                              inUse);
         }else
            compared = false;

         }}
         ssp.setCompareResult(ssc, compared);
      }
      return ssp.compared();
   }   

   /**
    * Returns a String representation of this object.
    * 
    * <p>The String representation is in the following format:
    * "name: s, restriction: n, inUse: n, compareString: s"</p>
    *
    * @return A String representation of this object.
    */
    
   public String toString()
   {
      return new String(
                     "name: " + name +
                     ", restriction: " + restriction +
                     ", inUse: " + inUse +
                     ", compareString: " + compareString);
   }

   /**
    * Clones the current VolumeRestriction object.
    * 
    * <p>Instantiates a new object of this type with all new references,
    *  but with the same values within those references.</p>
    *
    * @return  A new VolumeRestriction object with the same values.
    */
    
   public Object clone()
   {
      VolumeRestriction obj = null;
      try
      {
         obj = (VolumeRestriction) super.clone();
      }
      catch (CloneNotSupportedException e)
      {
         // this shouldn't happen, since we are Cloneable
         throw (new InternalError());
      }

      obj.name = name;
      obj.objectId = objectId;
      obj.restriction = restriction;
      obj.inUse = inUse;
      obj.compareString = compareString;
      obj.ssParser = ssParser;
      obj.firstParser = firstParser;
      obj.setCompareString(compareString);
      return obj;
   }

   public void copySubset(VolumeRestriction from)
   {
      this.objectId = from.objectId;
      this.restriction = from.restriction;
   }

   /**
    * Copies the CallsServiceRemote from object into this object.
    */
   public void copy(VolumeRestriction from)
   {
      this.name = from.name;
      this.objectId = from.objectId;
      this.restriction = from.restriction;
      this.inUse = from.inUse;
      this.compareString = from.compareString;
      this.ssParser = from.ssParser;
      this.firstParser = from.firstParser;
      this.setCompareString(from.compareString);
   }
}