/* Collections.java -- Utility class with methods to operate on collections
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.util;

import java.io.Serializable;

/**
 * Utility class consisting of static methods that operate on, or return
 * Collections. Contains methods to sort, search, reverse, fill and shuffle
 * Collections, methods to facilitate interoperability with legacy APIs that
 * are unaware of collections, a method to return a list which consists of
 * multiple copies of one element, and methods which "wrap" collections to give
 * them extra properties, such as thread-safety and unmodifiability.
 * <p>
 *
 * All methods which take a collection throw a {@link NullPointerException} if
 * that collection is null. Algorithms which can change a collection may, but
 * are not required, to throw the {@link UnsupportedOperationException} that
 * the underlying collection would throw during an attempt at modification.
 * For example,
 * <code>Collections.singleton("").addAll(Collections.EMPTY_SET)</code>
 * does not throw a exception, even though addAll is an unsupported operation
 * on a singleton; the reason for this is that addAll did not attempt to
 * modify the set.
 *
 * @author Original author unknown
 * @author Eric Blake (ebb9@email.byu.edu)
 * @see Collection
 * @see Set
 * @see List
 * @see Map
 * @see Arrays
 * @since 1.2
 * @status updated to 1.4
 */
public class Collections
{
  /**
   * Constant used to decide cutoff for when a non-RandomAccess list should
   * be treated as sequential-access. Basically, quadratic behavior is
   * acceptable for small lists when the overhead is so small in the first
   * place. I arbitrarily set it to 16, so it may need some tuning.
   */
  private static final int LARGE_LIST_SIZE = 16;

  /**
   * Determines if a list should be treated as a sequential-access one.
   * Rather than the old method of JDK 1.3 of assuming only instanceof
   * AbstractSequentialList should be sequential, this uses the new method
   * of JDK 1.4 of assuming anything that does NOT implement RandomAccess
   * and exceeds a large (unspecified) size should be sequential.
   *
   * @param l the list to check
   * @return <code>true</code> if it should be treated as sequential-access
   */
  private static boolean isSequential(List l)
  {
    return ! (l instanceof RandomAccess) && l.size() > LARGE_LIST_SIZE;
  }

  /**
   * This class is non-instantiable.
   */
  private Collections()
  {
  }

  /**
   * An immutable, serializable, empty Set.
   * @see Serializable
   */
  public static final Set EMPTY_SET = new EmptySet();

  /**
   * The implementation of {@link #EMPTY_SET}. This class name is required
   * for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class EmptySet extends AbstractSet
    implements Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 1582296315990362920L;

    /**
     * A private constructor adds overhead.
     */
    EmptySet()
    {
    }

    /**
     * The size: always 0!
     * @return 0.
     */
    public int size()
    {
      return 0;
    }

    /**
     * Returns an iterator that does not iterate.
     * @return A non-iterating iterator.
     */
    // This is really cheating! I think it's perfectly valid, though.
    public Iterator iterator()
    {
      return EMPTY_LIST.iterator();
    }

    // The remaining methods are optional, but provide a performance
    // advantage by not allocating unnecessary iterators in AbstractSet.
    /**
     * The empty set never contains anything.
     * @param o The object to search for.
     * @return <code>false</code>.
     */
    public boolean contains(Object o)
    {
      return false;
    }

    /**
     * This is true only if the given collection is also empty.
     * @param c The collection of objects which are to be compared
     *          against the members of this set.
     * @return <code>true</code> if c is empty.
     */
    public boolean containsAll(Collection c)
    {
      return c.isEmpty();
    }

    /**
     * Equal only if the other set is empty.
     * @param o The object to compare with this set.
     * @return <code>true</code> if o is an empty instance of <code>Set</code>.
     */
    public boolean equals(Object o)
    {
      return o instanceof Set && ((Set) o).isEmpty();
    }

    /**
     * The hashcode is always 0.
     * @return 0.
     */
    public int hashCode()
    {
      return 0;
    }

    /**
     * Always succeeds with a <code>false</code> result.
     * @param o The object to remove.
     * @return <code>false</code>.
     */
    public boolean remove(Object o)
    {
      return false;
    }

    /**
     * Always succeeds with a <code>false</code> result.
     * @param c The collection of objects which should
     *          all be removed from this set.
     * @return <code>false</code>.
     */
    public boolean removeAll(Collection c)
    {
      return false;
    }

    /**
     * Always succeeds with a <code>false</code> result.
     * @param c The collection of objects which should
     *          all be retained within this set.
     * @return <code>false</code>.
     */
    public boolean retainAll(Collection c)
    {
      return false;
    }

    /**
     * The array is always empty.
     * @return A new array with a size of 0.
     */
    public Object[] toArray()
    {
      return new Object[0];
    }

    /**
     * We don't even need to use reflection!
     * @param a An existing array, which can be empty.
     * @return The original array with any existing
     *         initial element set to null.
     */
    public Object[] toArray(Object[] a)
    {
      if (a.length > 0)
        a[0] = null;
      return a;
    }

