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

  $Archive: /njcl_v2rmi/src/com/novell/service/session/SessionAttrs.java $
  $Revision: 19 $
  $Modtime: 1/05/01 4:03p $

  Copyright (c) 1997 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.session;

import com.novell.service.jncpv2r.clx.*;
import com.novell.service.session.*;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Hashtable;
import com.novell.service.session.util.Debug;

/**
 * Provides for a  collection of session attribute objects (SessionAttr).
 */
public class SessionAttrs implements Serializable
{
   // Always access debug via final static...hopefully a final static of
   // false will be optimized out by the compiler
   final static private boolean DEBUG = false;
   final static private boolean I_DEBUG = false; // Ignore exception
   final static private boolean S_DEBUG = false; // May have side effects

  /**
   * @internal
   */
   protected Hashtable attributes = null;

   /**
    * Construct a new instance of a SessionAttrs object.
    *
    * @exception SessionException A top-level exception thrown by
    * Session objects. May be a subclass of SessionException.
    */
   public SessionAttrs
   (
   )
   throws SessionException
   {
      this.attributes = new Hashtable();
   }

   /**
    * Adds a new session attribute (attr) to this set. If a session attribute
    * already exists with the same ID as attr, the SessionAttrInUseException
    * is throw.
    *
    * @param attr The new session attribute to add.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public void add
   (
      SessionAttr attr
   )
   throws SessionException
   {
      if (this.attributes.get(
         attr.getSessionAttrId()) != null)
         throw new SessionAttrInUseException(
            attr.getSessionAttrId());
      this.attributes.put(
         attr.getSessionAttrId(),
         attr.clone());
   }

   /**
    * Adds a new session attribute to this set identified by attrId and
    * value parameters. If a session attribute already exists with the
    * same ID as attr, the SessionAttrInUseException is thrown.
    *
    * @param attrId  The new attribute ID to add.
    * @param value   The new attribute value to add.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    * @exception SessionAttrInUseException Thrown if attrId already exists.
    */
   public void add
   (
      String attrId,
      Object value
   )
   throws SessionException
   {
      add(new SessionAttr(attrId, value));
   }

   /**
    * Returns the number of attributes in this set.
    *
    * @return The number of attributes in the set.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public int count
   (
   )
   throws SessionException
   {
      return this.attributes.size();
   }

   /**
    * Returns the session attribute with the given session attribute ID
    * from this set. If no attrId matches, the SessionAttrNotFoundException
    * is thrown.
    *
    * @param attrId  The attribute ID to match.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    * @exception SessionAttrNotFoundException  Thrown if no attrId matches.
    */
   public SessionAttr get
   (
      String attrId
   )
   throws SessionException
   {
      Object o = this.attributes.get(attrId);
      if (null == o)
      {
         throw new SessionAttrNotFoundException(attrId);
      }
      return (SessionAttr)((SessionAttr)o).clone();
   }

   /**
    * Returns the session attribute with the passed-in session
    * attribute ID from this set.
    *
    * @return An object containing the session attribute value.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public Object getValue
   (
      String attrId
   )
   throws SessionException
   {
      SessionAttr a = (SessionAttr)get(attrId);
      Object value = a.getValue();
      return value;
   }

   /**
    * Returns an enumeration of the IDs of the attributes in this set.
    *
    * @return An Enumeration of attribute IDs.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public Enumeration getSessionAttrIds
   (
   )
   throws SessionException
   {
      return this.attributes.keys();
   }

   /**
    * Returns an enumeration of the attributes in this set.
    *
    * @return An enumeration of the attributes in this set.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public SessionAttrEnumerator getAttributes
   (
   )
   throws SessionException
   {
      return new SessionAttrEnumerator(this);
   }

   /**
    * Replaces the session attribute identified by the session attribute
    * ID of attr, or adds the session attribute if it does not exist.
    *
    * @param attr The session attribute to replace or add.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public void modify
   (
      SessionAttr attr
   )
   throws SessionException
   {
      this.attributes.put(
         attr.getSessionAttrId(),
         attr.clone());
   }

   /**
    * Replaces the session attribute identified by attrId with value,
    * or adds it if it does not exist.
    *
    * @param attrId  The attribute ID to replace or add.
    * @param value   The attribute value to replace or add.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public void modify
   (
      String attrId,
      Object value
   )
   throws SessionException
   {
      this.attributes.put(
         attrId,
         new SessionAttr(attrId, value));
   }

   /**
    * Replaces the attributes in this set by those in attributeSet, or
    * adds any that do not exist.
    *
    * @param attributeSet The attribute set to use during replace/modify.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public void modify
   (
      SessionAttrs attributeSet
   )
   throws SessionException
   {
      SessionAttrEnumerator enum = attributeSet.getAttributes();

      while (enum.hasMoreElements())
      {
         this.modify(
            enum.next());
      }
   }

   /**
    * Removes from this set the session attribute specified in the
    * passed in attrId parameter. If the session attribute does not
    * exist, the request is ignored.
    *
    * @param attrId The attribute ID to remove.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public void remove
   (
      String attrId
   )
   throws SessionException
   {
      this.attributes.remove(attrId);
   }

   /**
    * Merges two SessionAttrs specified in the passed in attributeSet
    * parameter. SessionAttrs existing in both sets will not be merged,
    * leaving the original SessionAttr.
    *
    * @param attributeSet The attribute set to merge.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public void merge
   (
      SessionAttrs attributeSet
   )
   throws SessionException
   {
      SessionAttrEnumerator enum = attributeSet.getAttributes();

      while (enum.hasMoreElements())
      {
         try
         {
            this.add(enum.next());
         }
         catch (SessionAttrInUseException e)
         {
            if (I_DEBUG)
            {
               Debug.ignoreException("merge failure", e);
            }
         }
      }
   }

   /**
    * Compares the passed-in attribute set with this SessionAttrs set.
    *
    * @param subSet The attribute set to match.
    *
    * @return A boolean set to TRUE if the passed in attribute set is a
    *         subset of this set and all attributes match, otherwise set
    *         to FALSE.
    *
    * @exception SessionException A top-level exception thrown by
    *            Session objects. May be a subclass of SessionException.
    */
   public boolean matchesSubset
   (
      SessionAttrs subSet
   )
   throws SessionException
   {
      boolean matches = true;

      SessionAttrEnumerator setEnum = subSet.getAttributes();
       // Iterate through attributes to match
      try
      {
         while (setEnum.hasMoreElements())
         {
            SessionAttr setAttr = setEnum.next();
             // Possible null return...caught in catch
            SessionAttr currentAttr = this.get(setAttr.getSessionAttrId());

             // Any failure is a complete failure.
            if (!setAttr.equals(currentAttr))
            {
               matches = false;
               break;
            }
         }
      }
      catch (Exception e)
      {
         matches = false;
      }
      return matches;
   }

   /**
    * @internal
    *
    * Returns a string that textually represents the sesson attributes.
    *
    * @return A string representation of the sesson attributes.
    */
   public String toString()
   {
      return "SessionAttrs$:" + attributes.toString();
   }
}

