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

  $Archive: /njcl_v2rmi/src/com/novell/service/nds/NdsObjectACL.java $
  $Revision: 16 $
  $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.*;
import com.novell.service.schema.*;

import com.novell.service.schema.SchemaComposite;
import java.lang.Cloneable;


/**
 * Provides access to attribute values of the ObjectACL
 * syntax. It is used for attributes whose values represent ACL
 * entries. An object ACL value can protect either an object
 * or an attribute. The protected object is always the one that
 * contains the ACL attribute. If an ACL entry is to apply to
 * the object as a whole, the protected attribute name should
 * be left empty (NULL). If a specific attribute is to be
 * protected, it should be named in the ACL entry.</p>
 *
 * <p>You can match an ACL value against either a subject
 * (trustee) or a privilege set, or both. If the subject name
 * is not to be considered in the comparison, specify it as
 * NULL. If the privilege set is not to be considered in the
 * comparison, specify an Approximate Match with a privilege
 * set value of zero.</p>
 *
 * <p>The Object ACL syntax supports both matching for equality
 * and approximate matching. The difference between matching
 * for equality and approximate matching concerns the privileges
 * field of the comparison value. When matching for equality,
 * the privilege set must match exactly for the comparison to
 * succeed. When approximate matching has been selected, any
 * bits in the privilege field in the filter that are set must
 * also be set in the target. Any other bits in the target are
 * ignored.
 *
 * <p>Matching Rules: Equality and Approximate Matching</p>
 *
 * @see NdsSyntaxId
 */