    /**
     * The string never changes.
     *
     * @return the string "[]".
     */
    public String toString()
    {
      return "[]";
    }
  } // class EmptySet

  /**
   * An immutable, serializable, empty List, which implements RandomAccess.
   * @see Serializable
   * @see RandomAccess
   */
  public static final List EMPTY_LIST = new EmptyList();

  /**
   * The implementation of {@link #EMPTY_LIST}. This class name is required
   * for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class EmptyList extends AbstractList
    implements Serializable, RandomAccess
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 8842843931221139166L;

    /**
     * A private constructor adds overhead.
     */
    EmptyList()
    {
    }

    /**
     * The size is always 0.
     * @return 0.
     */
    public int size()
    {
      return 0;
    }

    /**
     * No matter the index, it is out of bounds.  This
     * method never returns, throwing an exception instead.
     *
     * @param index The index of the element to retrieve.
     * @return the object at the specified index.
     * @throws IndexOutOfBoundsException as any given index
     *         is outside the bounds of an empty array.
     */
    public Object get(int index)
    {
      throw new IndexOutOfBoundsException();
    }

    // The remaining methods are optional, but provide a performance
    // advantage by not allocating unnecessary iterators in AbstractList.
    /**
     * Never contains anything.
     * @param o The object to search for.
     * @return <code>false</code>.
     */
    public boolean contains(Object o)
    {
      return false;
    }

    /**
     * This is true only if the given collection is also empty.
     * @param c The collection of objects, which should be compared
     *          against the members of this list.
     * @return <code>true</code> if c is also empty. 
     */
    public boolean containsAll(Collection c)
    {
      return c.isEmpty();
    }

    /**
     * Equal only if the other list is empty.
     * @param o The object to compare against this list.
     * @return <code>true</code> if o is also an empty instance of
     *         <code>List</code>.
     */
    public boolean equals(Object o)
    {
      return o instanceof List && ((List) o).isEmpty();
    }

    /**
     * The hashcode is always 1.
     * @return 1.
     */
    public int hashCode()
    {
      return 1;
    }

    /**
     * Returns -1.
     * @param o The object to search for.
     * @return -1.
     */
    public int indexOf(Object o)
    {
      return -1;
    }

    /**
     * Returns -1.
     * @param o The object to search for.
     * @return -1.
     */
    public int lastIndexOf(Object o)
    {
      return -1;
    }

    /**
     * Always succeeds with <code>false</code> result.
     * @param o The object to remove.
     * @return -1.
     */
    public boolean remove(Object o)
    {
      return false;
    }

    /**
     * Always succeeds with <code>false</code> result.
     * @param c The collection of objects which should
     *          all be removed from this list.
     * @return <code>false</code>.
     */
    public boolean removeAll(Collection c)
    {
      return false;
    }

    /**
     * Always succeeds with <code>false</code> result.
     * @param c The collection of objects which should
     *          all be retained within this list.
     * @return <code>false</code>.
     */
    public boolean retainAll(Collection c)
    {
      return false;
    }

    /**
     * The array is always empty.
     * @return A new array with a size of 0.
     */
    public Object[] toArray()
    {
      return new Object[0];
    }

    /**
     * We don't even need to use reflection!
     * @param a An existing array, which can be empty.
     * @return The original array with any existing
     *         initial element set to null.
     */
    public Object[] toArray(Object[] a)
    {
      if (a.length > 0)
        a[0] = null;
      return a;
    }

    /**
     * The string never changes.
     *
     * @return the string "[]".
     */
    public String toString()
    {
      return "[]";
    }
  } // class EmptyList

  /**
   * An immutable, serializable, empty Map.
   * @see Serializable
   */
  public static final Map EMPTY_MAP = new EmptyMap();

  /**
   * The implementation of {@link #EMPTY_MAP}. This class name is required
   * for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class EmptyMap extends AbstractMap
    implements Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 6428348081105594320L;

    /**
     * A private constructor adds overhead.
     */
    EmptyMap()
    {
    }

    /**
     * There are no entries.
     * @return The empty set.
     */
    public Set entrySet()
    {
      return EMPTY_SET;
    }

    // The remaining methods are optional, but provide a performance
    // advantage by not allocating unnecessary iterators in AbstractMap.
    /**
     * No entries!
     * @param key The key to search for.
     * @return <code>false</code>.
     */
    public boolean containsKey(Object key)
    {
      return false;
    }

    /**
     * No entries!
     * @param value The value to search for.
     * @return <code>false</code>.
     */
    public boolean containsValue(Object value)
    {
      return false;
    }

    /**
     * Equal to all empty maps.
     * @param o The object o to compare against this map.
     * @return <code>true</code> if o is also an empty instance of
     *         <code>Map</code>.
     */
    public boolean equals(Object o)
    {
      return o instanceof Map && ((Map) o).isEmpty();
    }

    /**
     * No mappings, so this returns null.
     * @param o The key of the object to retrieve.
     * @return null. 
     */
    public Object get(Object o)
    {
      return null;
    }

    /**
     * The hashcode is always 0.
     * @return 0.
     */
    public int hashCode()
    {
      return 0;
    }

    /**
     * No entries.
     * @return The empty set.
     */
    public Set keySet()
    {
      return EMPTY_SET;
    }

    /**
     * Remove always succeeds, with null result.
     * @param o The key of the mapping to remove.
     * @return null, as there is never a mapping for o.
     */
    public Object remove(Object o)
    {
      return null;
    }

    /**
     * Size is always 0.
     * @return 0.
     */
    public int size()
    {
      return 0;
    }

    /**
     * No entries. Technically, EMPTY_SET, while more specific than a general
     * Collection, will work. Besides, that's what the JDK uses!
     * @return The empty set.
     */
    public Collection values()
    {
      return EMPTY_SET;
    }

    /**
     * The string never changes.
     *
     * @return the string "[]".
     */
    public String toString()
    {
      return "[]";
    }
  } // class EmptyMap


  /**
   * Compare two objects with or without a Comparator. If c is null, uses the
   * natural ordering. Slightly slower than doing it inline if the JVM isn't
   * clever, but worth it for removing a duplicate of the search code.
   * Note: This code is also used in Arrays (for sort as well as search).
   */
  static final int compare(Object o1, Object o2, Comparator c)
  {
    return c == null ? ((Comparable) o1).compareTo(o2) : c.compare(o1, o2);
  }

  /**
   * Perform a binary search of a List for a key, using the natural ordering of
   * the elements. The list must be sorted (as by the sort() method) - if it is
   * not, the behavior of this method is undefined, and may be an infinite
   * loop. Further, the key must be comparable with every item in the list. If
   * the list contains the key more than once, any one of them may be found.
   * <p>
   *
   * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
   * and uses a linear search with O(n) link traversals and log(n) comparisons
   * with {@link AbstractSequentialList} lists. Note: although the
   * specification allows for an infinite loop if the list is unsorted, it will
   * not happen in this (Classpath) implementation.
   *
   * @param l the list to search (must be sorted)
   * @param key the value to search for
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value
   * @throws ClassCastException if key could not be compared with one of the
   *         elements of l
   * @throws NullPointerException if a null element has compareTo called
   * @see #sort(List)
   */
  public static int binarySearch(List l, Object key)
  {
    return binarySearch(l, key, null);
  }

  /**
   * Perform a binary search of a List for a key, using a supplied Comparator.
   * The list must be sorted (as by the sort() method with the same Comparator)
   * - if it is not, the behavior of this method is undefined, and may be an
   * infinite loop. Further, the key must be comparable with every item in the
   * list. If the list contains the key more than once, any one of them may be
   * found. If the comparator is null, the elements' natural ordering is used.
   * <p>
   *
   * This algorithm behaves in log(n) time for {@link RandomAccess} lists,
   * and uses a linear search with O(n) link traversals and log(n) comparisons
   * with {@link AbstractSequentialList} lists. Note: although the
   * specification allows for an infinite loop if the list is unsorted, it will
   * not happen in this (Classpath) implementation.
   *
   * @param l the list to search (must be sorted)
   * @param key the value to search for
   * @param c the comparator by which the list is sorted
   * @return the index at which the key was found, or -n-1 if it was not
   *         found, where n is the index of the first value higher than key or
   *         a.length if there is no such value
   * @throws ClassCastException if key could not be compared with one of the
   *         elements of l
   * @throws NullPointerException if a null element is compared with natural
   *         ordering (only possible when c is null)
   * @see #sort(List, Comparator)
   */
  public static int binarySearch(List l, Object key, Comparator c)
  {
    int pos = 0;
    int low = 0;
    int hi = l.size() - 1;

    // We use a linear search with log(n) comparisons using an iterator
    // if the list is sequential-access.
    if (isSequential(l))
      {
	ListIterator itr = l.listIterator();
        int i = 0;
	Object o = itr.next(); // Assumes list is not empty (see isSequential)
	boolean forward = true;
        while (low <= hi)
          {
            pos = (low + hi) >> 1;
            if (i < pos)
	      {
		if (!forward)
		  itr.next(); // Changing direction first.
		for ( ; i != pos; i++, o = itr.next());
		forward = true;
	      }
            else
	      {
		if (forward)
		  itr.previous(); // Changing direction first.
		for ( ; i != pos; i--, o = itr.previous());
		forward = false;
	      }
	    final int d = compare(o, key, c);
	    if (d == 0)
              return pos;
	    else if (d > 0)
              hi = pos - 1;
	    else
              // This gets the insertion point right on the last loop
              low = ++pos;
          }
      }
    else
      {
	while (low <= hi)
	  {
	    pos = (low + hi) >> 1;
	    final int d = compare(l.get(pos), key, c);
	    if (d == 0)
              return pos;
	    else if (d > 0)
              hi = pos - 1;
	    else
              // This gets the insertion point right on the last loop
              low = ++pos;
	  }
      }

    // If we failed to find it, we do the same whichever search we did.
    return -pos - 1;
  }

  /**
   * Copy one list to another. If the destination list is longer than the
   * source list, the remaining elements are unaffected. This method runs in
   * linear time.
   *
   * @param dest the destination list
   * @param source the source list
   * @throws IndexOutOfBoundsException if the destination list is shorter
   *         than the source list (the destination will be unmodified)
   * @throws UnsupportedOperationException if dest.listIterator() does not
   *         support the set operation
   */
  public static void copy(List dest, List source)
  {
    int pos = source.size();
    if (dest.size() < pos)
      throw new IndexOutOfBoundsException("Source does not fit in dest");

    Iterator i1 = source.iterator();
    ListIterator i2 = dest.listIterator();

    while (--pos >= 0)
      {
        i2.next();
        i2.set(i1.next());
      }
  }

  /**
   * Returns an Enumeration over a collection. This allows interoperability
   * with legacy APIs that require an Enumeration as input.
   *
   * @param c the Collection to iterate over
   * @return an Enumeration backed by an Iterator over c
   */
  public static Enumeration enumeration(Collection c)
  {
    final Iterator i = c.iterator();
    return new Enumeration()
    {
      /**
       * Returns <code>true</code> if there are more elements to
       * be enumerated.
       *
       * @return The result of <code>hasNext()</code>
       *         called on the underlying iterator.
       */
      public final boolean hasMoreElements()
      {
	return i.hasNext();
      }

      /**
       * Returns the next element to be enumerated.
       *
       * @return The result of <code>next()</code>
       *         called on the underlying iterator.
       */
      public final Object nextElement()
      {
	return i.next();
      }
    };
  }

  /**
   * Replace every element of a list with a given value. This method runs in
   * linear time.
   *
   * @param l the list to fill.
   * @param val the object to vill the list with.
   * @throws UnsupportedOperationException if l.listIterator() does not
   *         support the set operation.
   */
  public static void fill(List l, Object val)
  {
    ListIterator itr = l.listIterator();
    for (int i = l.size() - 1; i >= 0; --i)
      {
	itr.next();
	itr.set(val);
      }
  }

  /**
   * Returns the starting index where the specified sublist first occurs
   * in a larger list, or -1 if there is no matching position. If
   * <code>target.size() &gt; source.size()</code>, this returns -1,
   * otherwise this implementation uses brute force, checking for
   * <code>source.sublist(i, i + target.size()).equals(target)</code>
   * for all possible i.
   *
   * @param source the list to search
   * @param target the sublist to search for
   * @return the index where found, or -1
   * @since 1.4
   */
  public static int indexOfSubList(List source, List target)
  {
    int ssize = source.size();
    for (int i = 0, j = target.size(); j <= ssize; i++, j++)
      if (source.subList(i, j).equals(target))
        return i;
    return -1;
  }

  /**
   * Returns the starting index where the specified sublist last occurs
   * in a larger list, or -1 if there is no matching position. If
   * <code>target.size() &gt; source.size()</code>, this returns -1,
   * otherwise this implementation uses brute force, checking for
   * <code>source.sublist(i, i + target.size()).equals(target)</code>
   * for all possible i.
   *
   * @param source the list to search
   * @param target the sublist to search for
   * @return the index where found, or -1
   * @since 1.4
   */
  public static int lastIndexOfSubList(List source, List target)
  {
    int ssize = source.size();
    for (int i = ssize - target.size(), j = ssize; i >= 0; i--, j--)
      if (source.subList(i, j).equals(target))
        return i;
    return -1;
  }

  /**
   * Returns an ArrayList holding the elements visited by a given
   * Enumeration. This method exists for interoperability between legacy
   * APIs and the new Collection API.
   *
   * @param e the enumeration to put in a list
   * @return a list containing the enumeration elements
   * @see ArrayList
   * @since 1.4
   */
  public static ArrayList list(Enumeration e)
  {
    ArrayList l = new ArrayList();
    while (e.hasMoreElements())
      l.add(e.nextElement());
    return l;
  }

  /**
   * Find the maximum element in a Collection, according to the natural
   * ordering of the elements. This implementation iterates over the
   * Collection, so it works in linear time.
   *
   * @param c the Collection to find the maximum element of
   * @return the maximum element of c
   * @exception NoSuchElementException if c is empty
   * @exception ClassCastException if elements in c are not mutually comparable
   * @exception NullPointerException if null.compareTo is called
   */
  public static Object max(Collection c)
  {
    return max(c, null);
  }

  /**
   * Find the maximum element in a Collection, according to a specified
   * Comparator. This implementation iterates over the Collection, so it
   * works in linear time.
   *
   * @param c the Collection to find the maximum element of
   * @param order the Comparator to order the elements by, or null for natural
   *        ordering
   * @return the maximum element of c
   * @throws NoSuchElementException if c is empty
   * @throws ClassCastException if elements in c are not mutually comparable
   * @throws NullPointerException if null is compared by natural ordering
   *        (only possible when order is null)
   */
  public static Object max(Collection c, Comparator order)
  {
    Iterator itr = c.iterator();
    Object max = itr.next(); // throws NoSuchElementException
    int csize = c.size();
    for (int i = 1; i < csize; i++)
      {
	Object o = itr.next();
	if (compare(max, o, order) < 0)
	  max = o;
      }
    return max;
  }

  /**
   * Find the minimum element in a Collection, according to the natural
   * ordering of the elements. This implementation iterates over the
   * Collection, so it works in linear time.
   *
   * @param c the Collection to find the minimum element of
   * @return the minimum element of c
   * @throws NoSuchElementException if c is empty
   * @throws ClassCastException if elements in c are not mutually comparable
   * @throws NullPointerException if null.compareTo is called
   */
  public static Object min(Collection c)
  {
    return min(c, null);
  }

  /**
   * Find the minimum element in a Collection, according to a specified
   * Comparator. This implementation iterates over the Collection, so it
   * works in linear time.
   *
   * @param c the Collection to find the minimum element of
   * @param order the Comparator to order the elements by, or null for natural
   *        ordering
   * @return the minimum element of c
   * @throws NoSuchElementException if c is empty
   * @throws ClassCastException if elements in c are not mutually comparable
   * @throws NullPointerException if null is compared by natural ordering
   *        (only possible when order is null)
   */
  public static Object min(Collection c, Comparator order)
  {
    Iterator itr = c.iterator();
    Object min = itr.next();	// throws NoSuchElementExcception
    int csize = c.size();
    for (int i = 1; i < csize; i++)
      {
	Object o = itr.next();
	if (compare(min, o, order) > 0)
	  min = o;
      }
    return min;
  }

  /**
   * Creates an immutable list consisting of the same object repeated n times.
   * The returned object is tiny, consisting of only a single reference to the
   * object and a count of the number of elements. It is Serializable, and
   * implements RandomAccess. You can use it in tandem with List.addAll for
   * fast list construction.
   *
   * @param n the number of times to repeat the object
   * @param o the object to repeat
   * @return a List consisting of n copies of o
   * @throws IllegalArgumentException if n &lt; 0
   * @see List#addAll(Collection)
   * @see Serializable
   * @see RandomAccess
   */
  public static List nCopies(final int n, final Object o)
  {
    return new CopiesList(n, o);
  }

  /**
   * The implementation of {@link #nCopies(int, Object)}. This class name
   * is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class CopiesList extends AbstractList
    implements Serializable, RandomAccess
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 2739099268398711800L;

    /**
     * The count of elements in this list.
     * @serial the list size
     */
    private final int n;

    /**
     * The repeated list element.
     * @serial the list contents
     */
    private final Object element;

    /**
     * Constructs the list.
     *
     * @param n the count
     * @param o the object
     * @throws IllegalArgumentException if n &lt; 0
     */
    CopiesList(int n, Object o)
    {
      if (n < 0)
	throw new IllegalArgumentException();
      this.n = n;
      element = o;
    }

    /**
     * The size is fixed.
     * @return The size of the list.
     */
    public int size()
    {
      return n;
    }

    /**
     * The same element is returned.
     * @param index The index of the element to be returned (irrelevant
     *        as the list contains only copies of <code>element</code>).
     * @return The element used by this list.
     */
    public Object get(int index)
    {
      if (index < 0 || index >= n)
        throw new IndexOutOfBoundsException();
      return element;
    }

    // The remaining methods are optional, but provide a performance
    // advantage by not allocating unnecessary iterators in AbstractList.
    /**
     * This list only contains one element.
     * @param o The object to search for.
     * @return <code>true</code> if o is the element used by this list.
     */
    public boolean contains(Object o)
    {
      return n > 0 && equals(o, element);
    }

    /**
     * The index is either 0 or -1.
     * @param o The object to find the index of.
     * @return 0 if <code>o == element</code>, -1 if not.
     */
    public int indexOf(Object o)
    {
      return (n > 0 && equals(o, element)) ? 0 : -1;
    }

    /**
     * The index is either n-1 or -1.
     * @param o The object to find the last index of.
     * @return The last index in the list if <code>o == element</code>,
     *         -1 if not.
     */
    public int lastIndexOf(Object o)
    {
      return equals(o, element) ? n - 1 : -1;
    }

    /**
     * A subList is just another CopiesList.
     * @param from The starting bound of the sublist.
     * @param to The ending bound of the sublist.
     * @return A list of copies containing <code>from - to</code>
     *         elements, all of which are equal to the element
     *         used by this list.
     */
    public List subList(int from, int to)
    {
      if (from < 0 || to > n)
        throw new IndexOutOfBoundsException();
      return new CopiesList(to - from, element);
    }

    /**
     * The array is easy.
     * @return An array of size n filled with copies of
     *         the element used by this list.
     */
    public Object[] toArray()
    {
      Object[] a = new Object[n];
      Arrays.fill(a, element);
      return a;
    }

    /**
     * The string is easy to generate.
     * @return A string representation of the list.
     */
    public String toString()
    {
      StringBuffer r = new StringBuffer("{");
      for (int i = n - 1; --i > 0; )
        r.append(element).append(", ");
      r.append(element).append("}");
      return r.toString();
    }
  } // class CopiesList

  /**
   * Replace all instances of one object with another in the specified list.
   * The list does not change size. An element e is replaced if
   * <code>oldval == null ? e == null : oldval.equals(e)</code>.
   *
   * @param list the list to iterate over
   * @param oldval the element to replace
   * @param newval the new value for the element
   * @return <code>true</code> if a replacement occurred.
   * @throws UnsupportedOperationException if the list iterator does not allow
   *         for the set operation
   * @throws ClassCastException if newval is of a type which cannot be added
   *         to the list
   * @throws IllegalArgumentException if some other aspect of newval stops
   *         it being added to the list
   * @since 1.4
   */
  public static boolean replaceAll(List list, Object oldval, Object newval)
  {
    ListIterator itr = list.listIterator();
    boolean replace_occured = false;
    for (int i = list.size(); --i >= 0; )
      if (AbstractCollection.equals(oldval, itr.next()))
        {
          itr.set(newval);
          replace_occured = true;
        }
    return replace_occured;
  }

  /**
   * Reverse a given list. This method works in linear time.
   *
   * @param l the list to reverse
   * @throws UnsupportedOperationException if l.listIterator() does not
   *         support the set operation
   */
  public static void reverse(List l)
  {
    ListIterator i1 = l.listIterator();
    int pos1 = 1;
    int pos2 = l.size();
    ListIterator i2 = l.listIterator(pos2);
    while (pos1 < pos2)
      {
	Object o = i1.next();
	i1.set(i2.previous());
	i2.set(o);
	++pos1;
	--pos2;
      }
  }

  /**
   * Get a comparator that implements the reverse of natural ordering. In
   * other words, this sorts Comparable objects opposite of how their
   * compareTo method would sort. This makes it easy to sort into reverse
   * order, by simply passing Collections.reverseOrder() to the sort method.
   * The return value of this method is Serializable.
   *
   * @return a comparator that imposes reverse natural ordering
   * @see Comparable
   * @see Serializable
   */
  public static Comparator reverseOrder()
  {
    return rcInstance;
  }

  /**
   * The object for {@link #reverseOrder()}.
   */
  private static final ReverseComparator rcInstance = new ReverseComparator();

  /**
   * The implementation of {@link #reverseOrder()}. This class name
   * is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class ReverseComparator
    implements Comparator, Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 7207038068494060240L;

    /**
     * A private constructor adds overhead.
     */
    ReverseComparator()
    {
    }

    /**
     * Compare two objects in reverse natural order.
     *
     * @param a the first object
     * @param b the second object
     * @return &lt;, ==, or &gt; 0 according to b.compareTo(a)
     */
    public int compare(Object a, Object b)
    {
      return ((Comparable) b).compareTo(a);
    }
  }

  /**
   * Rotate the elements in a list by a specified distance. After calling this
   * method, the element now at index <code>i</code> was formerly at index
   * <code>(i - distance) mod list.size()</code>. The list size is unchanged.
   * <p>
   *
   * For example, suppose a list contains <code>[t, a, n, k, s]</code>. After
   * either <code>Collections.rotate(l, 4)</code> or
   * <code>Collections.rotate(l, -1)</code>, the new contents are
   * <code>[s, t, a, n, k]</code>. This can be applied to sublists to rotate
   * just a portion of the list. For example, to move element <code>a</code>
   * forward two positions in the original example, use
   * <code>Collections.rotate(l.subList(1, 3+1), -1)</code>, which will
   * result in <code>[t, n, k, a, s]</code>.
   * <p>
   *
   * If the list is small or implements {@link RandomAccess}, the
   * implementation exchanges the first element to its destination, then the
   * displaced element, and so on until a circuit has been completed. The
   * process is repeated if needed on the second element, and so forth, until
   * all elements have been swapped.  For large non-random lists, the
   * implementation breaks the list into two sublists at index
   * <code>-distance mod size</code>, calls {@link #reverse(List)} on the
   * pieces, then reverses the overall list.
   *
   * @param list the list to rotate
   * @param distance the distance to rotate by; unrestricted in value
   * @throws UnsupportedOperationException if the list does not support set
   * @since 1.4
   */
  public static void rotate(List list, int distance)
  {
    int size = list.size();
    if (size == 0)
      return;
    distance %= size;
    if (distance == 0)
      return;
    if (distance < 0)
      distance += size;

    if (isSequential(list))
      {
        reverse(list);
        reverse(list.subList(0, distance));
        reverse(list.subList(distance, size));
      }
    else
      {
        // Determine the least common multiple of distance and size, as there
        // are (distance / LCM) loops to cycle through.
        int a = size;
        int lcm = distance;
        int b = a % lcm;
        while (b != 0)
          {
            a = lcm;
            lcm = b;
            b = a % lcm;
          }

        // Now, make the swaps. We must take the remainder every time through
        // the inner loop so that we don't overflow i to negative values.
        while (--lcm >= 0)
          {
            Object o = list.get(lcm);
            for (int i = lcm + distance; i != lcm; i = (i + distance) % size)
              o = list.set(i, o);
            list.set(lcm, o);
          }
      }
  }

  /**
   * Shuffle a list according to a default source of randomness. The algorithm
   * used iterates backwards over the list, swapping each element with an
   * element randomly selected from the elements in positions less than or
   * equal to it (using r.nextInt(int)).
   * <p>
   *
   * This algorithm would result in a perfectly fair shuffle (that is, each
   * element would have an equal chance of ending up in any position) if r were
   * a perfect source of randomness. In practice the results are merely very
   * close to perfect.
   * <p>
   *
   * This method operates in linear time. To do this on large lists which do
   * not implement {@link RandomAccess}, a temporary array is used to acheive
   * this speed, since it would be quadratic access otherwise.
   *
   * @param l the list to shuffle
   * @throws UnsupportedOperationException if l.listIterator() does not
   *         support the set operation
   */
  public static void shuffle(List l)
  {
    if (defaultRandom == null)
      {
        synchronized (Collections.class)
	{
	  if (defaultRandom == null)
            defaultRandom = new Random();
	}
      }
    shuffle(l, defaultRandom);
  }

  /**
   * Cache a single Random object for use by shuffle(List). This improves
   * performance as well as ensuring that sequential calls to shuffle() will
   * not result in the same shuffle order occurring: the resolution of
   * System.currentTimeMillis() is not sufficient to guarantee a unique seed.
   */
  private static Random defaultRandom = null;

  /**
   * Shuffle a list according to a given source of randomness. The algorithm
   * used iterates backwards over the list, swapping each element with an
   * element randomly selected from the elements in positions less than or
   * equal to it (using r.nextInt(int)).
   * <p>
   *
   * This algorithm would result in a perfectly fair shuffle (that is, each
   * element would have an equal chance of ending up in any position) if r were
   * a perfect source of randomness. In practise (eg if r = new Random()) the
   * results are merely very close to perfect.
   * <p>
   *
   * This method operates in linear time. To do this on large lists which do
   * not implement {@link RandomAccess}, a temporary array is used to acheive
   * this speed, since it would be quadratic access otherwise.
   *
   * @param l the list to shuffle
   * @param r the source of randomness to use for the shuffle
   * @throws UnsupportedOperationException if l.listIterator() does not
   *         support the set operation
   */
  public static void shuffle(List l, Random r)
  {
    int lsize = l.size();
    ListIterator i = l.listIterator(lsize);
    boolean sequential = isSequential(l);
    Object[] a = null; // stores a copy of the list for the sequential case

    if (sequential)
      a = l.toArray();

    for (int pos = lsize - 1; pos > 0; --pos)
      {
	// Obtain a random position to swap with. pos + 1 is used so that the
	// range of the random number includes the current position.
	int swap = r.nextInt(pos + 1);

	// Swap the desired element.
	Object o;
        if (sequential)
          {
            o = a[swap];
            a[swap] = i.previous();
          }
        else
          o = l.set(swap, i.previous());

	i.set(o);
      }
  }


  /**
   * Obtain an immutable Set consisting of a single element. The return value
   * of this method is Serializable.
   *
   * @param o the single element
   * @return an immutable Set containing only o
   * @see Serializable
   */
  public static Set singleton(Object o)
  {
    return new SingletonSet(o);
  }

  /**
   * The implementation of {@link #singleton(Object)}. This class name
   * is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class SingletonSet extends AbstractSet
    implements Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 3193687207550431679L;


    /**
     * The single element; package visible for use in nested class.
     * @serial the singleton
     */
    final Object element;

    /**
     * Construct a singleton.
     * @param o the element
     */
    SingletonSet(Object o)
    {
      element = o;
    }

    /**
     * The size: always 1!
     * @return 1.
     */
    public int size()
    {
      return 1;
    }

    /**
     * Returns an iterator over the lone element.
     */
    public Iterator iterator()
    {
      return new Iterator()
      {
	/**
	 * Flag to indicate whether or not the element has
	 * been retrieved.
	 */
        private boolean hasNext = true;

	/**
	 * Returns <code>true</code> if elements still remain to be
	 * iterated through.
	 *
	 * @return <code>true</code> if the element has not yet been returned.
	 */
        public boolean hasNext()
        {
          return hasNext;
        }

	/**
	 * Returns the element.
	 *
	 * @return The element used by this singleton.
	 * @throws NoSuchElementException if the object
	 *         has already been retrieved.
	 */ 
        public Object next()
        {
          if (hasNext)
          {
            hasNext = false;
            return element;
          }
          else
            throw new NoSuchElementException();
        }

	/**
	 * Removes the element from the singleton.
	 * As this set is immutable, this will always
	 * throw an exception.
	 *
	 * @throws UnsupportedOperationException as the
	 *         singleton set doesn't support
	 *         <code>remove()</code>.
	 */
        public void remove()
        {
          throw new UnsupportedOperationException();
        }
      };
    }

    // The remaining methods are optional, but provide a performance
    // advantage by not allocating unnecessary iterators in AbstractSet.
    /**
     * The set only contains one element.
     *
     * @param o The object to search for.
     * @return <code>true</code> if o == the element of the singleton.
     */
    public boolean contains(Object o)
    {
      return equals(o, element);
    }

    /**
     * This is true if the other collection only contains the element.
     *
     * @param c A collection to compare against this singleton.
     * @return <code>true</code> if c only contains either no elements or
     *         elements equal to the element in this singleton.
     */
    public boolean containsAll(Collection c)
    {
      Iterator i = c.iterator();
      int pos = c.size();
      while (--pos >= 0)
        if (! equals(i.next(), element))
          return false;
      return true;
    }

    /**
     * The hash is just that of the element.
     * 
     * @return The hashcode of the element.
     */
    public int hashCode()
    {
      return hashCode(element);
    }

    /**
     * Returning an array is simple.
     *
     * @return An array containing the element.
     */
    public Object[] toArray()
    {
      return new Object[] {element};
    }

    /**
     * Obvious string.
     *
     * @return The string surrounded by enclosing
     *         square brackets.
     */
    public String toString()
    {
      return "[" + element + "]";
    }
  } // class SingletonSet

  /**
   * Obtain an immutable List consisting of a single element. The return value
   * of this method is Serializable, and implements RandomAccess.
   *
   * @param o the single element
   * @return an immutable List containing only o
   * @see Serializable
   * @see RandomAccess
   * @since 1.3
   */
  public static List singletonList(Object o)
  {
    return new SingletonList(o);
  }

  /**
   * The implementation of {@link #singletonList(Object)}. This class name
   * is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class SingletonList extends AbstractList
    implements Serializable, RandomAccess
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 3093736618740652951L;

    /**
     * The single element.
     * @serial the singleton
     */
    private final Object element;

    /**
     * Construct a singleton.
     * @param o the element
     */
    SingletonList(Object o)
    {
      element = o;
    }

    /**
     * The size: always 1!
     * @return 1.
     */
    public int size()
    {
      return 1;
    }

    /**
     * Only index 0 is valid.
     * @param index The index of the element
     *        to retrieve.
     * @return The singleton's element if the
     *         index is 0.
     * @throws IndexOutOfBoundsException if
     *         index is not 0.
     */
    public Object get(int index)
    {
      if (index == 0)
        return element;
      throw new IndexOutOfBoundsException();
    }

    // The remaining methods are optional, but provide a performance
    // advantage by not allocating unnecessary iterators in AbstractList.
    /**
     * The set only contains one element.
     *
     * @param o The object to search for.
     * @return <code>true</code> if o == the singleton element.
     */
    public boolean contains(Object o)
    {
      return equals(o, element);
    }

    /**
     * This is true if the other collection only contains the element.
     *
     * @param c A collection to compare against this singleton.
     * @return <code>true</code> if c only contains either no elements or
     *         elements equal to the element in this singleton.
     */
    public boolean containsAll(Collection c)
    {
      Iterator i = c.iterator();
      int pos = c.size();
      while (--pos >= 0)
        if (! equals(i.next(), element))
          return false;
      return true;
    }

    /**
     * Speed up the hashcode computation.
     *
     * @return The hashcode of the list, based
     *         on the hashcode of the singleton element.
     */
    public int hashCode()
    {
      return 31 + hashCode(element);
    }

    /**
     * Either the list has it or not.
     *
     * @param o The object to find the first index of.
     * @return 0 if o is the singleton element, -1 if not.
     */
    public int indexOf(Object o)
    {
      return equals(o, element) ? 0 : -1;
    }

    /**
     * Either the list has it or not.
     *
     * @param o The object to find the last index of.
     * @return 0 if o is the singleton element, -1 if not.
     */
    public int lastIndexOf(Object o)
    {
      return equals(o, element) ? 0 : -1;
    }

    /**
     * Sublists are limited in scope.
     * 
     * @param from The starting bound for the sublist.
     * @param to The ending bound for the sublist.
     * @return Either an empty list if both bounds are
     *         0 or 1, or this list if the bounds are 0 and 1.
     * @throws IllegalArgumentException if <code>from > to</code>
     * @throws IndexOutOfBoundsException if either bound is greater
     *         than 1.
     */
    public List subList(int from, int to)
    {
      if (from == to && (to == 0 || to == 1))
        return EMPTY_LIST;
      if (from == 0 && to == 1)
        return this;
      if (from > to)
        throw new IllegalArgumentException();
      throw new IndexOutOfBoundsException();
    }

    /**
     * Returning an array is simple.
     *
     * @return An array containing the element.
     */
    public Object[] toArray()
    {
      return new Object[] {element};
    }

    /**
     * Obvious string.
     *
     * @return The string surrounded by enclosing
     *         square brackets. 
     */
    public String toString()
    {
      return "[" + element + "]";
    }
  } // class SingletonList

  /**
   * Obtain an immutable Map consisting of a single key-value pair.
   * The return value of this method is Serializable.
   *
   * @param key the single key
   * @param value the single value
   * @return an immutable Map containing only the single key-value pair
   * @see Serializable
   * @since 1.3
   */
  public static Map singletonMap(Object key, Object value)
  {
    return new SingletonMap(key, value);
  }

  /**
   * The implementation of {@link #singletonMap(Object, Object)}. This class
   * name is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class SingletonMap extends AbstractMap
    implements Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -6979724477215052911L;

    /**
     * The single key.
     * @serial the singleton key
     */
    private final Object k;

    /**
     * The corresponding value.
     * @serial the singleton value
     */
    private final Object v;

    /**
     * Cache the entry set.
     */
    private transient Set entries;

    /**
     * Construct a singleton.
     * @param key the key
     * @param value the value
     */
    SingletonMap(Object key, Object value)
    {
      k = key;
      v = value;
    }

    /**
     * There is a single immutable entry.
     *
     * @return A singleton containing the map entry.
     */
    public Set entrySet()
    {
      if (entries == null)
        entries = singleton(new AbstractMap.BasicMapEntry(k, v)
        {
	  /**
	   * Sets the value of the map entry to the supplied value.
	   * An exception is always thrown, as the map is immutable.
	   *
	   * @param o The new value.
	   * @return The old value.
	   * @throws UnsupportedOperationException as setting the value
	   *         is not supported.
	   */
          public Object setValue(Object o)
          {
            throw new UnsupportedOperationException();
          }
        });
      return entries;
    }

    // The remaining methods are optional, but provide a performance
    // advantage by not allocating unnecessary iterators in AbstractMap.
    /**
     * Single entry.
     *
     * @param key The key to look for.
     * @return <code>true</code> if the key is the same as the one used by
     *         this map.
     */
    public boolean containsKey(Object key)
    {
      return equals(key, k);
    }

    /**
     * Single entry.
     *
     * @param value The value to look for.
     * @return <code>true</code> if the value is the same as the one used by
     *         this map.
     */
    public boolean containsValue(Object value)
    {
      return equals(value, v);
    }

    /**
     * Single entry.
     *
     * @param key The key of the value to be retrieved.
     * @return The singleton value if the key is the same as the
     *         singleton key, null otherwise.
     */
    public Object get(Object key)
    {
      return equals(key, k) ? v : null;
    }

    /**
     * Calculate the hashcode directly.
     *
     * @return The hashcode computed from the singleton key
     *         and the singleton value.
     */
    public int hashCode()
    {
      return hashCode(k) ^ hashCode(v);
    }

    /**
     * Return the keyset.
     *
     * @return A singleton containing the key.
     */
    public Set keySet()
    {
      if (keys == null)
        keys = singleton(k);
      return keys;
    }

    /**
     * The size: always 1!
     *
     * @return 1.
     */
    public int size()
    {
      return 1;
    }

    /**
     * Return the values. Technically, a singleton, while more specific than
     * a general Collection, will work. Besides, that's what the JDK uses!
     *
     * @return A singleton containing the value.
     */
    public Collection values()
    {
      if (values == null)
        values = singleton(v);
      return values;
    }

    /**
     * Obvious string.
     *
     * @return A string containing the string representations of the key
     *         and its associated value.
     */
    public String toString()
    {
      return "{" + k + "=" + v + "}";
    }
  } // class SingletonMap

  /**
   * Sort a list according to the natural ordering of its elements. The list
   * must be modifiable, but can be of fixed size. The sort algorithm is
   * precisely that used by Arrays.sort(Object[]), which offers guaranteed
   * nlog(n) performance. This implementation dumps the list into an array,
   * sorts the array, and then iterates over the list setting each element from
   * the array.
   *
   * @param l the List to sort
   * @throws ClassCastException if some items are not mutually comparable
   * @throws UnsupportedOperationException if the List is not modifiable
   * @throws NullPointerException if some element is null
   * @see Arrays#sort(Object[])
   */
  public static void sort(List l)
  {
    sort(l, null);
  }

  /**
   * Sort a list according to a specified Comparator. The list must be
   * modifiable, but can be of fixed size. The sort algorithm is precisely that
   * used by Arrays.sort(Object[], Comparator), which offers guaranteed
   * nlog(n) performance. This implementation dumps the list into an array,
   * sorts the array, and then iterates over the list setting each element from
   * the array.
   *
   * @param l the List to sort
   * @param c the Comparator specifying the ordering for the elements, or
   *        null for natural ordering
   * @throws ClassCastException if c will not compare some pair of items
   * @throws UnsupportedOperationException if the List is not modifiable
   * @throws NullPointerException if null is compared by natural ordering
   *        (only possible when c is null)
   * @see Arrays#sort(Object[], Comparator)
   */
  public static void sort(List l, Comparator c)
  {
    Object[] a = l.toArray();
    Arrays.sort(a, c);
    ListIterator i = l.listIterator();
    for (int pos = 0, alen = a.length;  pos < alen;  pos++)
      {
        i.next();
        i.set(a[pos]);
      }
  }

  /**
   * Swaps the elements at the specified positions within the list. Equal
   * positions have no effect.
   *
   * @param l the list to work on
   * @param i the first index to swap
   * @param j the second index
   * @throws UnsupportedOperationException if list.set is not supported
   * @throws IndexOutOfBoundsException if either i or j is &lt; 0 or &gt;=
   *         list.size()
   * @since 1.4
   */
  public static void swap(List l, int i, int j)
  {
    l.set(i, l.set(j, l.get(i)));
  }


  /**
   * Returns a synchronized (thread-safe) collection wrapper backed by the
   * given collection. Notice that element access through the iterators
   * is thread-safe, but if the collection can be structurally modified
   * (adding or removing elements) then you should synchronize around the
   * iteration to avoid non-deterministic behavior:<br>
   * <pre>
   * Collection c = Collections.synchronizedCollection(new Collection(...));
   * ...
   * synchronized (c)
   *   {
   *     Iterator i = c.iterator();
   *     while (i.hasNext())
   *       foo(i.next());
   *   }
   * </pre><p>
   *
   * Since the collection might be a List or a Set, and those have incompatible
   * equals and hashCode requirements, this relies on Object's implementation
   * rather than passing those calls on to the wrapped collection. The returned
   * Collection implements Serializable, but can only be serialized if
   * the collection it wraps is likewise Serializable.
   *
   * @param c the collection to wrap
   * @return a synchronized view of the collection
   * @see Serializable
   */
  public static Collection synchronizedCollection(Collection c)
  {
    return new SynchronizedCollection(c);
  }

  /**
   * The implementation of {@link #synchronizedCollection(Collection)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   * Package visible, so that collections such as the one for
   * Hashtable.values() can specify which object to synchronize on.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  static class SynchronizedCollection
    implements Collection, Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 3053995032091335093L;

    /**
     * The wrapped collection. Package visible for use by subclasses.
     * @serial the real collection
     */
    final Collection c;

    /**
     * The object to synchronize on.  When an instance is created via public
     * methods, it will be this; but other uses like SynchronizedMap.values()
     * must specify another mutex. Package visible for use by subclasses.
     * @serial the lock
     */
    final Object mutex;

    /**
     * Wrap a given collection.
     * @param c the collection to wrap
     * @throws NullPointerException if c is null
     */
    SynchronizedCollection(Collection c)
    {
      this.c = c;
      mutex = this;
      if (c == null)
        throw new NullPointerException();
    }

    /**
     * Called only by trusted code to specify the mutex as well as the
     * collection.
     * @param sync the mutex
     * @param c the collection
     */
    SynchronizedCollection(Object sync, Collection c)
    {
      this.c = c;
      mutex = sync;
    }

    /**
     * Adds the object to the underlying collection, first
     * obtaining a lock on the mutex.
     *
     * @param o The object to add.
     * @return <code>true</code> if the collection was modified as a result
     *         of this action.
     * @throws UnsupportedOperationException if this collection does not
     *         support the add operation.
     * @throws ClassCastException if o cannot be added to this collection due
     *         to its type.
     * @throws NullPointerException if o is null and this collection doesn't
     *         support the addition of null values.
     * @throws IllegalArgumentException if o cannot be added to this
     *         collection for some other reason.
     */
    public boolean add(Object o)
    {
      synchronized (mutex)
        {
          return c.add(o);
        }
    }

    /**
     * Adds the objects in col to the underlying collection, first
     * obtaining a lock on the mutex.
     *
     * @param col The collection to take the new objects from.
     * @return <code>true</code> if the collection was modified as a result
     *          of this action.
     * @throws UnsupportedOperationException if this collection does not
     *         support the addAll operation.
     * @throws ClassCastException if some element of col cannot be added to this
     *         collection due to its type.
     * @throws NullPointerException if some element of col is null and this
     *         collection does not support the addition of null values.
     * @throws NullPointerException if col itself is null.
     * @throws IllegalArgumentException if some element of col cannot be added
     *         to this collection for some other reason.
     */
    public boolean addAll(Collection col)
    {
      synchronized (mutex)
        {
          return c.addAll(col);
        }
    }

    /**
     * Removes all objects from the underlying collection,
     * first obtaining a lock on the mutex.
     *
     * @throws UnsupportedOperationException if this collection does not
     *         support the clear operation.
     */
    public void clear()
    {
      synchronized (mutex)
        {
          c.clear();
        }
    }

    /**
     * Checks for the existence of o within the underlying
     * collection, first obtaining a lock on the mutex.
     *
     * @param o the element to look for.
     * @return <code>true</code> if this collection contains at least one
     *         element e such that <code>o == null ? e == null : o.equals(e)</code>.
     * @throws ClassCastException if the type of o is not a valid type for this
     *         collection.
     * @throws NullPointerException if o is null and this collection doesn't
     *         support null values.
     */
    public boolean contains(Object o)
    {
      synchronized (mutex)
        {
          return c.contains(o);
        }
    }

    /**
     * Checks for the existence of each object in cl
     * within the underlying collection, first obtaining
     * a lock on the mutex.
     *
     * @param c1 the collection to test for.
     * @return <code>true</code> if for every element o in c, contains(o)
     *         would return <code>true</code>.
     * @throws ClassCastException if the type of any element in cl is not a valid
     *         type for this collection.
     * @throws NullPointerException if some element of cl is null and this
     *         collection does not support null values.
     * @throws NullPointerException if cl itself is null.
     */
    public boolean containsAll(Collection c1)
    {
      synchronized (mutex)
        {
          return c.containsAll(c1);
        }
    }

    /**
     * Returns <code>true</code> if there are no objects in the underlying
     * collection.  A lock on the mutex is obtained before the
     * check is performed.
     *
     * @return <code>true</code> if this collection contains no elements.
     */
    public boolean isEmpty()
    {
      synchronized (mutex)
        {
          return c.isEmpty();
        }
    }

    /**
     * Returns a synchronized iterator wrapper around the underlying
     * collection's iterator.  A lock on the mutex is obtained before
     * retrieving the collection's iterator.
     *
     * @return An iterator over the elements in the underlying collection,
     *         which returns each element in any order.
     */
    public Iterator iterator()
    {
      synchronized (mutex)
        {
          return new SynchronizedIterator(mutex, c.iterator());
        }
    }

    /**
     * Removes the specified object from the underlying collection,
     * first obtaining a lock on the mutex.
     *
     * @param o The object to remove.
     * @return <code>true</code> if the collection changed as a result of this call, that is,
     *         if the collection contained at least one occurrence of o.
     * @throws UnsupportedOperationException if this collection does not
     *         support the remove operation.
     * @throws ClassCastException if the type of o is not a valid type
     *         for this collection.
     * @throws NullPointerException if o is null and the collection doesn't
     *         support null values.
     */
    public boolean remove(Object o)
    {
      synchronized (mutex)
        {
          return c.remove(o);
        }
    }

    /**
     * Removes all elements, e, of the underlying
     * collection for which <code>col.contains(e)</code>
     * returns <code>true</code>.  A lock on the mutex is obtained
     * before the operation proceeds.
     *
     * @param col The collection of objects to be removed.
     * @return <code>true</code> if this collection was modified as a result of this call.
     * @throws UnsupportedOperationException if this collection does not
     *   support the removeAll operation.
     * @throws ClassCastException if the type of any element in c is not a valid
     *   type for this collection.
     * @throws NullPointerException if some element of c is null and this
     *   collection does not support removing null values.
     * @throws NullPointerException if c itself is null.
     */
    public boolean removeAll(Collection col)
    {
      synchronized (mutex)
        {
          return c.removeAll(col);
        }
    }

    /**
     * Retains all elements, e, of the underlying
     * collection for which <code>col.contains(e)</code>
     * returns <code>true</code>.  That is, every element that doesn't
     * exist in col is removed.  A lock on the mutex is obtained
     * before the operation proceeds.
     *
     * @param col The collection of objects to be removed.
     * @return <code>true</code> if this collection was modified as a result of this call.
     * @throws UnsupportedOperationException if this collection does not
     *   support the removeAll operation.
     * @throws ClassCastException if the type of any element in c is not a valid
     *   type for this collection.
     * @throws NullPointerException if some element of c is null and this
     *   collection does not support removing null values.
     * @throws NullPointerException if c itself is null.
     */
    public boolean retainAll(Collection col)
    {
      synchronized (mutex)
        {
          return c.retainAll(col);
        }
    }

    /**
     * Retrieves the size of the underlying collection.
     * A lock on the mutex is obtained before the collection
     * is accessed.
     *
     * @return The size of the collection.
     */
    public int size()
    {
      synchronized (mutex)
        {
          return c.size();
        }
    }

    /**
     * Returns an array containing each object within the underlying
     * collection.  A lock is obtained on the mutex before the collection
     * is accessed.
     *
     * @return An array of objects, matching the collection in size.  The
     *         elements occur in any order.
     */
    public Object[] toArray()
    {
      synchronized (mutex)
        {
          return c.toArray();
        }
    }

    /**
     * Copies the elements in the underlying collection to the supplied
     * array.  If <code>a.length < size()</code>, a new array of the
     * same run-time type is created, with a size equal to that of
     * the collection.  If <code>a.length > size()</code>, then the
     * elements from 0 to <code>size() - 1</code> contain the elements
     * from this collection.  The following element is set to null
     * to indicate the end of the collection objects.  However, this
     * only makes a difference if null is not a permitted value within
     * the collection.
     * Before the copying takes place, a lock is obtained on the mutex.
     *
     * @param a An array to copy elements to.
     * @return An array containing the elements of the underlying collection.
     * @throws ArrayStoreException if the type of any element of the
     *         collection is not a subtype of the element type of a.
     */
    public Object[] toArray(Object[] a)
    {
      synchronized (mutex)
        {
          return c.toArray(a);
        }
    }

    /**
     * Returns a string representation of the underlying collection.
     * A lock is obtained on the mutex before the string is created.
     *
     * @return A string representation of the collection.
     */
    public String toString()
    {
      synchronized (mutex)
        {
          return c.toString();
        }
    }
  } // class SynchronizedCollection

  /**
   * The implementation of the various iterator methods in the
   * synchronized classes. These iterators must "sync" on the same object
   * as the collection they iterate over.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class SynchronizedIterator implements Iterator
  {
    /**
     * The object to synchronize on. Package visible for use by subclass.
     */
    final Object mutex;

    /**
     * The wrapped iterator.
     */
    private final Iterator i;

    /**
     * Only trusted code creates a wrapper, with the specified sync.
     * @param sync the mutex
     * @param i the wrapped iterator
     */
    SynchronizedIterator(Object sync, Iterator i)
    {
      this.i = i;
      mutex = sync;
    }

    /**
     * Retrieves the next object in the underlying collection.
     * A lock is obtained on the mutex before the collection is accessed.
     * 
     * @return The next object in the collection.
     * @throws NoSuchElementException if there are no more elements
     */
    public Object next()
    {
      synchronized (mutex)
        {
          return i.next();
        }
    }

    /**
     * Returns <code>true</code> if objects can still be retrieved from the iterator
     * using <code>next()</code>.  A lock is obtained on the mutex before
     * the collection is accessed.
     *
     * @return <code>true</code> if at least one element is still to be returned by
     *         <code>next()</code>.
     */
    public boolean hasNext()
    {
      synchronized (mutex)
        {
          return i.hasNext();
        }
    }

    /**
     * Removes the object that was last returned by <code>next()</code>
     * from the underlying collection.  Only one call to this method is
     * allowed per call to the <code>next()</code> method, and it does
     * not affect the value that will be returned by <code>next()</code>.
     * Thus, if element n was retrieved from the collection by
     * <code>next()</code>, it is this element that gets removed.
     * Regardless of whether this takes place or not, element n+1 is
     * still returned on the subsequent <code>next()</code> call.
     *
     * @throws IllegalStateException if next has not yet been called or remove
     *         has already been called since the last call to next.
     * @throws UnsupportedOperationException if this Iterator does not support
     *         the remove operation.
     */
    public void remove()
    {
      synchronized (mutex)
        {
          i.remove();
        }
    }
  } // class SynchronizedIterator

  /**
   * Returns a synchronized (thread-safe) list wrapper backed by the
   * given list. Notice that element access through the iterators
   * is thread-safe, but if the list can be structurally modified
   * (adding or removing elements) then you should synchronize around the
   * iteration to avoid non-deterministic behavior:<br>
   * <pre>
   * List l = Collections.synchronizedList(new List(...));
   * ...
   * synchronized (l)
   *   {
   *     Iterator i = l.iterator();
   *     while (i.hasNext())
   *       foo(i.next());
   *   }
   * </pre><p>
   *
   * The returned List implements Serializable, but can only be serialized if
   * the list it wraps is likewise Serializable. In addition, if the wrapped
   * list implements RandomAccess, this does too.
   *
   * @param l the list to wrap
   * @return a synchronized view of the list
   * @see Serializable
   * @see RandomAccess
   */
  public static List synchronizedList(List l)
  {
    if (l instanceof RandomAccess)
      return new SynchronizedRandomAccessList(l);
    return new SynchronizedList(l);
  }

  /**
   * The implementation of {@link #synchronizedList(List)} for sequential
   * lists. This class name is required for compatibility with Sun's JDK
   * serializability. Package visible, so that lists such as Vector.subList()
   * can specify which object to synchronize on.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  static class SynchronizedList extends SynchronizedCollection
    implements List
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -7754090372962971524L;

    /**
     * The wrapped list; stored both here and in the superclass to avoid
     * excessive casting. Package visible for use by subclass.
     * @serial the wrapped list
     */
    final List list;

    /**
     * Wrap a given list.
     * @param l the list to wrap
     * @throws NullPointerException if l is null
     */
    SynchronizedList(List l)
    {
      super(l);
      list = l;
    }

    /**
     * Called only by trusted code to specify the mutex as well as the list.
     * @param sync the mutex
     * @param l the list
     */
    SynchronizedList(Object sync, List l)
    {
      super(sync, l);
      list = l;
    }

  /**
   * Insert an element into the underlying list at a given position (optional
   * operation).  This shifts all existing elements from that position to the
   * end one index to the right. This version of add has no return, since it is
   * assumed to always succeed if there is no exception.  Before the
   * addition takes place, a lock is obtained on the mutex.
   *
   * @param index the location to insert the item
   * @param o the object to insert
   * @throws UnsupportedOperationException if this list does not support the
   *         add operation
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
   * @throws ClassCastException if o cannot be added to this list due to its
   *         type
   * @throws IllegalArgumentException if o cannot be added to this list for
   *         some other reason
   * @throws NullPointerException if o is null and this list doesn't support
   *         the addition of null values.
   */
    public void add(int index, Object o)
    {
      synchronized (mutex)
        {
          list.add(index, o);
        }
    }

  /**
   * Add the contents of a collection to the underlying list at the given
   * index (optional operation).  If the list imposes restraints on what 
   * can be inserted, such as no null elements, this should be documented.
   * A lock is obtained on the mutex before any of the elements are added.
   *
   * @param index the index at which to insert
   * @param c the collection to add
   * @return <code>true</code>, as defined by Collection for a modified list
   * @throws UnsupportedOperationException if this list does not support the
   *         add operation
   * @throws ClassCastException if o cannot be added to this list due to its
   *         type
   * @throws IllegalArgumentException if o cannot be added to this list for
   *         some other reason
   * @throws NullPointerException if o is null and this list doesn't support
   *         the addition of null values.
   */
    public boolean addAll(int index, Collection c)
    {
      synchronized (mutex)
        {
          return list.addAll(index, c);
        }
    }

   /**
    * Tests whether the underlying list is equal to the supplied object.
    * The object is deemed to be equal if it is also a <code>List</code>
    * of equal size and with the same elements (i.e. each element, e1,
    * in list, l1, and each element, e2, in l2, must return <code>true</code> for
    * <code>e1 == null ? e2 == null : e1.equals(e2)</code>.  Before the
    * comparison is made, a lock is obtained on the mutex.
    *
    * @param o The object to test for equality with the underlying list.
    * @return <code>true</code> if o is equal to the underlying list under the above
    *         definition.
    */
    public boolean equals(Object o)
    {
      synchronized (mutex)
        {
          return list.equals(o);
        }
    }

    /**
     * Retrieves the object at the specified index.  A lock
     * is obtained on the mutex before the list is accessed.
     *
     * @param index the index of the element to be returned
     * @return the element at index index in this list
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
     */
    public Object get(int index)
    {
      synchronized (mutex)
        {
          return list.get(index);
        }
    }

    /**
     * Obtains a hashcode for the underlying list, first obtaining
     * a lock on the mutex.  The calculation of the hashcode is
     * detailed in the documentation for the <code>List</code>
     * interface.
     *
     * @return The hashcode of the underlying list.
     * @see List#hashCode()
     */
    public int hashCode()
    {
      synchronized (mutex)
        {
          return list.hashCode();
        }
    }

    /**
     * Obtain the first index at which a given object is to be found in the
     * underlying list.  A lock is obtained on the mutex before the list is
     * accessed.
     *
     * @param o the object to search for
     * @return the least integer n such that <code>o == null ? get(n) == null :
     *         o.equals(get(n))</code>, or -1 if there is no such index.
     * @throws ClassCastException if the type of o is not a valid
     *         type for this list.
     * @throws NullPointerException if o is null and this
     *         list does not support null values.
     */

    public int indexOf(Object o)
    {
      synchronized (mutex)
        {
          return list.indexOf(o);
        }
    }

    /**
     * Obtain the last index at which a given object is to be found in this
     * underlying list.  A lock is obtained on the mutex before the list
     * is accessed.
     *
     * @return the greatest integer n such that <code>o == null ? get(n) == null
     *         : o.equals(get(n))</code>, or -1 if there is no such index.
     * @throws ClassCastException if the type of o is not a valid
     *         type for this list.
     * @throws NullPointerException if o is null and this
     *         list does not support null values.
     */
    public int lastIndexOf(Object o)
    {
      synchronized (mutex)
        {
          return list.lastIndexOf(o);
        }
    }

    /**
     * Retrieves a synchronized wrapper around the underlying list's
     * list iterator.  A lock is obtained on the mutex before the
     * list iterator is retrieved.
     *
     * @return A list iterator over the elements in the underlying list.
     *         The list iterator allows additional list-specific operations
     *         to be performed, in addition to those supplied by the
     *         standard iterator.
     */
    public ListIterator listIterator()
    {
      synchronized (mutex)
        {
          return new SynchronizedListIterator(mutex, list.listIterator());
        }
    }

    /**
     * Retrieves a synchronized wrapper around the underlying list's
     * list iterator.  A lock is obtained on the mutex before the
     * list iterator is retrieved.  The iterator starts at the
     * index supplied, leading to the element at that index being
     * the first one returned by <code>next()</code>.  Calling
     * <code>previous()</code> from this initial position returns
     * index - 1.
     *
     * @param index the position, between 0 and size() inclusive, to begin the
     *        iteration from
     * @return A list iterator over the elements in the underlying list.
     *         The list iterator allows additional list-specific operations
     *         to be performed, in addition to those supplied by the
     *         standard iterator.
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
     */
    public ListIterator listIterator(int index)
    {
      synchronized (mutex)
        {
          return new SynchronizedListIterator(mutex, list.listIterator(index));
        }
    }

    /**
     * Remove the element at a given position in the underlying list (optional
     * operation).  All remaining elements are shifted to the left to fill the gap.
     * A lock on the mutex is obtained before the element is removed.
     *
     * @param index the position within the list of the object to remove
     * @return the object that was removed
     * @throws UnsupportedOperationException if this list does not support the
     *         remove operation
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
     */
    public Object remove(int index)
    {
      synchronized (mutex)
        {
          return list.remove(index);
        }
    }

  /**
   * Replace an element of the underlying list with another object (optional
   * operation).  A lock is obtained on the mutex before the element is
   * replaced.
   *
   * @param index the position within this list of the element to be replaced
   * @param o the object to replace it with
   * @return the object that was replaced
   * @throws UnsupportedOperationException if this list does not support the
   *         set operation.
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
   * @throws ClassCastException if o cannot be added to this list due to its
   *         type
   * @throws IllegalArgumentException if o cannot be added to this list for
   *         some other reason
   * @throws NullPointerException if o is null and this
   *         list does not support null values.
   */
    public Object set(int index, Object o)
    {
      synchronized (mutex)
        {
          return list.set(index, o);
        }
    }

    /**
     * Obtain a List view of a subsection of the underlying list, from fromIndex
     * (inclusive) to toIndex (exclusive). If the two indices are equal, the
     * sublist is empty. The returned list should be modifiable if and only
     * if this list is modifiable. Changes to the returned list should be
     * reflected in this list. If this list is structurally modified in
     * any way other than through the returned list, the result of any subsequent
     * operations on the returned list is undefined.  A lock is obtained
     * on the mutex before the creation of the sublist.  The returned list
     * is also synchronized, using the same mutex.
     *
     * @param fromIndex the index that the returned list should start from
     *        (inclusive)
     * @param toIndex the index that the returned list should go to (exclusive)
     * @return a List backed by a subsection of this list
     * @throws IndexOutOfBoundsException if fromIndex &lt; 0
     *         || toIndex &gt; size() || fromIndex &gt; toIndex
     */
    public List subList(int fromIndex, int toIndex)
    {
      synchronized (mutex)
        {
          return new SynchronizedList(mutex, list.subList(fromIndex, toIndex));
        }
    }
  } // class SynchronizedList

  /**
   * The implementation of {@link #synchronizedList(List)} for random-access
   * lists. This class name is required for compatibility with Sun's JDK
   * serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class SynchronizedRandomAccessList
    extends SynchronizedList implements RandomAccess
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 1530674583602358482L;

    /**
     * Wrap a given list.
     * @param l the list to wrap
     * @throws NullPointerException if l is null
     */
    SynchronizedRandomAccessList(List l)
    {
      super(l);
    }

    /**
     * Called only by trusted code to specify the mutex as well as the
     * collection.
     * @param sync the mutex
     * @param l the list
     */
    SynchronizedRandomAccessList(Object sync, List l)
    {
      super(sync, l);
    }

    /**
     * Obtain a List view of a subsection of the underlying list, from fromIndex
     * (inclusive) to toIndex (exclusive). If the two indices are equal, the
     * sublist is empty. The returned list should be modifiable if and only
     * if this list is modifiable. Changes to the returned list should be
     * reflected in this list. If this list is structurally modified in
     * any way other than through the returned list, the result of any subsequent
     * operations on the returned list is undefined.    A lock is obtained
     * on the mutex before the creation of the sublist.  The returned list
     * is also synchronized, using the same mutex.  Random accessibility
     * is also extended to the new list.
     *
     * @param fromIndex the index that the returned list should start from
     *        (inclusive)
     * @param toIndex the index that the returned list should go to (exclusive)
     * @return a List backed by a subsection of this list
     * @throws IndexOutOfBoundsException if fromIndex &lt; 0
     *         || toIndex &gt; size() || fromIndex &gt; toIndex
     */
    public List subList(int fromIndex, int toIndex)
    {
      synchronized (mutex)
        {
          return new SynchronizedRandomAccessList(mutex,
                                                  list.subList(fromIndex,
                                                               toIndex));
        }
    }
  } // class SynchronizedRandomAccessList

  /**
   * The implementation of {@link SynchronizedList#listIterator()}. This
   * iterator must "sync" on the same object as the list it iterates over.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class SynchronizedListIterator
    extends SynchronizedIterator implements ListIterator
  {
    /**
     * The wrapped iterator, stored both here and in the superclass to
     * avoid excessive casting.
     */
    private final ListIterator li;

    /**
     * Only trusted code creates a wrapper, with the specified sync.
     * @param sync the mutex
     * @param li the wrapped iterator
     */
    SynchronizedListIterator(Object sync, ListIterator li)
    {
      super(sync, li);
      this.li = li;
    }

    /**
     * Insert an element into the underlying list at the current position of
     * the iterator (optional operation). The element is inserted in between
     * the element that would be returned by <code>previous()</code> and the
     * element that would be returned by <code>next()</code>. After the
     * insertion, a subsequent call to next is unaffected, but
     * a call to previous returns the item that was added. The values returned
     * by nextIndex() and previousIndex() are incremented.  A lock is obtained
     * on the mutex before the addition takes place.
     *
     * @param o the object to insert into the list
     * @throws ClassCastException if the object is of a type which cannot be added
     *         to this list.
     * @throws IllegalArgumentException if some other aspect of the object stops
     *         it being added to this list.
     * @throws UnsupportedOperationException if this ListIterator does not
     *         support the add operation.
     */
    public void add(Object o)
    {
      synchronized (mutex)
        {
          li.add(o);
        }
    }

    /**
     * Tests whether there are elements remaining in the underlying list
     * in the reverse direction. In other words, <code>previous()</code>
     * will not fail with a NoSuchElementException.  A lock is obtained
     * on the mutex before the check takes place.
     *
     * @return <code>true</code> if the list continues in the reverse direction
     */
    public boolean hasPrevious()
    {
      synchronized (mutex)
        {
          return li.hasPrevious();
        }
    }

    /**
      * Find the index of the element that would be returned by a call to
      * <code>next()</code>.  If hasNext() returns <code>false</code>, this
      * returns the list size.  A lock is obtained on the mutex before the
      * query takes place.
      *
      * @return the index of the element that would be returned by next()
      */
    public int nextIndex()
    {
      synchronized (mutex)
        {
          return li.nextIndex();
        }
    }

    /**
     * Obtain the previous element from the underlying list. Repeated
     * calls to previous may be used to iterate backwards over the entire list,
     * or calls to next and previous may be used together to go forwards and
     * backwards. Alternating calls to next and previous will return the same
     * element.  A lock is obtained on the mutex before the object is retrieved.
     *
     * @return the next element in the list in the reverse direction
     * @throws NoSuchElementException if there are no more elements
     */
    public Object previous()
    {
      synchronized (mutex)
        {
          return li.previous();
        }
    }

    /**
     * Find the index of the element that would be returned by a call to
     * previous. If hasPrevious() returns <code>false</code>, this returns -1.
     * A lock is obtained on the mutex before the query takes place.
     *
     * @return the index of the element that would be returned by previous()
     */
    public int previousIndex()
    {
      synchronized (mutex)
        {
          return li.previousIndex();
        }
    }

    /**
     * Replace the element last returned by a call to <code>next()</code> or
     * <code>previous()</code> with a given object (optional operation).  This
     * method may only be called if neither <code>add()</code> nor
     * <code>remove()</code> have been called since the last call to
     * <code>next()</code> or <code>previous</code>.  A lock is obtained
     * on the mutex before the list is modified.
     *
     * @param o the object to replace the element with
     * @throws ClassCastException the object is of a type which cannot be added
     *         to this list
     * @throws IllegalArgumentException some other aspect of the object stops
     *         it being added to this list
     * @throws IllegalStateException if neither next or previous have been
     *         called, or if add or remove has been called since the last call
     *         to next or previous
     * @throws UnsupportedOperationException if this ListIterator does not
     *         support the set operation
     */
    public void set(Object o)
    {
      synchronized (mutex)
        {
          li.set(o);
        }
    }
  } // class SynchronizedListIterator

  /**
   * Returns a synchronized (thread-safe) map wrapper backed by the given
   * map. Notice that element access through the collection views and their
   * iterators are thread-safe, but if the map can be structurally modified
   * (adding or removing elements) then you should synchronize around the
   * iteration to avoid non-deterministic behavior:<br>
   * <pre>
   * Map m = Collections.synchronizedMap(new Map(...));
   * ...
   * Set s = m.keySet(); // safe outside a synchronized block
   * synchronized (m) // synch on m, not s
   *   {
   *     Iterator i = s.iterator();
   *     while (i.hasNext())
   *       foo(i.next());
   *   }
   * </pre><p>
   *
   * The returned Map implements Serializable, but can only be serialized if
   * the map it wraps is likewise Serializable.
   *
   * @param m the map to wrap
   * @return a synchronized view of the map
   * @see Serializable
   */
  public static Map synchronizedMap(Map m)
  {
    return new SynchronizedMap(m);
  }

  /**
   * The implementation of {@link #synchronizedMap(Map)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class SynchronizedMap implements Map, Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 1978198479659022715L;

    /**
     * The wrapped map.
     * @serial the real map
     */
    private final Map m;

    /**
     * The object to synchronize on.  When an instance is created via public
     * methods, it will be this; but other uses like
     * SynchronizedSortedMap.subMap() must specify another mutex. Package
     * visible for use by subclass.
     * @serial the lock
     */
    final Object mutex;

    /**
     * Cache the entry set.
     */
    private transient Set entries;

    /**
     * Cache the key set.
     */
    private transient Set keys;

    /**
     * Cache the value collection.
     */
    private transient Collection values;

    /**
     * Wrap a given map.
     * @param m the map to wrap
     * @throws NullPointerException if m is null
     */
    SynchronizedMap(Map m)
    {
      this.m = m;
      mutex = this;
      if (m == null)
        throw new NullPointerException();
    }

    /**
     * Called only by trusted code to specify the mutex as well as the map.
     * @param sync the mutex
     * @param m the map
     */
    SynchronizedMap(Object sync, Map m)
    {
      this.m = m;
      mutex = sync;
    }

    /**
     * Clears all the entries from the underlying map.  A lock is obtained
     * on the mutex before the map is cleared.
     *
     * @throws UnsupportedOperationException if clear is not supported
     */
    public void clear()
    {
      synchronized (mutex)
        {
          m.clear();
        }
    }

    /**
     * Returns <code>true</code> if the underlying map contains a entry for the given key.
     * A lock is obtained on the mutex before the map is queried.
     *
     * @param key the key to search for.
     * @return <code>true</code> if the underlying map contains the key.
     * @throws ClassCastException if the key is of an inappropriate type.
     * @throws NullPointerException if key is <code>null</code> but the map
     *         does not permit null keys.
     */
    public boolean containsKey(Object key)
    {
      synchronized (mutex)
        {
          return m.containsKey(key);
        }
    }

  /**
   * Returns <code>true</code> if the underlying map contains at least one entry with the
   * given value.  In other words, returns <code>true</code> if a value v exists where
   * <code>(value == null ? v == null : value.equals(v))</code>. This usually
   * requires linear time.  A lock is obtained on the mutex before the map
   * is queried.
   *
   * @param value the value to search for
   * @return <code>true</code> if the map contains the value
   * @throws ClassCastException if the type of the value is not a valid type
   *         for this map.
   * @throws NullPointerException if the value is null and the map doesn't
   *         support null values.
   */
    public boolean containsValue(Object value)
    {
      synchronized (mutex)
        {
          return m.containsValue(value);
        }
    }

    // This is one of the ickiest cases of nesting I've ever seen. It just
    // means "return a SynchronizedSet, except that the iterator() method
    // returns an SynchronizedIterator whose next() method returns a
    // synchronized wrapper around its normal return value".
    public Set entrySet()
    {
      // Define this here to spare some nesting.
      class SynchronizedMapEntry implements Map.Entry
      {
        final Map.Entry e;
        SynchronizedMapEntry(Object o)
        {
          e = (Map.Entry) o;
        }

	/**
	 * Returns <code>true</code> if the object, o, implements <code>Map.Entry</code>
	 * with the same key and value as the underlying entry.  A lock is
	 * obtained on the mutex before the comparison takes place.
	 *
	 * @param o The object to compare with this entry.
	 * @return <code>true</code> if o is equivalent to the underlying map entry.
	 */
        public boolean equals(Object o)
        {
          synchronized (mutex)
            {
              return e.equals(o);
            }
        }

	/**
	 * Returns the key used in the underlying map entry.  A lock is obtained
	 * on the mutex before the key is retrieved.
	 *
	 * @return The key of the underlying map entry.
	 */
        public Object getKey()
        {
          synchronized (mutex)
            {
              return e.getKey();
            }
        }

	/**
	 * Returns the value used in the underlying map entry.  A lock is obtained
	 * on the mutex before the value is retrieved.
	 *
	 * @return The value of the underlying map entry.
	 */
        public Object getValue()
        {
          synchronized (mutex)
            {
              return e.getValue();
            }
        }

	/**
	 * Computes the hash code for the underlying map entry.
	 * This computation is described in the documentation for the
	 * <code>Map</code> interface.  A lock is obtained on the mutex
	 * before the underlying map is accessed.
	 *
	 * @return The hash code of the underlying map entry.
	 * @see Map#hashCode()
	 */
        public int hashCode()
        {
          synchronized (mutex)
            {
              return e.hashCode();
            }
        }

	/**
	 * Replaces the value in the underlying map entry with the specified
	 * object (optional operation).  A lock is obtained on the mutex
	 * before the map is altered.  The map entry, in turn, will alter
	 * the underlying map object.  The operation is undefined if the
	 * <code>remove()</code> method of the iterator has been called
	 * beforehand.
	 *
	 * @param value the new value to store
	 * @return the old value
	 * @throws UnsupportedOperationException if the operation is not supported.
	 * @throws ClassCastException if the value is of the wrong type.
	 * @throws IllegalArgumentException if something about the value
	 *         prevents it from existing in this map.
	 * @throws NullPointerException if the map forbids null values.
	 */
        public Object setValue(Object value)
        {
          synchronized (mutex)
            {
              return e.setValue(value);
            }
        }

	/**
	 * Returns a textual representation of the underlying map entry.
	 * A lock is obtained on the mutex before the entry is accessed.
	 *
	 * @return The contents of the map entry in <code>String</code> form.
	 */
        public String toString()
        {
          synchronized (mutex)
            {
              return e.toString();
            }
        }
      } // class SynchronizedMapEntry

      // Now the actual code.
      if (entries == null)
        synchronized (mutex)
          {
            entries = new SynchronizedSet(mutex, m.entrySet())
            {
	      /**
	       * Returns an iterator over the set.  The iterator has no specific order,
	       * unless further specified.  A lock is obtained on the set's mutex
	       * before the iterator is created.  The created iterator is also
	       * thread-safe.
	       *
	       * @return A synchronized set iterator.
	       */
	      public Iterator iterator()
              {
                synchronized (super.mutex)
                  {
                    return new SynchronizedIterator(super.mutex, c.iterator())
                    {
		      /**
		       * Retrieves the next map entry from the iterator.
		       * A lock is obtained on the iterator's mutex before
		       * the entry is created.  The new map entry is enclosed in
		       * a thread-safe wrapper.
		       *
		       * @return A synchronized map entry.
		       */
                      public Object next()
                      {
                        synchronized (super.mutex)
                          {
                            return new SynchronizedMapEntry(super.next());
                          }
                      }
                    };
                  }
              }
            };
          }
      return entries;
    }

    /**
     * Returns <code>true</code> if the object, o, is also an instance
     * of <code>Map</code> and contains an equivalent
     * entry set to that of the underlying map.  A lock
     * is obtained on the mutex before the objects are
     * compared.
     *
     * @param o The object to compare.
     * @return <code>true</code> if o and the underlying map are equivalent.
     */
    public boolean equals(Object o)
    {
      synchronized (mutex)
        {
          return m.equals(o);
        }
    }

    /**
     * Returns the value associated with the given key, or null
     * if no such mapping exists.  An ambiguity exists with maps
     * that accept null values as a return value of null could
     * be due to a non-existent mapping or simply a null value
     * for that key.  To resolve this, <code>containsKey</code>
     * should be used.  A lock is obtained on the mutex before
     * the value is retrieved from the underlying map.
     *
     * @param key The key of the required mapping.
     * @return The value associated with the given key, or
     *         null if no such mapping exists.
     * @throws ClassCastException if the key is an inappropriate type.
     * @throws NullPointerException if this map does not accept null keys.
     */
    public Object get(Object key)
    {
      synchronized (mutex)
        {
          return m.get(key);
        }
    }

    /**
     * Calculates the hash code of the underlying map as the
     * sum of the hash codes of all entries.  A lock is obtained
     * on the mutex before the hash code is computed.
     *
     * @return The hash code of the underlying map.
     */
    public int hashCode()
    {
      synchronized (mutex)
        {
          return m.hashCode();
        }
    }

    /**
     * Returns <code>true</code> if the underlying map contains no entries.
     * A lock is obtained on the mutex before the map is examined.
     *
     * @return <code>true</code> if the map is empty.
     */
    public boolean isEmpty()
    {
      synchronized (mutex)
        {
          return m.isEmpty();
        }
    }

    /**
     * Returns a thread-safe set view of the keys in the underlying map.  The
     * set is backed by the map, so that changes in one show up in the other.
     * Modifications made while an iterator is in progress cause undefined
     * behavior.  If the set supports removal, these methods remove the
     * underlying mapping from the map: <code>Iterator.remove</code>,
     * <code>Set.remove</code>, <code>removeAll</code>, <code>retainAll</code>,
     * and <code>clear</code>.  Element addition, via <code>add</code> or
     * <code>addAll</code>, is not supported via this set.  A lock is obtained
     * on the mutex before the set is created.
     *
     * @return A synchronized set containing the keys of the underlying map.
     */
    public Set keySet()
    {
      if (keys == null)
        synchronized (mutex)
          {
            keys = new SynchronizedSet(mutex, m.keySet());
          }
      return keys;
    }

    /**
     * Associates the given key to the given value (optional operation). If the
     * underlying map already contains the key, its value is replaced. Be aware
     * that in a map that permits <code>null</code> values, a null return does not
     * always imply that the mapping was created.  A lock is obtained on the mutex
     * before the modification is made.
     *
     * @param key the key to map.
     * @param value the value to be mapped.
     * @return the previous value of the key, or null if there was no mapping
     * @throws UnsupportedOperationException if the operation is not supported
     * @throws ClassCastException if the key or value is of the wrong type
     * @throws IllegalArgumentException if something about this key or value
     *         prevents it from existing in this map
     * @throws NullPointerException if either the key or the value is null,
     *         and the map forbids null keys or values
     * @see #containsKey(Object)
     */
    public Object put(Object key, Object value)
    {
      synchronized (mutex)
        {
          return m.put(key, value);
        }
    }

    /**
     * Copies all entries of the given map to the underlying one (optional
     * operation). If the map already contains a key, its value is replaced.
     * A lock is obtained on the mutex before the operation proceeds.
     *
     * @param map the mapping to load into this map
     * @throws UnsupportedOperationException if the operation is not supported
     * @throws ClassCastException if a key or value is of the wrong type
     * @throws IllegalArgumentException if something about a key or value
     *         prevents it from existing in this map
     * @throws NullPointerException if the map forbids null keys or values, or
     *         if <code>m</code> is null.
     * @see #put(Object, Object)
     */
    public void putAll(Map map)
    {
      synchronized (mutex)
        {
          m.putAll(map);
        }
    }

    /**
     * Removes the mapping for the key, o, if present (optional operation). If
     * the key is not present, this returns null. Note that maps which permit
     * null values may also return null if the key was removed.  A prior
     * <code>containsKey()</code> check is required to avoid this ambiguity.
     * Before the mapping is removed, a lock is obtained on the mutex.
     *
     * @param o the key to remove
     * @return the value the key mapped to, or null if not present
     * @throws UnsupportedOperationException if deletion is unsupported
     * @throws NullPointerException if the key is null and this map doesn't
     *         support null keys.
     * @throws ClassCastException if the type of the key is not a valid type
     *         for this map.
     */
    public Object remove(Object o)
    {
      synchronized (mutex)
        {
          return m.remove(o);
        }
    }

    /**
     * Retrieves the size of the underlying map.  A lock
     * is obtained on the mutex before access takes place.
     * Maps with a size greater than <code>Integer.MAX_VALUE</code>
     * return <code>Integer.MAX_VALUE</code> instead.
     *
     * @return The size of the underlying map.
     */
    public int size()
    {
      synchronized (mutex)
        {
          return m.size();
        }
    }

    /**
     * Returns a textual representation of the underlying
     * map.  A lock is obtained on the mutex before the map
     * is accessed.
     *
     * @return The map in <code>String</code> form.
     */
    public String toString()
    {
      synchronized (mutex)
        {
          return m.toString();
        }
    }

    /**
     * Returns a synchronized collection view of the values in the underlying
     * map.  The collection is backed by the map, so that changes in one show up in
     * the other.  Modifications made while an iterator is in progress cause
     * undefined behavior.  If the collection supports removal, these methods
     * remove the underlying mapping from the map: <code>Iterator.remove</code>,
     * <code>Collection.remove</code>, <code>removeAll</code>,
     * <code>retainAll</code>, and <code>clear</code>. Element addition, via
     * <code>add</code> or <code>addAll</code>, is not supported via this
     * collection.  A lock is obtained on the mutex before the collection
     * is created.
     * 
     * @return the collection of all values in the underlying map.
     */
    public Collection values()
    {
      if (values == null)
        synchronized (mutex)
          {
            values = new SynchronizedCollection(mutex, m.values());
          }
      return values;
    }
  } // class SynchronizedMap

  /**
   * Returns a synchronized (thread-safe) set wrapper backed by the given
   * set. Notice that element access through the iterator is thread-safe, but
   * if the set can be structurally modified (adding or removing elements)
   * then you should synchronize around the iteration to avoid
   * non-deterministic behavior:<br>
   * <pre>
   * Set s = Collections.synchronizedSet(new Set(...));
   * ...
   * synchronized (s)
   *   {
   *     Iterator i = s.iterator();
   *     while (i.hasNext())
   *       foo(i.next());
   *   }
   * </pre><p>
   *
   * The returned Set implements Serializable, but can only be serialized if
   * the set it wraps is likewise Serializable.
   *
   * @param s the set to wrap
   * @return a synchronized view of the set
   * @see Serializable
   */
  public static Set synchronizedSet(Set s)
  {
    return new SynchronizedSet(s);
  }

  /**
   * The implementation of {@link #synchronizedSet(Set)}. This class
   * name is required for compatibility with Sun's JDK serializability.
   * Package visible, so that sets such as Hashtable.keySet()
   * can specify which object to synchronize on.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  static class SynchronizedSet extends SynchronizedCollection
    implements Set
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 487447009682186044L;

    /**
     * Wrap a given set.
     * @param s the set to wrap
     * @throws NullPointerException if s is null
     */
    SynchronizedSet(Set s)
    {
      super(s);
    }

    /**
     * Called only by trusted code to specify the mutex as well as the set.
     * @param sync the mutex
     * @param s the set
     */
    SynchronizedSet(Object sync, Set s)
    {
      super(sync, s);
    }

    /**
     * Returns <code>true</code> if the object, o, is a <code>Set</code>
     * of the same size as the underlying set, and contains
     * each element, e, which occurs in the underlying set.
     * A lock is obtained on the mutex before the comparison
     * takes place.
     *
     * @param o The object to compare against.
     * @return <code>true</code> if o is an equivalent set.
     */
    public boolean equals(Object o)
    {
      synchronized (mutex)
        {
          return c.equals(o);
        }
    }

    /**
     * Computes the hash code for the underlying set as the
     * sum of the hash code of all elements within the set.
     * A lock is obtained on the mutex before the computation
     * occurs.
     *
     * @return The hash code for the underlying set.
     */
    public int hashCode()
    {
      synchronized (mutex)
        {
          return c.hashCode();
        }
    }
  } // class SynchronizedSet

  /**
   * Returns a synchronized (thread-safe) sorted map wrapper backed by the
   * given map. Notice that element access through the collection views,
   * subviews, and their iterators are thread-safe, but if the map can be
   * structurally modified (adding or removing elements) then you should
   * synchronize around the iteration to avoid non-deterministic behavior:<br>
   * <pre>
   * SortedMap m = Collections.synchronizedSortedMap(new SortedMap(...));
   * ...
   * Set s = m.keySet(); // safe outside a synchronized block
   * SortedMap m2 = m.headMap(foo); // safe outside a synchronized block
   * Set s2 = m2.keySet(); // safe outside a synchronized block
   * synchronized (m) // synch on m, not m2, s or s2
   *   {
   *     Iterator i = s.iterator();
   *     while (i.hasNext())
   *       foo(i.next());
   *     i = s2.iterator();
   *     while (i.hasNext())
   *       bar(i.next());
   *   }
   * </pre><p>
   *
   * The returned SortedMap implements Serializable, but can only be
   * serialized if the map it wraps is likewise Serializable.
   *
   * @param m the sorted map to wrap
   * @return a synchronized view of the sorted map
   * @see Serializable
   */
  public static SortedMap synchronizedSortedMap(SortedMap m)
  {
    return new SynchronizedSortedMap(m);
  }

  /**
   * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class SynchronizedSortedMap extends SynchronizedMap
    implements SortedMap
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -8798146769416483793L;

    /**
     * The wrapped map; stored both here and in the superclass to avoid
     * excessive casting.
     * @serial the wrapped map
     */
    private final SortedMap sm;

    /**
     * Wrap a given map.
     * @param sm the map to wrap
     * @throws NullPointerException if sm is null
     */
    SynchronizedSortedMap(SortedMap sm)
    {
      super(sm);
      this.sm = sm;
    }

    /**
     * Called only by trusted code to specify the mutex as well as the map.
     * @param sync the mutex
     * @param sm the map
     */
    SynchronizedSortedMap(Object sync, SortedMap sm)
    {
      super(sync, sm);
      this.sm = sm;
    }

    /**
     * Returns the comparator used in sorting the underlying map, or null if
     * it is the keys' natural ordering.  A lock is obtained on the mutex
     * before the comparator is retrieved.
     *
     * @return the sorting comparator.
     */
    public Comparator comparator()
    {
      synchronized (mutex)
        {
          return sm.comparator();
        }
    }

    /**
     * Returns the first, lowest sorted, key from the underlying map.
     * A lock is obtained on the mutex before the map is accessed.
     *
     * @return the first key.
     * @throws NoSuchElementException if this map is empty.
     */
    public Object firstKey()
    {
      synchronized (mutex)
        {
          return sm.firstKey();
        }
    }

    /**
     * Returns a submap containing the keys from the first
     * key (as returned by <code>firstKey()</code>) to
     * the key before that specified.  The submap supports all
     * operations supported by the underlying map and all actions
     * taking place on the submap are also reflected in the underlying
     * map.  A lock is obtained on the mutex prior to submap creation.
     * This operation is equivalent to <code>subMap(firstKey(), toKey)</code>.
     * The submap retains the thread-safe status of this map.
     *
     * @param toKey the exclusive upper range of the submap.
     * @return a submap from <code>firstKey()</code> to the
     *         the key preceding toKey.
     * @throws ClassCastException if toKey is not comparable to the underlying
     *         map's contents.
     * @throws IllegalArgumentException if toKey is outside the map's range.
     * @throws NullPointerException if toKey is null. but the map does not allow
     *         null keys.
     */
    public SortedMap headMap(Object toKey)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedMap(mutex, sm.headMap(toKey));
        }
    }

    /**
     * Returns the last, highest sorted, key from the underlying map.
     * A lock is obtained on the mutex before the map is accessed.
     *
     * @return the last key.
     * @throws NoSuchElementException if this map is empty.
     */
    public Object lastKey()
    {
      synchronized (mutex)
        {
          return sm.lastKey();
        }
    }

    /**
     * Returns a submap containing the keys from fromKey to
     * the key before toKey.  The submap supports all
     * operations supported by the underlying map and all actions
     * taking place on the submap are also reflected in the underlying
     * map.  A lock is obtained on the mutex prior to submap creation.
     * The submap retains the thread-safe status of this map.
     *
     * @param fromKey the inclusive lower range of the submap.
     * @param toKey the exclusive upper range of the submap.
     * @return a submap from fromKey to the key preceding toKey.
     * @throws ClassCastException if fromKey or toKey is not comparable
     *         to the underlying map's contents.
     * @throws IllegalArgumentException if fromKey or toKey is outside the map's
     *         range.
     * @throws NullPointerException if fromKey or toKey is null. but the map does
     *         not allow  null keys.
     */
    public SortedMap subMap(Object fromKey, Object toKey)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedMap(mutex, sm.subMap(fromKey, toKey));
        }
    }

    /**
     * Returns a submap containing all the keys from fromKey onwards.
     * The submap supports all operations supported by the underlying
     * map and all actions taking place on the submap are also reflected
     * in the underlying map.  A lock is obtained on the mutex prior to
     * submap creation.  The submap retains the thread-safe status of
     * this map.
     *
     * @param fromKey the inclusive lower range of the submap.
     * @return a submap from fromKey to <code>lastKey()</code>.
     * @throws ClassCastException if fromKey is not comparable to the underlying
     *         map's contents.
     * @throws IllegalArgumentException if fromKey is outside the map's range.
     * @throws NullPointerException if fromKey is null. but the map does not allow
     *         null keys.
     */
    public SortedMap tailMap(Object fromKey)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedMap(mutex, sm.tailMap(fromKey));
        }
    }
  } // class SynchronizedSortedMap

  /**
   * Returns a synchronized (thread-safe) sorted set wrapper backed by the
   * given set. Notice that element access through the iterator and through
   * subviews are thread-safe, but if the set can be structurally modified
   * (adding or removing elements) then you should synchronize around the
   * iteration to avoid non-deterministic behavior:<br>
   * <pre>
   * SortedSet s = Collections.synchronizedSortedSet(new SortedSet(...));
   * ...
   * SortedSet s2 = s.headSet(foo); // safe outside a synchronized block
   * synchronized (s) // synch on s, not s2
   *   {
   *     Iterator i = s2.iterator();
   *     while (i.hasNext())
   *       foo(i.next());
   *   }
   * </pre><p>
   *
   * The returned SortedSet implements Serializable, but can only be
   * serialized if the set it wraps is likewise Serializable.
   *
   * @param s the sorted set to wrap
   * @return a synchronized view of the sorted set
   * @see Serializable
   */
  public static SortedSet synchronizedSortedSet(SortedSet s)
  {
    return new SynchronizedSortedSet(s);
  }

  /**
   * The implementation of {@link #synchronizedSortedSet(SortedSet)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class SynchronizedSortedSet extends SynchronizedSet
    implements SortedSet
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 8695801310862127406L;

    /**
     * The wrapped set; stored both here and in the superclass to avoid
     * excessive casting.
     * @serial the wrapped set
     */
    private final SortedSet ss;

    /**
     * Wrap a given set.
     * @param ss the set to wrap
     * @throws NullPointerException if ss is null
     */
    SynchronizedSortedSet(SortedSet ss)
    {
      super(ss);
      this.ss = ss;
    }

    /**
     * Called only by trusted code to specify the mutex as well as the set.
     * @param sync the mutex
     * @param ss the set
     */
    SynchronizedSortedSet(Object sync, SortedSet ss)
    {
      super(sync, ss);
      this.ss = ss;
    }

    /**
     * Returns the comparator used in sorting the underlying set, or null if
     * it is the elements' natural ordering.  A lock is obtained on the mutex
     * before the comparator is retrieved.
     *
     * @return the sorting comparator.
     */
    public Comparator comparator()
    {
      synchronized (mutex)
        {
          return ss.comparator();
        }
    }

    /**
     * Returns the first, lowest sorted, element from the underlying set.
     * A lock is obtained on the mutex before the set is accessed.
     *
     * @return the first element.
     * @throws NoSuchElementException if this set is empty.
     */
    public Object first()
    {
      synchronized (mutex)
        {
          return ss.first();
        }
    }

    /**
     * Returns a subset containing the element from the first
     * element (as returned by <code>first()</code>) to
     * the element before that specified.  The subset supports all
     * operations supported by the underlying set and all actions
     * taking place on the subset are also reflected in the underlying
     * set.  A lock is obtained on the mutex prior to subset creation.
     * This operation is equivalent to <code>subSet(first(), toElement)</code>.
     * The subset retains the thread-safe status of this set.
     *
     * @param toElement the exclusive upper range of the subset.
     * @return a subset from <code>first()</code> to the
     *         the element preceding toElement.
     * @throws ClassCastException if toElement is not comparable to the underlying
     *         set's contents.
     * @throws IllegalArgumentException if toElement is outside the set's range.
     * @throws NullPointerException if toElement is null. but the set does not allow
     *         null elements.
     */
    public SortedSet headSet(Object toElement)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedSet(mutex, ss.headSet(toElement));
        }
    }

    /**
     * Returns the last, highest sorted, element from the underlying set.
     * A lock is obtained on the mutex before the set is accessed.
     *
     * @return the last element.
     * @throws NoSuchElementException if this set is empty.
     */
    public Object last()
    {
      synchronized (mutex)
        {
          return ss.last();
        }
    }

    /**
     * Returns a subset containing the elements from fromElement to
     * the element before toElement.  The subset supports all
     * operations supported by the underlying set and all actions
     * taking place on the subset are also reflected in the underlying
     * set.  A lock is obtained on the mutex prior to subset creation.
     * The subset retains the thread-safe status of this set.
     *
     * @param fromElement the inclusive lower range of the subset.
     * @param toElement the exclusive upper range of the subset.
     * @return a subset from fromElement to the element preceding toElement.
     * @throws ClassCastException if fromElement or toElement is not comparable
     *         to the underlying set's contents.
     * @throws IllegalArgumentException if fromElement or toElement is outside the set's
     *         range.
     * @throws NullPointerException if fromElement or toElement is null. but the set does
     *         not allow null elements.
     */
    public SortedSet subSet(Object fromElement, Object toElement)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedSet(mutex,
                                           ss.subSet(fromElement, toElement));
        }
    }

    /**
     * Returns a subset containing all the elements from fromElement onwards.
     * The subset supports all operations supported by the underlying
     * set and all actions taking place on the subset are also reflected
     * in the underlying set.  A lock is obtained on the mutex prior to
     * subset creation.  The subset retains the thread-safe status of
     * this set.
     *
     * @param fromElement the inclusive lower range of the subset.
     * @return a subset from fromElement to <code>last()</code>.
     * @throws ClassCastException if fromElement is not comparable to the underlying
     *         set's contents.
     * @throws IllegalArgumentException if fromElement is outside the set's range.
     * @throws NullPointerException if fromElement is null. but the set does not allow
     *         null elements.
     */
    public SortedSet tailSet(Object fromElement)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedSet(mutex, ss.tailSet(fromElement));
        }
    }
  } // class SynchronizedSortedSet


  /**
   * Returns an unmodifiable view of the given collection. This allows
   * "read-only" access, although changes in the backing collection show up
   * in this view. Attempts to modify the collection directly or via iterators
   * will fail with {@link UnsupportedOperationException}.  Although this view
   * prevents changes to the structure of the collection and its elements, the values
   * referenced by the objects in the collection can still be modified.
   * <p>
   *
   * Since the collection might be a List or a Set, and those have incompatible
   * equals and hashCode requirements, this relies on Object's implementation
   * rather than passing those calls on to the wrapped collection. The returned
   * Collection implements Serializable, but can only be serialized if
   * the collection it wraps is likewise Serializable.
   *
   * @param c the collection to wrap
   * @return a read-only view of the collection
   * @see Serializable
   */
  public static Collection unmodifiableCollection(Collection c)
  {
    return new UnmodifiableCollection(c);
  }

  /**
   * The implementation of {@link #unmodifiableCollection(Collection)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class UnmodifiableCollection
    implements Collection, Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 1820017752578914078L;

    /**
     * The wrapped collection. Package visible for use by subclasses.
     * @serial the real collection
     */
    final Collection c;

    /**
     * Wrap a given collection.
     * @param c the collection to wrap
     * @throws NullPointerException if c is null
     */
    UnmodifiableCollection(Collection c)
    {
      this.c = c;
      if (c == null)
        throw new NullPointerException();
    }

    /**
     * Blocks the addition of elements to the underlying collection.
     * This method never returns, throwing an exception instead.
     *
     * @param o the object to add.
     * @return <code>true</code> if the collection was modified as a result of this action.
     * @throws UnsupportedOperationException as an unmodifiable collection does not
     *         support the add operation.
     */
    public boolean add(Object o)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Blocks the addition of a collection of elements to the underlying
     * collection.  This method never returns, throwing an exception instead.
     *
     * @param c the collection to add.
     * @return <code>true</code> if the collection was modified as a result of this action.
     * @throws UnsupportedOperationException as an unmodifiable collection does not
     *         support the <code>addAll</code> operation.
     */
    public boolean addAll(Collection c)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Blocks the clearing of the underlying collection.  This method never
     * returns, throwing an exception instead.
     *
     * @throws UnsupportedOperationException as an unmodifiable collection does
     *         not support the <code>clear()</code> operation.
     */
    public void clear()
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Test whether the underlying collection contains a given object as one of its
     * elements.
     *
     * @param o the element to look for.
     * @return <code>true</code> if the underlying collection contains at least
     *         one element e such that
     *         <code>o == null ? e == null : o.equals(e)</code>.
     * @throws ClassCastException if the type of o is not a valid type for the
     *         underlying collection.
     * @throws NullPointerException if o is null and the underlying collection
     *         doesn't support null values.
     */
    public boolean contains(Object o)
    {
      return c.contains(o);
    }

    /**
     * Test whether the underlying collection contains every element in a given
     * collection.
     *
     * @param c1 the collection to test for.
     * @return <code>true</code> if for every element o in c, contains(o) would
     *         return <code>true</code>.
     * @throws ClassCastException if the type of any element in c is not a valid
     *   type for the underlying collection.
     * @throws NullPointerException if some element of c is null and the underlying
     *   collection does not support null values.
     * @throws NullPointerException if c itself is null.
     */
    public boolean containsAll(Collection c1)
    {
      return c.containsAll(c1);
    }

    /**
     * Tests whether the underlying collection is empty, that is,
     * if size() == 0.
     *
     * @return <code>true</code> if this collection contains no elements.
     */
    public boolean isEmpty()
    {
      return c.isEmpty();
    }

    /**
     * Obtain an Iterator over the underlying collection, which maintains
     * its unmodifiable nature.
     *
     * @return an UnmodifiableIterator over the elements of the underlying
     *         collection, in any order.
     */
    public Iterator iterator()
    {
      return new UnmodifiableIterator(c.iterator());
    }

    /**
     * Blocks the removal of an object from the underlying collection.
     * This method never returns, throwing an exception instead.
     *
     * @param o The object to remove.
     * @return <code>true</code> if the object was removed (i.e. the underlying
     *         collection returned 1 or more instances of o).
     * @throws UnsupportedOperationException as an unmodifiable collection
     *         does not support the <code>remove()</code> operation.
     */
    public boolean remove(Object o)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Blocks the removal of a collection of objects from the underlying
     * collection.  This method never returns, throwing an exception
     * instead.
     *
     * @param c The collection of objects to remove.
     * @return <code>true</code> if the collection was modified.
     * @throws UnsupportedOperationException as an unmodifiable collection
     *         does not support the <code>removeAll()</code> operation.
     */
    public boolean removeAll(Collection c)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Blocks the removal of all elements from the underlying collection,
     * except those in the supplied collection.  This method never returns,
     * throwing an exception instead.
     *
     * @param c The collection of objects to retain.
     * @return <code>true</code> if the collection was modified.
     * @throws UnsupportedOperationException as an unmodifiable collection
     *         does not support the <code>retainAll()</code> operation.
     */
    public boolean retainAll(Collection c)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Retrieves the number of elements in the underlying collection.
     *
     * @return the number of elements in the collection.
     */
    public int size()
    {
      return c.size();
    }

    /**
     * Copy the current contents of the underlying collection into an array.
     *
     * @return an array of type Object[] with a length equal to the size of the
     *         underlying collection and containing the elements currently in
     *         the underlying collection, in any order.
     */
    public Object[] toArray()
    {
      return c.toArray();
    }

    /**
     * Copy the current contents of the underlying collection into an array.  If
     * the array passed as an argument has length less than the size of the
     * underlying collection, an array of the same run-time type as a, with a length
     * equal to the size of the underlying collection, is allocated using reflection.
     * Otherwise, a itself is used.  The elements of the underlying collection are
     * copied into it, and if there is space in the array, the following element is
     * set to null. The resultant array is returned.
     * Note: The fact that the following element is set to null is only useful
     * if it is known that this collection does not contain any null elements.
     *
     * @param a the array to copy this collection into.
     * @return an array containing the elements currently in the underlying
     *         collection, in any order.
     * @throws ArrayStoreException if the type of any element of the
     *         collection is not a subtype of the element type of a.
     */
    public Object[] toArray(Object[] a)
    {
      return c.toArray(a);
    }

    /**
     * A textual representation of the unmodifiable collection.
     *
     * @return The unmodifiable collection in the form of a <code>String</code>.
     */
    public String toString()
    {
      return c.toString();
    }
  } // class UnmodifiableCollection

  /**
   * The implementation of the various iterator methods in the
   * unmodifiable classes.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class UnmodifiableIterator implements Iterator
  {
    /**
     * The wrapped iterator.
     */
    private final Iterator i;

    /**
     * Only trusted code creates a wrapper.
     * @param i the wrapped iterator
     */
    UnmodifiableIterator(Iterator i)
    {
      this.i = i;
    }

    /**
     * Obtains the next element in the underlying collection.
     *
     * @return the next element in the collection.
     * @throws NoSuchElementException if there are no more elements.
     */
    public Object next()
    {
      return i.next();
    }
    /**
     * Tests whether there are still elements to be retrieved from the
     * underlying collection by <code>next()</code>.  When this method
     * returns <code>true</code>, an exception will not be thrown on calling
     * <code>next()</code>.
     *
     * @return <code>true</code> if there is at least one more element in the underlying
     *         collection.
     */
    public boolean hasNext()
    {
      return i.hasNext();
    }

    /**
     * Blocks the removal of elements from the underlying collection by the
     * iterator.
     *
     * @throws UnsupportedOperationException as an unmodifiable collection
     *         does not support the removal of elements by its iterator.
     */
    public void remove()
    {
      throw new UnsupportedOperationException();
    }
  } // class UnmodifiableIterator

  /**
   * Returns an unmodifiable view of the given list. This allows
   * "read-only" access, although changes in the backing list show up
   * in this view. Attempts to modify the list directly, via iterators, or
   * via sublists, will fail with {@link UnsupportedOperationException}.
   * Although this view prevents changes to the structure of the list and
   * its elements, the values referenced by the objects in the list can
   * still be modified.   
   * <p>
   *
   * The returned List implements Serializable, but can only be serialized if
   * the list it wraps is likewise Serializable. In addition, if the wrapped
   * list implements RandomAccess, this does too.
   *
   * @param l the list to wrap
   * @return a read-only view of the list
   * @see Serializable
   * @see RandomAccess
   */
  public static List unmodifiableList(List l)
  {
    if (l instanceof RandomAccess)
      return new UnmodifiableRandomAccessList(l);
    return new UnmodifiableList(l);
  }

  /**
   * The implementation of {@link #unmodifiableList(List)} for sequential
   * lists. This class name is required for compatibility with Sun's JDK
   * serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class UnmodifiableList extends UnmodifiableCollection
    implements List
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -283967356065247728L;


    /**
     * The wrapped list; stored both here and in the superclass to avoid
     * excessive casting. Package visible for use by subclass.
     * @serial the wrapped list
     */
    final List list;

    /**
     * Wrap a given list.
     * @param l the list to wrap
     * @throws NullPointerException if l is null
     */
    UnmodifiableList(List l)
    {
      super(l);
      list = l;
    }

    /**
     * Blocks the addition of an element to the underlying
     * list at a specific index.  This method never returns,
     * throwing an exception instead.
     *
     * @param index The index at which to place the new element.
     * @param o the object to add.
     * @throws UnsupportedOperationException as an unmodifiable
     *         list doesn't support the <code>add()</code> operation.
     */
    public void add(int index, Object o)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Blocks the addition of a collection of elements to the
     * underlying list at a specific index.  This method never
     * returns, throwing an exception instead.
     *
     * @param index The index at which to place the new element.
     * @param c the collections of objects to add.
     * @throws UnsupportedOperationException as an unmodifiable
     *         list doesn't support the <code>addAll()</code> operation.
     */
    public boolean addAll(int index, Collection c)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Returns <code>true</code> if the object, o, is an instance of
     * <code>List</code> with the same size and elements
     * as the underlying list.
     *
     * @param o The object to compare.
     * @return <code>true</code> if o is equivalent to the underlying list.
     */
    public boolean equals(Object o)
    {
      return list.equals(o);
    }

    /**
     * Retrieves the element at a given index in the underlying list.
     *
     * @param index the index of the element to be returned
     * @return the element at index index in this list
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
     */
    public Object get(int index)
    {
      return list.get(index);
    }

    /**
     * Computes the hash code for the underlying list.
     * The exact computation is described in the documentation
     * of the <code>List</code> interface.
     *
     * @return The hash code of the underlying list.
     * @see List#hashCode()
     */
    public int hashCode()
    {
      return list.hashCode();
    }

    /**
     * Obtain the first index at which a given object is to be found in the
     * underlying list.
     *
     * @param o the object to search for
     * @return the least integer n such that <code>o == null ? get(n) == null :
     *         o.equals(get(n))</code>, or -1 if there is no such index.
     * @throws ClassCastException if the type of o is not a valid
     *         type for the underlying list.
     * @throws NullPointerException if o is null and the underlying
     *         list does not support null values.
     */
    public int indexOf(Object o)
    {
      return list.indexOf(o);
    }

    /**
     * Obtain the last index at which a given object is to be found in the
     * underlying list.
     *
     * @return the greatest integer n such that <code>o == null ? get(n) == null
     *         : o.equals(get(n))</code>, or -1 if there is no such index.
     * @throws ClassCastException if the type of o is not a valid
     *         type for the underlying list.
     * @throws NullPointerException if o is null and the underlying
     *         list does not support null values.
     */
    public int lastIndexOf(Object o)
    {
      return list.lastIndexOf(o);
    }

  /**
   * Obtains a list iterator over the underlying list, starting at the beginning
   * and maintaining the unmodifiable nature of this list.
   *
   * @return a <code>UnmodifiableListIterator</code> over the elements of the
   *         underlying list, in order, starting at the beginning.
   */
    public ListIterator listIterator()
    {
      return new UnmodifiableListIterator(list.listIterator());
    }

  /**
   * Obtains a list iterator over the underlying list, starting at the specified
   * index and maintaining the unmodifiable nature of this list.  An initial call
   * to <code>next()</code> will retrieve the element at the specified index,
   * and an initial call to <code>previous()</code> will retrieve the element
   * at index - 1.
   *
   *
   * @param index the position, between 0 and size() inclusive, to begin the
   *        iteration from.
   * @return a <code>UnmodifiableListIterator</code> over the elements of the
   *         underlying list, in order, starting at the specified index.
   * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
   */
    public ListIterator listIterator(int index)
    {
      return new UnmodifiableListIterator(list.listIterator(index));
    }

    /**
     * Blocks the removal of the element at the specified index.
     * This method never returns, throwing an exception instead.
     *
     * @param index The index of the element to remove.
     * @return the removed element.
     * @throws UnsupportedOperationException as an unmodifiable
     *         list does not support the <code>remove()</code>
     *         operation.
     */
    public Object remove(int index)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Blocks the replacement of the element at the specified index.
     * This method never returns, throwing an exception instead.
     *
     * @param index The index of the element to replace.
     * @param o The new object to place at the specified index.
     * @return the replaced element.
     * @throws UnsupportedOperationException as an unmodifiable
     *         list does not support the <code>set()</code>
     *         operation.
     */
    public Object set(int index, Object o)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Obtain a List view of a subsection of the underlying list, from
     * fromIndex (inclusive) to toIndex (exclusive). If the two indices
     * are equal, the sublist is empty. The returned list will be
     * unmodifiable, like this list.  Changes to the elements of the
     * returned list will be reflected in the underlying list. No structural
     * modifications can take place in either list.
     *
     * @param fromIndex the index that the returned list should start from
     *        (inclusive).
     * @param toIndex the index that the returned list should go to (exclusive).
     * @return a List backed by a subsection of the underlying list.
     * @throws IndexOutOfBoundsException if fromIndex &lt; 0
     *         || toIndex &gt; size() || fromIndex &gt; toIndex.
     */
    public List subList(int fromIndex, int toIndex)
    {
      return unmodifiableList(list.subList(fromIndex, toIndex));
    }
  } // class UnmodifiableList

  /**
   * The implementation of {@link #unmodifiableList(List)} for random-access
   * lists. This class name is required for compatibility with Sun's JDK
   * serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class UnmodifiableRandomAccessList
    extends UnmodifiableList implements RandomAccess
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -2542308836966382001L;

    /**
     * Wrap a given list.
     * @param l the list to wrap
     * @throws NullPointerException if l is null
     */
    UnmodifiableRandomAccessList(List l)
    {
      super(l);
    }
  } // class UnmodifiableRandomAccessList

  /**
   * The implementation of {@link UnmodifiableList#listIterator()}.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class UnmodifiableListIterator
    extends UnmodifiableIterator implements ListIterator
  {
    /**
     * The wrapped iterator, stored both here and in the superclass to
     * avoid excessive casting.
     */
    private final ListIterator li;

    /**
     * Only trusted code creates a wrapper.
     * @param li the wrapped iterator
     */
    UnmodifiableListIterator(ListIterator li)
    {
      super(li);
      this.li = li;
    }

    /**
     * Blocks the addition of an object to the list underlying this iterator.
     * This method never returns, throwing an exception instead.
     *
     * @param o The object to add.
     * @throws UnsupportedOperationException as the iterator of an unmodifiable
     *         list does not support the <code>add()</code> operation.
     */
    public void add(Object o)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Tests whether there are still elements to be retrieved from the
     * underlying collection by <code>previous()</code>.  When this method
     * returns <code>true</code>, an exception will not be thrown on calling
     * <code>previous()</code>.
     *
     * @return <code>true</code> if there is at least one more element prior to the
     *         current position in the underlying list.
     */
    public boolean hasPrevious()
    {
      return li.hasPrevious();
    }

    /**
     * Find the index of the element that would be returned by a call to next.
     * If <code>hasNext()</code> returns <code>false</code>, this returns the list size.
     *
     * @return the index of the element that would be returned by
     *         <code>next()</code>.
     */
    public int nextIndex()
    {
      return li.nextIndex();
    }

    /**
     * Obtains the previous element in the underlying list.
     *
     * @return the previous element in the list.
     * @throws NoSuchElementException if there are no more prior elements.
     */
    public Object previous()
    {
      return li.previous();
    }

    /**
     * Find the index of the element that would be returned by a call to
     * previous. If <code>hasPrevious()</code> returns <code>false</code>,
     * this returns -1.
     *
     * @return the index of the element that would be returned by
     *         <code>previous()</code>.
     */
    public int previousIndex()
    {
      return li.previousIndex();
    }

    /**
     * Blocks the replacement of an element in the list underlying this
     * iterator.  This method never returns, throwing an exception instead.
     *
     * @param o The new object to replace the existing one.
     * @throws UnsupportedOperationException as the iterator of an unmodifiable
     *         list does not support the <code>set()</code> operation.
     */
    public void set(Object o)
    {
      throw new UnsupportedOperationException();
    }
  } // class UnmodifiableListIterator

  /**
   * Returns an unmodifiable view of the given map. This allows "read-only"
   * access, although changes in the backing map show up in this view.
   * Attempts to modify the map directly, or via collection views or their
   * iterators will fail with {@link UnsupportedOperationException}.
   * Although this view prevents changes to the structure of the map and its
   * entries, the values referenced by the objects in the map can still be
   * modified.   
   * <p>
   *
   * The returned Map implements Serializable, but can only be serialized if
   * the map it wraps is likewise Serializable.
   *
   * @param m the map to wrap
   * @return a read-only view of the map
   * @see Serializable
   */
  public static Map unmodifiableMap(Map m)
  {
    return new UnmodifiableMap(m);
  }

  /**
   * The implementation of {@link #unmodifiableMap(Map)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class UnmodifiableMap implements Map, Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -1034234728574286014L;

    /**
     * The wrapped map.
     * @serial the real map
     */
    private final Map m;

    /**
     * Cache the entry set.
     */
    private transient Set entries;

    /**
     * Cache the key set.
     */
    private transient Set keys;

    /**
     * Cache the value collection.
     */
    private transient Collection values;

    /**
     * Wrap a given map.
     * @param m the map to wrap
     * @throws NullPointerException if m is null
     */
    UnmodifiableMap(Map m)
    {
      this.m = m;
      if (m == null)
        throw new NullPointerException();
    }

    /**
     * Blocks the clearing of entries from the underlying map.
     * This method never returns, throwing an exception instead.
     *
     * @throws UnsupportedOperationException as an unmodifiable
     *         map does not support the <code>clear()</code> operation.
     */
    public void clear()
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Returns <code>true</code> if the underlying map contains a mapping for
     * the given key.
     *
     * @param key the key to search for
     * @return <code>true</code> if the map contains the key
     * @throws ClassCastException if the key is of an inappropriate type
     * @throws NullPointerException if key is <code>null</code> but the map
     *         does not permit null keys
     */
    public boolean containsKey(Object key)
    {
      return m.containsKey(key);
    }

    /**
     * Returns <code>true</code> if the underlying map contains at least one mapping with
     * the given value.  In other words, it returns <code>true</code> if a value v exists where
     * <code>(value == null ? v == null : value.equals(v))</code>. This usually
     * requires linear time.
     *
     * @param value the value to search for
     * @return <code>true</code> if the map contains the value
     * @throws ClassCastException if the type of the value is not a valid type
     *         for this map.
     * @throws NullPointerException if the value is null and the map doesn't
     *         support null values.
     */
    public boolean containsValue(Object value)
    {
      return m.containsValue(value);
    }

    /**
     * Returns a unmodifiable set view of the entries in the underlying map.
     * Each element in the set is a unmodifiable variant of <code>Map.Entry</code>.
     * The set is backed by the map, so that changes in one show up in the other.
     * Modifications made while an iterator is in progress cause undefined
     * behavior.  These modifications are again limited to the values of
     * the objects.
     *
     * @return the unmodifiable set view of all mapping entries.
     * @see Map.Entry
     */
    public Set entrySet()
    {
      if (entries == null)
        entries = new UnmodifiableEntrySet(m.entrySet());
      return entries;
    }

    /**
     * The implementation of {@link UnmodifiableMap#entrySet()}. This class
     * name is required for compatibility with Sun's JDK serializability.
     *
     * @author Eric Blake (ebb9@email.byu.edu)
     */
    private static final class UnmodifiableEntrySet extends UnmodifiableSet
      implements Serializable
    {
      /**
       * Compatible with JDK 1.4.
       */
      private static final long serialVersionUID = 7854390611657943733L;

      /**
       * Wrap a given set.
       * @param s the set to wrap
       */
      UnmodifiableEntrySet(Set s)
      {
        super(s);
      }

      // The iterator must return unmodifiable map entries.
      public Iterator iterator()
      {
        return new UnmodifiableIterator(c.iterator())
	{
	  /**
	   * Obtains the next element from the underlying set of
	   * map entries.
	   *
	   * @return the next element in the collection.
	   * @throws NoSuchElementException if there are no more elements.
	   */
          public Object next()
          {
            final Map.Entry e = (Map.Entry) super.next();
            return new Map.Entry()
	    {
	      /**
	       * Returns <code>true</code> if the object, o, is also a map entry with an
	       * identical key and value.
	       *
	       * @param o the object to compare.
	       * @return <code>true</code> if o is an equivalent map entry.
	       */
              public boolean equals(Object o)
              {
                return e.equals(o);
              }
	      
	      /**
	       * Returns the key of this map entry.
	       *
	       * @return the key.
	       */
              public Object getKey()
              {
                return e.getKey();
              }

	      /**
	       * Returns the value of this map entry.
	       *
	       * @return the value.
	       */
              public Object getValue()
              {
                return e.getValue();
              }

	      /**
	       * Computes the hash code of this map entry.
	       * The computation is described in the <code>Map</code>
	       * interface documentation.
	       *
	       * @return the hash code of this entry.
	       * @see Map#hashCode()
	       */
              public int hashCode()
              {
                return e.hashCode();
              }

	      /**
	       * Blocks the alteration of the value of this map entry.
	       * This method never returns, throwing an exception instead.
	       *
	       * @param value The new value.
	       * @throws UnsupportedOperationException as an unmodifiable
	       *         map entry does not support the <code>setValue()</code>
	       *         operation.
	       */
              public Object setValue(Object value)
              {
                throw new UnsupportedOperationException();
              }

	      /**
	       * Returns a textual representation of the map entry.
	       *
	       * @return The map entry as a <code>String</code>.
	       */
              public String toString()
              {
                return e.toString();
              }
	    };
          }
	};
      }
    } // class UnmodifiableEntrySet

    /**
     * Returns <code>true</code> if the object, o, is also an instance
     * of <code>Map</code> with an equal set of map entries.
     *
     * @param o The object to compare.
     * @return <code>true</code> if o is an equivalent map.
     */
    public boolean equals(Object o)
    {
      return m.equals(o);
    }

    /**
     * Returns the value associated with the supplied key or
     * null if no such mapping exists.  An ambiguity can occur
     * if null values are accepted by the underlying map.
     * In this case, <code>containsKey()</code> can be used
     * to separate the two possible cases of a null result.
     *
     * @param key The key to look up.
     * @return the value associated with the key, or null if key not in map.
     * @throws ClassCastException if the key is an inappropriate type.
     * @throws NullPointerException if this map does not accept null keys.
     * @see #containsKey(Object)
     */
    public Object get(Object key)
    {
      return m.get(key);
    }

    /**
     * Blocks the addition of a new entry to the underlying map.
     * This method never returns, throwing an exception instead.
     *
     * @param key The new key.
     * @param value The new value.
     * @return the previous value of the key, or null if there was no mapping.
     * @throws UnsupportedOperationException as an unmodifiable
     *         map does not support the <code>put()</code> operation.
     */
    public Object put(Object key, Object value)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Computes the hash code for the underlying map, as the sum
     * of the hash codes of all entries.
     *
     * @return The hash code of the underlying map.
     * @see Map.Entry#hashCode()
     */
    public int hashCode()
    {
      return m.hashCode();
    }

    /**
     * Returns <code>true</code> if the underlying map contains no entries.
     *
     * @return <code>true</code> if the map is empty.
     */
    public boolean isEmpty()
    {
      return m.isEmpty();
    }

    /**
     * Returns a unmodifiable set view of the keys in the underlying map.
     * The set is backed by the map, so that changes in one show up in the other.
     * Modifications made while an iterator is in progress cause undefined
     * behavior.  These modifications are again limited to the values of
     * the keys.
     *
     * @return the set view of all keys.
     */
    public Set keySet()
    {
      if (keys == null)
        keys = new UnmodifiableSet(m.keySet());
      return keys;
    }

    /**
     * Blocks the addition of the entries in the supplied map.
     * This method never returns, throwing an exception instead.
     *
     * @param m The map, the entries of which should be added
     *          to the underlying map.
     * @throws UnsupportedOperationException as an unmodifiable
     *         map does not support the <code>putAll</code> operation.
     */
    public void putAll(Map m)
    {
      throw new UnsupportedOperationException();
    }

    /**
     * Blocks the removal of an entry from the map.
     * This method never returns, throwing an exception instead.
     *
     * @param o The key of the entry to remove.
     * @return The value the key was associated with, or null
     *         if no such mapping existed.  Null is also returned
     *         if the removed entry had a null key.
     * @throws UnsupportedOperationException as an unmodifiable
     *         map does not support the <code>remove</code> operation.
     */
    public Object remove(Object o)
    {
      throw new UnsupportedOperationException();
    }


    /**
     * Returns the number of key-value mappings in the underlying map.
     * If there are more than Integer.MAX_VALUE mappings, Integer.MAX_VALUE
     * is returned.
     *
     * @return the number of mappings.
     */
    public int size()
    {
      return m.size();
    }

    /**
     * Returns a textual representation of the map.
     *
     * @return The map in the form of a <code>String</code>.
     */
    public String toString()
    {
      return m.toString();
    }

    /**
     * Returns a unmodifiable collection view of the values in the underlying map.
     * The collection is backed by the map, so that changes in one show up in the other.
     * Modifications made while an iterator is in progress cause undefined
     * behavior.  These modifications are again limited to the values of
     * the keys.
     *
     * @return the collection view of all values.
     */
    public Collection values()
    {
      if (values == null)
        values = new UnmodifiableCollection(m.values());
      return values;
    }
  } // class UnmodifiableMap

  /**
   * Returns an unmodifiable view of the given set. This allows
   * "read-only" access, although changes in the backing set show up
   * in this view. Attempts to modify the set directly or via iterators
   * will fail with {@link UnsupportedOperationException}.
   * Although this view prevents changes to the structure of the set and its
   * entries, the values referenced by the objects in the set can still be
   * modified.   
   * <p>
   *
   * The returned Set implements Serializable, but can only be serialized if
   * the set it wraps is likewise Serializable.
   *
   * @param s the set to wrap
   * @return a read-only view of the set
   * @see Serializable
   */
  public static Set unmodifiableSet(Set s)
  {
    return new UnmodifiableSet(s);
  }

  /**
   * The implementation of {@link #unmodifiableSet(Set)}. This class
   * name is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class UnmodifiableSet extends UnmodifiableCollection
    implements Set
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -9215047833775013803L;

    /**
     * Wrap a given set.
     * @param s the set to wrap
     * @throws NullPointerException if s is null
     */
    UnmodifiableSet(Set s)
    {
      super(s);
    }

    /**
     * Returns <code>true</code> if the object, o, is also an instance of
     * <code>Set</code> of the same size and with the same entries.
     *
     * @return <code>true</code> if o is an equivalent set.
     */
    public boolean equals(Object o)
    {
      return c.equals(o);
    }

    /**
     * Computes the hash code of this set, as the sum of the
     * hash codes of all elements within the set.
     *
     * @return the hash code of the set.
     */ 
    public int hashCode()
    {
      return c.hashCode();
    }
  } // class UnmodifiableSet

  /**
   * Returns an unmodifiable view of the given sorted map. This allows
   * "read-only" access, although changes in the backing map show up in this
   * view. Attempts to modify the map directly, via subviews, via collection
   * views, or iterators, will fail with {@link UnsupportedOperationException}.
   * Although this view prevents changes to the structure of the map and its
   * entries, the values referenced by the objects in the map can still be
   * modified.   
   * <p>
   *
   * The returned SortedMap implements Serializable, but can only be
   * serialized if the map it wraps is likewise Serializable.
   *
   * @param m the map to wrap
   * @return a read-only view of the map
   * @see Serializable
   */
  public static SortedMap unmodifiableSortedMap(SortedMap m)
  {
    return new UnmodifiableSortedMap(m);
  }

  /**
   * The implementation of {@link #unmodifiableSortedMap(SortedMap)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class UnmodifiableSortedMap extends UnmodifiableMap
    implements SortedMap
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -8806743815996713206L;

    /**
     * The wrapped map; stored both here and in the superclass to avoid
     * excessive casting.
     * @serial the wrapped map
     */
    private final SortedMap sm;

    /**
     * Wrap a given map.
     * @param sm the map to wrap
     * @throws NullPointerException if sm is null
     */
    UnmodifiableSortedMap(SortedMap sm)
    {
      super(sm);
      this.sm = sm;
    }

    /**
     * Returns the comparator used in sorting the underlying map,
     * or null if it is the keys' natural ordering.
     *
     * @return the sorting comparator.
     */
    public Comparator comparator()
    {
      return sm.comparator();
    }

    /**
     * Returns the first (lowest sorted) key in the map.
     *
     * @return the first key.
     * @throws NoSuchElementException if this map is empty.
     */
    public Object firstKey()
    {
      return sm.firstKey();
    }

    /**
     * Returns a unmodifiable view of the portion of the map strictly less
     * than toKey. The view is backed by the underlying map, so changes in
     * one show up in the other.  The submap supports all optional operations
     * of the original.  This operation is equivalent to
     * <code>subMap(firstKey(), toKey)</code>.
     * <p>
     *
     * The returned map throws an IllegalArgumentException any time a key is
     * used which is out of the range of toKey. Note that the endpoint, toKey,
     * is not included; if you want this value to be included, pass its successor
     * object in to toKey.  For example, for Integers, you could request
     * <code>headMap(new Integer(limit.intValue() + 1))</code>.
     *
     * @param toKey the exclusive upper range of the submap.
     * @return the submap.
     * @throws ClassCastException if toKey is not comparable to the map contents.
     * @throws IllegalArgumentException if this is a subMap, and toKey is out
     *         of range.
     * @throws NullPointerException if toKey is null but the map does not allow
     *         null keys.
     */
    public SortedMap headMap(Object toKey)
    {
      return new UnmodifiableSortedMap(sm.headMap(toKey));
    }

    /**
     * Returns the last (highest sorted) key in the map.
     *
     * @return the last key.
     * @throws NoSuchElementException if this map is empty.
     */
    public Object lastKey()
    {
      return sm.lastKey();
    }

    /**
     * Returns a unmodifiable view of the portion of the map greater than or
     * equal to fromKey, and strictly less than toKey. The view is backed by
     * the underlying map, so changes in one show up in the other. The submap
     * supports all optional operations of the original.
     * <p>
     *
     * The returned map throws an IllegalArgumentException any time a key is
     * used which is out of the range of fromKey and toKey. Note that the
     * lower endpoint is included, but the upper is not; if you want to
     * change the inclusion or exclusion of an endpoint, pass its successor
     * object in instead.  For example, for Integers, you could request
     * <code>subMap(new Integer(lowlimit.intValue() + 1),
     * new Integer(highlimit.intValue() + 1))</code> to reverse
     * the inclusiveness of both endpoints.
     *
     * @param fromKey the inclusive lower range of the submap.
     * @param toKey the exclusive upper range of the submap.
     * @return the submap.
     * @throws ClassCastException if fromKey or toKey is not comparable to
     *         the map contents.
     * @throws IllegalArgumentException if this is a subMap, and fromKey or
     *         toKey is out of range.
     * @throws NullPointerException if fromKey or toKey is null but the map
     *         does not allow null keys.
     */
    public SortedMap subMap(Object fromKey, Object toKey)
    {
      return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
    }

    /**
     * Returns a unmodifiable view of the portion of the map greater than or
     * equal to fromKey. The view is backed by the underlying map, so changes
     * in one show up in the other. The submap supports all optional operations
     * of the original.
     * <p>
     *
     * The returned map throws an IllegalArgumentException any time a key is
     * used which is out of the range of fromKey. Note that the endpoint, fromKey, is
     * included; if you do not want this value to be included, pass its successor object in
     * to fromKey.  For example, for Integers, you could request
     * <code>tailMap(new Integer(limit.intValue() + 1))</code>.
     *
     * @param fromKey the inclusive lower range of the submap
     * @return the submap
     * @throws ClassCastException if fromKey is not comparable to the map
     *         contents
     * @throws IllegalArgumentException if this is a subMap, and fromKey is out
     *         of range
     * @throws NullPointerException if fromKey is null but the map does not allow
     *         null keys
     */
    public SortedMap tailMap(Object fromKey)
    {
      return new UnmodifiableSortedMap(sm.tailMap(fromKey));
    }
  } // class UnmodifiableSortedMap

  /**
   * Returns an unmodifiable view of the given sorted set. This allows
   * "read-only" access, although changes in the backing set show up
   * in this view. Attempts to modify the set directly, via subsets, or via
   * iterators, will fail with {@link UnsupportedOperationException}.
   * Although this view prevents changes to the structure of the set and its
   * entries, the values referenced by the objects in the set can still be
   * modified.   
   * <p>
   *
   * The returns SortedSet implements Serializable, but can only be
   * serialized if the set it wraps is likewise Serializable.
   *
   * @param s the set to wrap
   * @return a read-only view of the set
   * @see Serializable
   */
  public static SortedSet unmodifiableSortedSet(SortedSet s)
  {
    return new UnmodifiableSortedSet(s);
  }

  /**
   * The implementation of {@link #synchronizedSortedMap(SortedMap)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class UnmodifiableSortedSet extends UnmodifiableSet
    implements SortedSet
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -4929149591599911165L;

    /**
     * The wrapped set; stored both here and in the superclass to avoid
     * excessive casting.
     * @serial the wrapped set
     */
    private SortedSet ss;

    /**
     * Wrap a given set.
     * @param ss the set to wrap
     * @throws NullPointerException if ss is null
     */
    UnmodifiableSortedSet(SortedSet ss)
    {
      super(ss);
      this.ss = ss;
    }

    /**
     * Returns the comparator used in sorting the underlying set,
     * or null if it is the elements' natural ordering.
     *
     * @return the sorting comparator
     */
    public Comparator comparator()
    {
      return ss.comparator();
    }

    /**
     * Returns the first (lowest sorted) element in the underlying
     * set.
     *
     * @return the first element.
     * @throws NoSuchElementException if the set is empty.
     */
    public Object first()
    {
      return ss.first();
    }

    /**
     * Returns a unmodifiable view of the portion of the set strictly
     * less than toElement. The view is backed by the underlying set,
     * so changes in one show up in the other.  The subset supports
     * all optional operations of the original.  This operation
     * is equivalent to <code>subSet(first(), toElement)</code>.
     * <p>
     *
     * The returned set throws an IllegalArgumentException any time an element is
     * used which is out of the range of toElement. Note that the endpoint, toElement,
     * is not included; if you want this value included, pass its successor object in to
     * toElement.  For example, for Integers, you could request
     * <code>headSet(new Integer(limit.intValue() + 1))</code>.
     *
     * @param toElement the exclusive upper range of the subset
     * @return the subset.
     * @throws ClassCastException if toElement is not comparable to the set
     *         contents.
     * @throws IllegalArgumentException if this is a subSet, and toElement is out
     *         of range.
     * @throws NullPointerException if toElement is null but the set does not
     *         allow null elements.
     */
    public SortedSet headSet(Object toElement)
    {
      return new UnmodifiableSortedSet(ss.headSet(toElement));
    }

    /**
     * Returns the last (highest sorted) element in the underlying
     * set.
     *
     * @return the last element.
     * @throws NoSuchElementException if the set is empty.
     */
    public Object last()
    {
      return ss.last();
    }

    /**
     * Returns a unmodifiable view of the portion of the set greater than or
     * equal to fromElement, and strictly less than toElement. The view is backed by
     * the underlying set, so changes in one show up in the other. The subset
     * supports all optional operations of the original.
     * <p>
     *
     * The returned set throws an IllegalArgumentException any time an element is
     * used which is out of the range of fromElement and toElement. Note that the
     * lower endpoint is included, but the upper is not; if you want to
     * change the inclusion or exclusion of an endpoint, pass its successor
     * object in instead.  For example, for Integers, you can request
     * <code>subSet(new Integer(lowlimit.intValue() + 1),
     * new Integer(highlimit.intValue() + 1))</code> to reverse
     * the inclusiveness of both endpoints.
     *
     * @param fromElement the inclusive lower range of the subset.
     * @param toElement the exclusive upper range of the subset.
     * @return the subset.
     * @throws ClassCastException if fromElement or toElement is not comparable
     *         to the set contents.
     * @throws IllegalArgumentException if this is a subSet, and fromElement or
     *         toElement is out of range.
     * @throws NullPointerException if fromElement or toElement is null but the
     *         set does not allow null elements.
     */
    public SortedSet subSet(Object fromElement, Object toElement)
    {
      return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));
    }

    /**
     * Returns a unmodifiable view of the portion of the set greater than or equal to
     * fromElement. The view is backed by the underlying set, so changes in one show up
     * in the other. The subset supports all optional operations of the original.
     * <p>
     *
     * The returned set throws an IllegalArgumentException any time an element is
     * used which is out of the range of fromElement. Note that the endpoint,
     * fromElement, is included; if you do not want this value to be included, pass its
     * successor object in to fromElement.  For example, for Integers, you could request
     * <code>tailSet(new Integer(limit.intValue() + 1))</code>.
     *
     * @param fromElement the inclusive lower range of the subset
     * @return the subset.
     * @throws ClassCastException if fromElement is not comparable to the set
     *         contents.
     * @throws IllegalArgumentException if this is a subSet, and fromElement is
     *         out of range.
     * @throws NullPointerException if fromElement is null but the set does not
     *         allow null elements.
     */
    public SortedSet tailSet(Object fromElement)
    {
      return new UnmodifiableSortedSet(ss.tailSet(fromElement));
    }
  } // class UnmodifiableSortedSet
} // class Collections
