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

  $Archive: /njcl/src/com/novell/service/bindery/BinderyPropertyAttrVal.java $
  $Revision: 8 $
  $Modtime: 7/15/99 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.bindery;

import java.util.*;

  /**
   * Holds all the information found in a Bindery Property.
   *
   * <p>BinderyPropertyAttrVal is used as an Attribute Value attached
   * to the Properties Attribute for a bindery object. This class is
   * immutable, which means once it is created it cannot be changed
   * (except for adding more data segments). To make modifications,
   * extract the data not to be changed, create a new object with the
   * old, and add the object new data.
   */
   
public class BinderyPropertyAttrVal
{
   private boolean  dynamic,  propIsSet;
   private int      security;

   private String name;

   // This vector will be composed of BinderyPropertyDataSegs

   private Vector segs = new Vector();


  /**
   * Constructs a BinderyPropertyAttrVal object with the name,
   * flags and security parameters.
   *
   * @param name     The name of this property.
   * @param flags    Static/dynamic and  set/nonset bits.
   * @param security The type of read/write access for this property.
   */

   public BinderyPropertyAttrVal
   (
      String name,
      int    flags,
      int    security
   )    
   {
      this.name = new String( name );

      dynamic   = BinderyUtil.BF_DYNAMIC == (flags & BinderyUtil.BF_DYNAMIC);
      propIsSet = BinderyUtil.BF_SET     == (flags & BinderyUtil.BF_SET );

      this.security = security;
      
   }  // end constructor

   /**
    *  Adds a BinderyPropertyDataSegment to an instance of this class.
    *
    * @param dataSeg Adds a BinderyPropertyDataSegment to an instance
    *                of this class
    */

   public void addDataSegment( BinderyPropertyDataSegment dataSeg )
   {
      this.segs.addElement( dataSeg );
   }

   /**
    * Returns the specified BinderyPropertyDataSegment from an instance
    * of this class.
    *
    * @param segnum The segment number to return.
    */

   public BinderyPropertyDataSegment getDataSegment( int segNum )
   {
       return( (BinderyPropertyDataSegment)this.segs.elementAt( segNum ) );
   }

   /** 
    * Returns the number of data segments in an instance of this class.
    *
    * @return The number of data segments.
    */

   public int getNumOfSegs()
   {
      return( this.segs.size() );
   }

   /**
    * Returns the name of an instance of this class.
    *
    * @return The name of an instance of this class.
    */

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

   /**
    * Determines if this is a dynamic property.
    *
    * @return A boolean set to TRUE if this is a dynamic (not
    *         a static) property, otherwise set to FALSE.
    */

   public boolean getDynamicFlag()
   {
      return(dynamic) ;
   }

   /**
    * Determines if the data in this instance is Set data.
    *
    * @return A boolean set to TRUE if the data in this instance
    *         is Set data.
    */

   public boolean getSetFlag()
   {
      return(propIsSet) ;
   }

   /**
    *  Returns both the Dynamic and Set flags together as an integer.
    *  This is how they are used in the old API.
    *
    * @return The Dynamic and Set flags together as an integer.
    */

   public int getPropertyFlags()
   {
      if( dynamic && propIsSet )
         return( BinderyUtil.BF_DYNAMIC + BinderyUtil.BF_SET );
      else if( propIsSet )
         return( BinderyUtil.BF_SET );
      else if( dynamic )
         return( BinderyUtil.BF_DYNAMIC );
      else
         return(0) ;
   }

   /**
    *  Returns the security flag as an int.
    *
    * @return The security flag.
    */

   public int getSecurity()
   {
      return(security) ;
   }

   /**
    * Compares two BinderyPropertyAttrVal objects.
    * 
    * <p>Compares two objects in order to do searches on the
    * BinderyProperty attribute. The comparison is TRUE if all
    * valid values in the parameter are found in the current object.
    * Values can be invalidated (tagged to be ignored) by setting
    * them either to -1 (for the security field) or null (name field)
    * or just not adding any data fields. The flags are never valid
    * values on which to compare.
    *
    * <p> Both objs must have the same number of segments. However, if
    * they hold set data, they don not need to have the same number of
    * IDs. This lets you search an obj for one ID. Since each segment
    * can hold 32 IDs, the restriction to have same number of segments is
    * fairly loose.
    *
    * @param obj The object with which to compare the current object.
    *
    * @return A boolean set to TRUE if all values in the parameter are
    *         found in the current object, otherwise set to FALSE.
    */

   public boolean equals( Object obj )
   {
      if( !(obj instanceof BinderyPropertyAttrVal) )
         return( false );

      BinderyPropertyAttrVal bpav = (BinderyPropertyAttrVal)obj;

      // Compare the two simple values

      int sec = bpav.getSecurity();
      if( sec != -1 )
         if( sec != this.security )
            return( false );

      String str = bpav.getName();

      if( str != null  &&  str.length() > 0 )
         if( str.equals(this.name) == false )
            return( false );


      // Compare the data itself.

      int num = this.getNumOfSegs();
      if( num != bpav.getNumOfSegs() )
         return( false );

      for( int i=0;  i<num; i++)
      {
         BinderyPropertyDataSegment bpds1 = this.getDataSegment( i );
         BinderyPropertyDataSegment bpds2 = bpav.getDataSegment( i );

         if( !bpds1.equals(bpds2) )
            return( false );
      }

      return( true );

   }  // end equals


   /** 
    * Returns a string representation of the object.
    *
    * @return A string representation of the object.
    */
    
    /* Since we have a somewhat complex structure, need our own
    * toString. Probably ought to convert the booleans to more
    * meaningful words ...
    */
   public String toString()
   {
      Boolean d = new Boolean( dynamic );
      Boolean s = new Boolean( propIsSet );
      
      StringBuffer str = new StringBuffer(
                     name +
                     " "  +
                     d.toString() +
                     " "  +
                     s.toString() +
                     " "  +
                     Integer.toHexString( security ) );

      int i=0, j = segs.size();
      BinderyPropertyDataSegment bpds;

      for( ; i<j; i++ )
      {
         bpds = (BinderyPropertyDataSegment)segs.elementAt(i) ;
         str.append( " " + bpds.toString() );
      }

      return( str.toString() );

   }  // end toString

}
