// Copyright(c) 1996,1997 ObjectSpace, Inc.
// Portions Copyright(c) 1995, 1996 Hewlett-Packard Company.

package COM.objectspace.jgl;

import java.util.Enumeration;

/**
 * An OrderedMultiSet is a container that is optimized for fast associative lookup. Items are
 * matched using equals(). When an item is inserted into a OrderedMultiSet, it is stored in a
 * data structure that allows the item to be found very quickly. Within the data
 * structure, the items are ordered according to a comparator object. By default, the
 * comparator is a HashComparator that orders objects based on their hash value.
 * An OrderedMultiSet may contain matching items.
 * <p>
 * OrderedMultiSets are useful when fast associate lookup is important and when index-based
 * lookup is unnecessary.
 * <p>
 * Strictly speaking, there is no reason why null is not a valid entry. However, most
 * comparators (including the default HashComparator) will fail and throw an exception
 * if you attempt to add a null entry because they cast the entry to a class and then
 * activate one of its methods. It is perfectly possible to hand-craft a comparator
 * that will accept null as a valid key.
 * <p>
 * There are many different approaches that could be used to implementing an associative
 * container. For example, most of the older libraries used a hashing scheme for
 * positioning and retrieving items. This implementation use a data structure called a
 * red-black tree. A red-black tree is a binary search tree that uses an extra field in
 * every node to store the node's color. Red-black trees constrain the way that nodes may
 * be colored in such a way that the tree remains reasonably balanced. This property is
 * important for ensuring a good overall performance - red-black trees guarantee that the
 * worst case performance for the most common dynamic set operations is O(log N). One
 * conseqence of using a binary tree for storage of data is that the items remain in a
 * sorted order. This allows JGL users to iterate through an associative container and
 * access its elements in a sequenced manner.
 * <p>
 * Insertion does not affect iterators or references.
 * <p>
 * Removal only invalidates the iterators and references to the removed elements.
 * <p>
 * @see COM.objectspace.jgl.OrderedSet
 * @see COM.objectspace.jgl.BinaryPredicate
 * @see COM.objectspace.jgl.SetOperations
 * @see COM.objectspace.jgl.examples.OrderedSetExamples
 * @version 2.0.2
 * @author ObjectSpace, Inc.
 * @deprecated
 * @see COM.objectspace.jgl.OrderedSet
 */

public class OrderedMultiSet extends OrderedSet
  {
  /**
   * Construct myself to be an empty OrderedMultiSet that orders elements based on
   * their hash value.
   */
  public OrderedMultiSet()
    {
    myTree = new Tree( false, true, this );
    }

  /**
   * Construct myself to be an empty OrderedMultiSet that orders elements using
   * a specified binary predicate.
   * @param comparator The predicate for ordering objects.
   */
  public OrderedMultiSet( BinaryPredicate comparator )
    {
    myTree = new Tree( false, true, comparator, this );
    }

  /**
   * Construct myself to be a shallow copy of an existing OrderedMultiSet.
   * @param set The OrderedMultiSet to copy.
   */
  public OrderedMultiSet( OrderedMultiSet set )
    {
    super( set );
    }

  /**
   * Return a shallow copy of myself.
   */
  public synchronized Object clone()
    {
    return new OrderedMultiSet( this );
    }

  /**
   * Become a shallow copy of an existing OrderedMultiSet.
   * @param set The OrderedMultiSet that I shall become a shallow copy of.
   */
  public synchronized void copy( OrderedMultiSet set )
    {
    super.copy( set );
    }

  /**
   * Return a string that describes me.
   */
  public synchronized String toString()
    {
    return Printing.toString( this, "OrderedMultiSet" );
    }

  /**
   * Return true if I'm equal to another object.
   * @param object The object to compare myself against.
   */
  public boolean equals( Object object )
    {
    return object instanceof OrderedMultiSet && equals( (OrderedMultiSet) object );
    }

  /**
   * Return true if I contain the same items in the same order as
   * another OrderedMultiSet. Use equals() to compare the individual elements.
   * @param set The OrderedMultiSet to compare myself against.
   */
  public synchronized boolean equals( OrderedMultiSet set )
    {
    return super.equals( set );
    }

  /**
   * Swap my contents with another OrderedMultiSet.
   * @param set The OrderedMultiSet that I will swap my contents with.
   */
  public synchronized void swap( OrderedMultiSet set )
    {
    super.swap( set );
    }
  }