public class NdsObjectACL 
   implements NdsAttributeValue, SchemaComposite, Cloneable, Serializable
{
   /* Special attribute names in ACLs */

   /**
    * All Attributes Rights ACL to be stored as a String value.
    *
    * <p>(DS_ALL_ATTRS_NAME = "[All Attributes Rights]")
    */
   public static final String DS_ALL_ATTRS_NAME = "[All Attributes Rights]";

  /**
   * Entry Rights ACL to be stored as a String value.
   *
   * <p>(DS_ENTRY_RIGHTS_NAME = "[Entry Rights]")
   */
   public static final String DS_ENTRY_RIGHTS_NAME = "[Entry Rights]";


   /* Special entry names in ACLs */

   /**
    * String constant for the [Root] object.
    *
    * <p>(DS_ROOT_NAME = "[Root]")
    */
   public static final String DS_ROOT_NAME = "[Root]";

   /**
    * String constant for the [Public] object.
    *
    * <p>(DS_PUBLIC_NAME = "[Public]")
    */
   public static final String DS_PUBLIC_NAME = "[Public]";

   /**
    * String constant for [Inheritance Mask] special entry name.
    *
    * <p>(DS_MASK_NAME = "[Inheritance Mask]")
    */
   public static final String DS_MASK_NAME = "[Inheritance Mask]";

   /**
    * String constant for [Creator] special entry name. It
    * can only be used in the AddEntry method.
    *
    * <p>(DS_CREATOR_NAME = "[Creator]")
    */
   public static final String DS_CREATOR_NAME = "[Creator]";

   /**
    * String constant for [Self] special entry name. It
    * can only be used in the AddEntry method.
    *
    * <p>(DS_SELF_NAME = "[Self]")
    */
   public static final String DS_SELF_NAME = "[Self]";


    private static String[] compositeIds;
    private static final int matchingRules = equality|approximate;


   static
   {
      compositeIds = new String[3];

      compositeIds[0] = "protectedAttrName";
      compositeIds[1] = "subjectName";
      compositeIds[2] = "privileges";
   }

   /** @internal
    *
    */
   protected String protectedAttrName;

   /**
    * @internal
    */
   protected String subjectName;

   /**
    * @internal
    */
   protected int privileges;

   private String name;


   /**
    * Constructs an NdsObjectACL object based on the specified
    * protectedAttrName, subjectName, and privileges parameters.
    * 
    * @param protectedAttrName The name of the attribute to be
    *                           protected stored as a String value.
    * @param subjectName       The subject (trustee) name stored as a
    *                          String value.
    * @param privileges        The privileges containing a bit mask
    *                          identifying specific rights stored as
    *                          a long value.
    */
   public NdsObjectACL (
         String protectedAttrName,
         String subjectName,
         long privileges)
   {
      this (
               "",
               protectedAttrName,
               subjectName,
               (int) (privileges & INT_MASK));
   }

   /**
    * @internal
    */
   protected NdsObjectACL ()
   {

   }

   private NdsObjectACL (
         String name,
         String protectedAttrName,
         String subjectName,
         int privileges)
   {
      this.protectedAttrName = protectedAttrName;
      this.subjectName = subjectName;
      this.privileges = privileges;
      this.name = name;
   }

   /**
    * @internal
    */
   protected NdsObjectACL (
         NdsObjectACL anObjectACL)
   {
      this.protectedAttrName = anObjectACL.protectedAttrName;
      this.subjectName = anObjectACL.subjectName;
      this.privileges = anObjectACL.privileges;
      this.name = anObjectACL.name;
   }


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

   /**
    * Compares two objects for ordering, or compares two strings
    * lexicographically.
    *
    * The compareTo method does not apply to the ObjectACL 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. When matching for equality, the 
    * privilege set must match exactly for the comparison to succeed.
    *
    * <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 NdsObjectACL))
      {
         NdsObjectACL anotherObjectACL;

         anotherObjectACL = (NdsObjectACL) anObject;
         if (false == protectedAttrName.equals (anotherObjectACL.protectedAttrName))
         {
            return (false);
         }
         if (anotherObjectACL.subjectName != null)
         {
             if (false == subjectName.equals (anotherObjectACL.subjectName))
             {
                return (false);
             }
         }
         if (privileges != anotherObjectACL.privileges)
         {
            return (false);
         }
         return (true);
      }
      return (false);

   } /* equals () */

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

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


   // ******************** 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 protectedAttrName,
    *         subjectName and privileges, or NULL.
    */
   public SchemaValue getValue (
         String compositeId)
   {
      if (compositeId.equalsIgnoreCase (compositeIds[0]))
      {
         // getProtectedAttrName ();
         return (new NdsString (compositeIds[0], protectedAttrName));
      }
      else if (compositeId.equalsIgnoreCase (compositeIds[1]))
      {
         // getSubjectName ();
         return (new NdsString (compositeIds[1], subjectName));
      }
      else if (compositeId.equalsIgnoreCase (compositeIds[2]))
      {
         // getPrivileges ();
         return (new NdsInteger (compositeIds[2], privileges));
      }
      return (null);

    } /* getValue () */

   /**
    * Returns an enumeration of composite IDs.
    *
    * @return An enumeration of composite 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 the elements in this composite.
    *
    * @return An enumeration of the composite elements
    *         (protectedAttrName, subjectName and privileges).
    */
   public Enumeration getValues ()
   {
      Vector values = new Vector ();

      values.addElement (new NdsString (compositeIds[0], protectedAttrName));
      values.addElement (new NdsString (compositeIds[1], subjectName));
      values.addElement (new NdsInteger (compositeIds[2], privileges));
      return (values.elements ());
   }


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

  /**
   * Compares two Objects using the approximate equals matching rule.
   * It compares this object with the reference object in the anObject
   * parameter.
   * 
   * <p>An Object ACL value can protect either an object or an attribute.
   * The protected object is always the one that contains the ACL attribute.
   * If an ACL entry is to apply to the object as a whole, leave the
   * protected attribute name empty (NULL). If a specific attribute is
   * to be protected, name it in the ACL entry.
   * <p>You can match an ACL value against either a subject (trustee) or
   * a privilege set, or both, If the subject name is not to be considered
   * in the compariosn, specify it as NULL. If the privilege set is not
   * to be considered in the comparison, specify an approximate equals
   * match with a privilege set value of zero.
   * <p>When the approximate equals matching is used, set any bits in
   * the target that are set in the filter's privilege field. Any other
   * bits in the target are ignored. Values with the same protectedAttrName
   * and subjectName are considered to be duplicate and thus are not
   * permitted. The Protected Attribute Name conveys the attribute that
   * the ACL is protecting.
   * 
   * @param anObject The reference object with which to compare.
   *
   * @return A Boolean set to TRUE if any argument is not equal to
   *         NULL, otherwise set to FALSE.
   *
   * @exception NsiException The approximate() method is not supported
   *            for this syntax.
   */
   public boolean approximate (
         Object anObject)
      throws Exception
   {
      if ((anObject != null) && (anObject instanceof NdsObjectACL))
      {
         NdsObjectACL anotherObjectACL;

         anotherObjectACL = (NdsObjectACL) anObject;
         if (false == protectedAttrName.equals (anotherObjectACL.protectedAttrName))
         {
            return (false);
         }
         if (anotherObjectACL.subjectName != null)
         {
             if (false == subjectName.equals (anotherObjectACL.subjectName))
             {
                return (false);
             }
         }
         int result = privileges & anotherObjectACL.privileges;
         if (result != anotherObjectACL.privileges)
         {
            return (false);
         }
         return (true);
      }
      throw (new Exception ());

    } /* approximate () */

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

   /**
    * Checks to see if this object supports the specified
    * matching rules. The ObjectACL syntax supports both the
    * equality and approximate equals matching rules.
    *
    * @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
      {
         NdsObjectACL objectACL = (NdsObjectACL) super.clone ();

         objectACL.protectedAttrName = this.protectedAttrName;
         objectACL.subjectName = this.subjectName;
         objectACL.privileges = this.privileges;

         objectACL.name = this.name;

         return (objectACL);
      }
      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 (
         protectedAttrName + ";" +
         subjectName + ";" +
         String.valueOf (privileges));
   }


   // ******************** NdsObjectACL Class ********************

   /**
    * Returns the stored protectedAttrName variable as a
    * String value stored in the object data member.
    * 
    * @return The String value of protectedAttrName.
    */
   public String getProtectedAttrName ()
   {
      return (protectedAttrName);
   }

   /**
    * Returns the stored subjectName variable as a
    * String value stored in the object data member.
    * 
    * @return The String value of subjectName.
    */
   public String getSubjectName ()
   {
      return (subjectName);
   }

   /**
    * Returns the stored privileges variable as a long value stored
    * in the object data member.
    * 
    * @return The long value of the privileges variable.
    */
   public long getPrivileges ()
   {
      return (privileges & INT_MASK);
   }

}


