/* Collections.java -- Utility class with methods to operate on collections
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006
   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 gnu.java.lang.CPStringBuilder;

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)
 * @author Tom Tromey (tromey@redhat.com)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @see Collection
 * @see Set
 * @see List
 * @see Map
 * @see Arrays
 * @since 1.2
 * @status updated to 1.5
 */
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();

  /**
   * Returns an immutable, serializable parameterized empty set.
   * Unlike the constant <code>EMPTY_SET</code>, the set returned by
   * this method is type-safe.
   *
   * @return an empty parameterized set.
   * @since 1.5
   */
  public static final <T> Set<T> emptySet()
  {
    /* FIXME: Could this be optimized? */
    return new EmptySet<T>();
  }

  /**
   * 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<T> extends AbstractSet<T>
    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<T> iterator()
    {
      return (Iterator<T>) 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 <E> E[] toArray(E[] 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();

  /**
   * Returns an immutable, serializable parameterized empty list.
   * Unlike the constant <code>EMPTY_LIST</code>, the list returned by
   * this method is type-safe.
   *
   * @return an empty parameterized list.
   * @since 1.5
   */
  public static final <T> List<T> emptyList()
  {
    /* FIXME: Could this be optimized? */
    return new EmptyList<T>();
  }

  /**
   * 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<T> extends AbstractList<T>
    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 T 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 <E> E[] toArray(E[] 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();

  /**
   * Returns an immutable, serializable parameterized empty map.
   * Unlike the constant <code>EMPTY_MAP</code>, the map returned by
   * this method is type-safe.
   *
   * @return an empty parameterized map.
   * @since 1.5
   */
  public static final <K,V> Map<K,V> emptyMap()
  {
    /* FIXME: Could this be optimized? */
    return new EmptyMap<K,V>();
  }

  /**
   * 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<K, V> extends AbstractMap<K, V>
    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<Map.Entry<K, V>> 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 V 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<K> 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 V 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<V> 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 <T> int compare(T o1, T o2, Comparator<? super T> 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 <T> int binarySearch(List<? extends Comparable<? super T>> l,
                                     T 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 <T> int binarySearch(List<? extends T> l, T key,
                                     Comparator<? super T> 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<T> itr = ((List<T>) l).listIterator();
        int i = 0;
        T 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(((List<T>) 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 <T> void copy(List<? super T> dest, List<? extends T> source)
  {
    int pos = source.size();
    if (dest.size() < pos)
      throw new IndexOutOfBoundsException("Source does not fit in dest");

    Iterator<? extends T> i1 = source.iterator();
    ListIterator<? super T> 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 <T> Enumeration<T> enumeration(Collection<T> c)
  {
    final Iterator<T> i = c.iterator();
    return new Enumeration<T>()
    {
      /**
       * 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 T 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 <T> void fill(List<? super T> l, T val)
  {
    ListIterator<? super T> 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 <T> ArrayList<T> list(Enumeration<T> e)
  {
    ArrayList<T> l = new ArrayList<T>();
    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 <T extends Object & Comparable<? super T>>
  T max(Collection<? extends T> 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 <T> T max(Collection<? extends T> c,
                          Comparator<? super T> order)
  {
    Iterator<? extends T> itr = c.iterator();
    T max = itr.next(); // throws NoSuchElementException
    int csize = c.size();
    for (int i = 1; i < csize; i++)
      {
        T 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 <T extends Object & Comparable<? super T>>
  T min(Collection<? extends T> 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 <T> T min(Collection<? extends T> c,
                          Comparator<? super T> order)
  {
    Iterator<? extends T> itr = c.iterator();
    T min = itr.next(); // throws NoSuchElementExcception
    int csize = c.size();
    for (int i = 1; i < csize; i++)
      {
        T 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 <T> List<T> nCopies(final int n, final T o)
  {
    return new CopiesList<T>(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<T> extends AbstractList<T>
    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 T element;

    /**
     * Constructs the list.
     *
     * @param n the count
     * @param o the object
     * @throws IllegalArgumentException if n &lt; 0
     */
    CopiesList(int n, T 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 T 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<T> subList(int from, int to)
    {
      if (from < 0 || to > n)
        throw new IndexOutOfBoundsException();
      return new CopiesList<T>(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()
    {
      CPStringBuilder r = new CPStringBuilder("{");
      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 <T> boolean replaceAll(List<T> list, T oldval, T newval)
  {
    ListIterator<T> 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 o1 = i1.next();
    Object o2 = i2.previous();
        i1.set(o2);
        i2.set(o1);
        ++pos1;
        --pos2;
      }
  }

  /**
   * Get a comparator that implements the reverse of the ordering
   * specified by the given Comparator. If the Comparator is null,
   * this is equivalent to {@link #reverseOrder()}.  The return value
   * of this method is Serializable, if the specified Comparator is
   * either Serializable or null.
   *
   * @param c the comparator to invert
   * @return a comparator that imposes reverse ordering
   * @see Comparable
   * @see Serializable
   *
   * @since 1.5
   */
  public static <T> Comparator<T> reverseOrder(final Comparator<T> c)
  {
    if (c == null)
      return (Comparator<T>) rcInstance;
    return new ReverseComparator<T> ()
    {
      public int compare(T a, T b)
      {
        return - c.compare(a, b);
      }
    };
  }

  /**
   * 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 <T> Comparator<T> reverseOrder()
  {
    return (Comparator<T>) 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 class ReverseComparator<T>
    implements Comparator<T>, 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(T a, T 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.
        List<Object> objList = (List<Object>) list;
        while (--lcm >= 0)
          {
            Object o = objList.get(lcm);
            for (int i = lcm + distance; i != lcm; i = (i + distance) % size)
              o = objList.set(i, o);
            objList.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();
    List<Object> list = (List<Object>) l;
    ListIterator<Object> i = list.listIterator(lsize);
    boolean sequential = isSequential(l);
    Object[] a = null; // stores a copy of the list for the sequential case

    if (sequential)
      a = list.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 = list.set(swap, i.previous());

        i.set(o);
      }
  }

  /**
   * Returns the frequency of the specified object within the supplied
   * collection.  The frequency represents the number of occurrences of
   * elements within the collection which return <code>true</code> when
   * compared with the object using the <code>equals</code> method.
   *
   * @param c the collection to scan for occurrences of the object.
   * @param o the object to locate occurrances of within the collection.
   * @throws NullPointerException if the collection is <code>null</code>.
   * @since 1.5
   */
  public static int frequency (Collection<?> c, Object o)
  {
    int result = 0;
    final Iterator<?> it = c.iterator();
    while (it.hasNext())
      {
        Object v = it.next();
        if (AbstractCollection.equals(o, v))
          ++result;
      }
    return result;
  }

  /**
   * Adds all the specified elements to the given collection, in a similar
   * way to the <code>addAll</code> method of the <code>Collection</code>.
   * However, this is a variable argument method which allows the new elements
   * to be specified individually or in array form, as opposed to the list
   * required by the collection's <code>addAll</code> method.  This has
   * benefits in both simplicity (multiple elements can be added without
   * having to be wrapped inside a grouping structure) and efficiency
   * (as a redundant list doesn't have to be created to add an individual
   * set of elements or an array).
   *
   * @param c the collection to which the elements should be added.
   * @param a the elements to be added to the collection.
   * @return true if the collection changed its contents as a result.
   * @throws UnsupportedOperationException if the collection does not support
   *                                       addition.
   * @throws NullPointerException if one or more elements in a are null,
   *                              and the collection does not allow null
   *                              elements.  This exception is also thrown
   *                              if either <code>c</code> or <code>a</code>
   *                              are null.
   * @throws IllegalArgumentException if the collection won't allow an element
   *                                  to be added for some other reason.
   * @since 1.5
   */
  public static <T> boolean addAll(Collection<? super T> c, T... a)
  {
    boolean overall = false;

    for (T element : a)
      {
        boolean result = c.add(element);
        if (result)
          overall = true;
      }
    return overall;
  }

  /**
   * Returns true if the two specified collections have no elements in
   * common.  This method may give unusual results if one or both collections
   * use a non-standard equality test.  In the trivial case of comparing
   * a collection with itself, this method returns true if, and only if,
   * the collection is empty.
   *
   * @param c1 the first collection to compare.
   * @param c2 the second collection to compare.
   * @return true if the collections are disjoint.
   * @throws NullPointerException if either collection is null.
   * @since 1.5
   */
  public static boolean disjoint(Collection<?> c1, Collection<?> c2)
  {
    Collection<Object> oc1 = (Collection<Object>) c1;
    final Iterator<Object> it = oc1.iterator();
    while (it.hasNext())
      if (c2.contains(it.next()))
        return false;
    return true;
  }


  /**
   * 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 <T> Set<T> singleton(T o)
  {
    return new SingletonSet<T>(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<T> extends AbstractSet<T>
    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 T element;

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

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

    /**
     * Returns an iterator over the lone element.
     */
    public Iterator<T> iterator()
    {
      return new Iterator<T>()
      {
        /**
         * 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 T 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 <T> List<T> singletonList(T o)
  {
    return new SingletonList<T>(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<T> extends AbstractList<T>
    implements Serializable, RandomAccess
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 3093736618740652951L;

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

    /**
     * Construct a singleton.
     * @param o the element
     */
    SingletonList(T 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 T 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<T> 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 <K, V> Map<K, V> singletonMap(K key, V value)
  {
    return new SingletonMap<K, V>(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<K, V> extends AbstractMap<K, V>
    implements Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -6979724477215052911L;

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

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

    /**
     * Cache the entry set.
     */
    private transient Set<Map.Entry<K, V>> entries;

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

    /**
     * There is a single immutable entry.
     *
     * @return A singleton containing the map entry.
     */
    public Set<Map.Entry<K, V>> entrySet()
    {
      if (entries == null)
        {
          Map.Entry<K,V> entry = new AbstractMap.SimpleEntry<K, V>(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 V setValue(V o)
            {
              throw new UnsupportedOperationException();
            }
          };
          entries = singleton(entry);
        }
      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 V 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<K> 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<V> 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 (<code>null</code> not permitted)
   * @throws ClassCastException if some items are not mutually comparable
   * @throws UnsupportedOperationException if the List is not modifiable
   * @throws NullPointerException if the list is <code>null</code>, or contains
   *     some element that is <code>null</code>.
   * @see Arrays#sort(Object[])
   */
  public static <T extends Comparable<? super T>> void sort(List<T> 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 (<code>null</code> not permitted)
   * @param c the Comparator specifying the ordering for the elements, or
   *        <code>null</code> 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 the List is <code>null</code> or
   *         <code>null</code> is compared by natural ordering (only possible
   *         when c is <code>null</code>)
   *
   * @see Arrays#sort(Object[], Comparator)
   */
  public static <T> void sort(List<T> l, Comparator<? super T> c)
  {
    T[] a = (T[]) l.toArray();
    Arrays.sort(a, c);
    ListIterator<T> 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)
  {
    List<Object> list = (List<Object>) l;
    list.set(i, list.set(j, list.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 <T> Collection<T> synchronizedCollection(Collection<T> c)
  {
    return new SynchronizedCollection<T>(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<T>
    implements Collection<T>, 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<T> 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<T> 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<T> 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(T 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<? extends T> 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<T> iterator()
    {
      synchronized (mutex)
        {
          return new SynchronizedIterator<T>(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 <T> T[] toArray(T[] 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<T> implements Iterator<T>
  {
    /**
     * The object to synchronize on. Package visible for use by subclass.
     */
    final Object mutex;

    /**
     * The wrapped iterator.
     */
    private final Iterator<T> i;

    /**
     * Only trusted code creates a wrapper, with the specified sync.
     * @param sync the mutex
     * @param i the wrapped iterator
     */
    SynchronizedIterator(Object sync, Iterator<T> 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 T 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 <T> List<T> synchronizedList(List<T> l)
  {
    if (l instanceof RandomAccess)
      return new SynchronizedRandomAccessList<T>(l);
    return new SynchronizedList<T>(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<T> extends SynchronizedCollection<T>
    implements List<T>
  {
    /**
     * 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<T> list;

    /**
     * Wrap a given list.
     * @param l the list to wrap
     * @throws NullPointerException if l is null
     */
    SynchronizedList(List<T> 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<T> 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, T 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<? extends T> 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 T 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<T> listIterator()
    {
      synchronized (mutex)
        {
          return new SynchronizedListIterator<T>(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<T> listIterator(int index)
    {
      synchronized (mutex)
        {
          return new SynchronizedListIterator<T>(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 T 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 T set(int index, T 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<T> subList(int fromIndex, int toIndex)
    {
      synchronized (mutex)
        {
          return new SynchronizedList<T>(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<T>
    extends SynchronizedList<T> 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<T> 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<T> 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<T> subList(int fromIndex, int toIndex)
    {
      synchronized (mutex)
        {
          return new SynchronizedRandomAccessList<T>(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<T>
    extends SynchronizedIterator<T> implements ListIterator<T>
  {
    /**
     * The wrapped iterator, stored both here and in the superclass to
     * avoid excessive casting.
     */
    private final ListIterator<T> li;

    /**
     * Only trusted code creates a wrapper, with the specified sync.
     * @param sync the mutex
     * @param li the wrapped iterator
     */
    SynchronizedListIterator(Object sync, ListIterator<T> 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(T 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 T 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(T 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 <K, V> Map<K, V> synchronizedMap(Map<K, V> m)
  {
    return new SynchronizedMap<K, V>(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<K, V> implements Map<K, V>, Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 1978198479659022715L;

    /**
     * The wrapped map.
     * @serial the real map
     */
    private final Map<K, V> 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<Map.Entry<K, V>> entries;

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

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

    /**
     * Wrap a given map.
     * @param m the map to wrap
     * @throws NullPointerException if m is null
     */
    SynchronizedMap(Map<K, V> 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<K, V> 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<Map.Entry<K, V>> entrySet()
    {
      // Define this here to spare some nesting.
      class SynchronizedMapEntry<K, V> implements Map.Entry<K, V>
      {
        final Map.Entry<K, V> e;
        SynchronizedMapEntry(Map.Entry<K, V> o)
        {
          e = 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 K 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 V 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 V setValue(V 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<Map.Entry<K, V>>(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<Map.Entry<K, V>> iterator()
              {
                synchronized (super.mutex)
                  {
                    return new SynchronizedIterator<Map.Entry<K, V>>(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 Map.Entry<K, V> next()
                      {
                        synchronized (super.mutex)
                          {
                            return new SynchronizedMapEntry<K, V>(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 V 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<K> keySet()
    {
      if (keys == null)
        synchronized (mutex)
          {
            keys = new SynchronizedSet<K>(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 V put(K key, V 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<? extends K, ? extends V> 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 V 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<V> values()
    {
      if (values == null)
        synchronized (mutex)
          {
            values = new SynchronizedCollection<V>(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 <T> Set<T> synchronizedSet(Set<T> s)
  {
    return new SynchronizedSet<T>(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<T> extends SynchronizedCollection<T>
    implements Set<T>
  {
    /**
     * 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<T> 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<T> 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 <K, V> SortedMap<K, V> synchronizedSortedMap(SortedMap<K, V> m)
  {
    return new SynchronizedSortedMap<K, V>(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<K, V>
    extends SynchronizedMap<K, V>
    implements SortedMap<K, V>
  {
    /**
     * 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<K, V> sm;

    /**
     * Wrap a given map.
     * @param sm the map to wrap
     * @throws NullPointerException if sm is null
     */
    SynchronizedSortedMap(SortedMap<K, V> 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<K, V> 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<? super K> 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 K 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<K, V> headMap(K toKey)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedMap<K, V>(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 K 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<K, V> subMap(K fromKey, K toKey)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedMap<K, V>(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<K, V> tailMap(K fromKey)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedMap<K, V>(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 <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
  {
    return new SynchronizedSortedSet<T>(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<T>
    extends SynchronizedSet<T>
    implements SortedSet<T>
  {
    /**
     * 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<T> ss;

    /**
     * Wrap a given set.
     * @param ss the set to wrap
     * @throws NullPointerException if ss is null
     */
    SynchronizedSortedSet(SortedSet<T> 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<T> 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<? super T> 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 T 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<T> headSet(T toElement)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedSet<T>(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 T 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<T> subSet(T fromElement, T toElement)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedSet<T>(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<T> tailSet(T fromElement)
    {
      synchronized (mutex)
        {
          return new SynchronizedSortedSet<T>(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 <T> Collection<T> unmodifiableCollection(Collection<? extends T> c)
  {
    return new UnmodifiableCollection<T>(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<T>
    implements Collection<T>, 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<? extends T> c;

    /**
     * Wrap a given collection.
     * @param c the collection to wrap
     * @throws NullPointerException if c is null
     */
    UnmodifiableCollection(Collection<? extends T> 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(T 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<? extends T> 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<T> iterator()
    {
      return new UnmodifiableIterator<T>(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 <S> S[] toArray(S[] 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<T> implements Iterator<T>
  {
    /**
     * The wrapped iterator.
     */
    private final Iterator<? extends T> i;

    /**
     * Only trusted code creates a wrapper.
     * @param i the wrapped iterator
     */
    UnmodifiableIterator(Iterator<? extends T> 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 T 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 <T> List<T> unmodifiableList(List<? extends T> l)
  {
    if (l instanceof RandomAccess)
      return new UnmodifiableRandomAccessList<T>(l);
    return new UnmodifiableList<T>(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<T> extends UnmodifiableCollection<T>
    implements List<T>
  {
    /**
     * 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<T> list;

    /**
     * Wrap a given list.
     * @param l the list to wrap
     * @throws NullPointerException if l is null
     */
    UnmodifiableList(List<? extends T> l)
    {
      super(l);
      list = (List<T>) 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, T 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<? extends T> 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 T 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<T> listIterator()
    {
      return new UnmodifiableListIterator<T>(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<T> listIterator(int index)
    {
      return new UnmodifiableListIterator<T>(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 T 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 T set(int index, T 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<T> 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<T>
    extends UnmodifiableList<T> 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<? extends T> l)
    {
      super(l);
    }
  } // class UnmodifiableRandomAccessList

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

    /**
     * Only trusted code creates a wrapper.
     * @param li the wrapped iterator
     */
    UnmodifiableListIterator(ListIterator<T> 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(T 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 T 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(T 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 <K, V> Map<K, V> unmodifiableMap(Map<? extends K,
                                                 ? extends V> m)
  {
    return new UnmodifiableMap<K, V>(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<K, V> implements Map<K, V>, Serializable
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = -1034234728574286014L;

    /**
     * The wrapped map.
     * @serial the real map
     */
    private final Map<K, V> m;

    /**
     * Cache the entry set.
     */
    private transient Set<Map.Entry<K, V>> entries;

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

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

    /**
     * Wrap a given map.
     * @param m the map to wrap
     * @throws NullPointerException if m is null
     */
    UnmodifiableMap(Map<? extends K, ? extends V> m)
    {
      this.m = (Map<K,V>) 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<Map.Entry<K, V>> entrySet()
    {
      if (entries == null)
        entries = new UnmodifiableEntrySet<K,V>(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<K,V>
      extends UnmodifiableSet<Map.Entry<K,V>>
      implements Serializable
    {
      // Unmodifiable implementation of Map.Entry used as return value for
      // UnmodifiableEntrySet accessors (iterator, toArray, toArray(Object[]))
      private static final class UnmodifiableMapEntry<K,V>
          implements Map.Entry<K,V>
      {
        private final Map.Entry<K,V> e;

        private UnmodifiableMapEntry(Map.Entry<K,V> e)
        {
          super();
          this.e = e;
        }

        /**
         * 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 K getKey()
        {
          return e.getKey();
        }

        /**
         * Returns the value of this map entry.
         *
         * @return the value.
         */
        public V 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 V setValue(V 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();
        }
      }

      /**
       * Compatible with JDK 1.4.
       */
      private static final long serialVersionUID = 7854390611657943733L;

      /**
       * Wrap a given set.
       * @param s the set to wrap
       */
      UnmodifiableEntrySet(Set<Map.Entry<K,V>> s)
      {
        super(s);
      }

      // The iterator must return unmodifiable map entries.
      public Iterator<Map.Entry<K,V>> iterator()
      {
        return new UnmodifiableIterator<Map.Entry<K,V>>(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 Map.Entry<K,V> next()
          {
            final Map.Entry<K,V> e = super.next();
            return new UnmodifiableMapEntry<K,V>(e);
          }
        };
      }

      // The array returned is an array of UnmodifiableMapEntry instead of
      // Map.Entry
      public Object[] toArray()
      {
        Object[] mapEntryResult = super.toArray();
        UnmodifiableMapEntry<K,V> result[] = null;

        if (mapEntryResult != null)
          {
            result = (UnmodifiableMapEntry<K,V>[])
              new UnmodifiableMapEntry[mapEntryResult.length];
            for (int i = 0; i < mapEntryResult.length; ++i)
              result[i] = new UnmodifiableMapEntry<K,V>((Map.Entry<K,V>)mapEntryResult[i]);
          }
        return result;
      }

      // The array returned is an array of UnmodifiableMapEntry instead of
      // Map.Entry
      public <S> S[] toArray(S[] array)
      {
        S[] result = super.toArray(array);

        if (result != null)
          for (int i = 0; i < result.length; i++)
            array[i] =
              (S) new UnmodifiableMapEntry<K,V>((Map.Entry<K,V>) result[i]);
        return array;
      }


    } // 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 V 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 V put(K key, V 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<K> keySet()
    {
      if (keys == null)
        keys = new UnmodifiableSet<K>(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<? extends K, ? extends V> 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 V 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<V> values()
    {
      if (values == null)
        values = new UnmodifiableCollection<V>(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 <T> Set<T> unmodifiableSet(Set<? extends T> s)
  {
    return new UnmodifiableSet<T>(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<T> extends UnmodifiableCollection<T>
    implements Set<T>
  {
    /**
     * 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<? extends T> 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 <K, V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K,
                                                             ? extends V> m)
  {
    return new UnmodifiableSortedMap<K, V>(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<K, V>
    extends UnmodifiableMap<K, V>
    implements SortedMap<K, V>
  {
    /**
     * 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<K, V> sm;

    /**
     * Wrap a given map.
     * @param sm the map to wrap
     * @throws NullPointerException if sm is null
     */
    UnmodifiableSortedMap(SortedMap<K, ? extends V> sm)
    {
      super(sm);
      this.sm = (SortedMap<K,V>) 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<? super K> 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 K 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<K, V> headMap(K toKey)
    {
      return new UnmodifiableSortedMap<K, V>(sm.headMap(toKey));
    }

    /**
     * Returns the last (highest sorted) key in the map.
     *
     * @return the last key.
     * @throws NoSuchElementException if this map is empty.
     */
    public K 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<K, V> subMap(K fromKey, K toKey)
    {
      return new UnmodifiableSortedMap<K, V>(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<K, V> tailMap(K fromKey)
    {
      return new UnmodifiableSortedMap<K, V>(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 <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s)
  {
    return new UnmodifiableSortedSet<T>(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<T> extends UnmodifiableSet<T>
    implements SortedSet<T>
  {
    /**
     * 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<T> ss;

    /**
     * Wrap a given set.
     * @param ss the set to wrap
     * @throws NullPointerException if ss is null
     */
    UnmodifiableSortedSet(SortedSet<T> 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<? super T> 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 T 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<T> headSet(T toElement)
    {
      return new UnmodifiableSortedSet<T>(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 T 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<T> subSet(T fromElement, T toElement)
    {
      return new UnmodifiableSortedSet<T>(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<T> tailSet(T fromElement)
    {
      return new UnmodifiableSortedSet<T>(ss.tailSet(fromElement));
    }
  } // class UnmodifiableSortedSet

  /**
   * <p>
   * Returns a dynamically typesafe view of the given collection,
   * where any modification is first checked to ensure that the type
   * of the new data is appropriate.  Although the addition of
   * generics and parametrically-typed collections prevents an
   * incorrect type of element being added to a collection at
   * compile-time, via static type checking, this can be overridden by
   * casting.  In contrast, wrapping the collection within a
   * dynamically-typesafe wrapper, using this and associated methods,
   * <emph>guarantees</emph> that the collection will only contain
   * elements of an appropriate type (provided it only contains such
   * at the type of wrapping, and all subsequent access is via the
   * wrapper).  This can be useful for debugging the cause of a
   * <code>ClassCastException</code> caused by erroneous casting, or
   * for protecting collections from corruption by external libraries.
   * </p>
   * <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.
   * </p>
   *
   * @param c the collection to wrap in a dynamically typesafe wrapper
   * @param type the type of elements the collection should hold.
   * @return a dynamically typesafe view of the collection.
   * @see Serializable
   * @since 1.5
   */
  public static <E> Collection<E> checkedCollection(Collection<E> c,
                                                    Class<E> type)
  {
    return new CheckedCollection<E>(c, type);
  }

  /**
   * The implementation of {@link #checkedCollection(Collection,Class)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.5
   */
  private static class CheckedCollection<E>
    implements Collection<E>, Serializable
  {
    /**
     * Compatible with JDK 1.5.
     */
    private static final long serialVersionUID = 1578914078182001775L;

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

    /**
     * The type of the elements of this collection.
     * @serial the element type.
     */
    final Class<E> type;

    /**
     * Wrap a given collection.
     * @param c the collection to wrap
     * @param type the type to wrap
     * @throws NullPointerException if c is null
     */
    CheckedCollection(Collection<E> c, Class<E> type)
    {
      this.c = c;
      this.type = type;
      if (c == null)
        throw new NullPointerException();
    }

    /**
     * Adds the supplied object to the collection, on the condition that
     * it is of the correct type.
     *
     * @param o the object to add.
     * @return <code>true</code> if the collection was modified as a result
     *                           of this action.
     * @throws ClassCastException if the object is not of the correct type.
     */
    public boolean add(E o)
    {
      if (type.isInstance(o))
        return c.add(o);
      else
        throw new ClassCastException("The element is of the incorrect type.");
    }

    /**
     * Adds the elements of the specified collection to the backing collection,
     * provided they are all of the correct type.
     *
     * @param coll the collection to add.
     * @return <code>true</code> if the collection was modified as a result
     *                           of this action.
     * @throws ClassCastException if <code>c</code> contained elements of an
     *                            incorrect type.
     */
    public boolean addAll(Collection<? extends E> coll)
    {
      Collection<E> typedColl = (Collection<E>) c;
      final Iterator<E> it = typedColl.iterator();
      while (it.hasNext())
        {
          final E element = it.next();
          if (!type.isInstance(element))
            throw new ClassCastException("A member of the collection is not of the correct type.");
        }
      return c.addAll(typedColl);
    }

    /**
     * Removes all elements from the underlying collection.
     */
    public void clear()
    {
      c.clear();
    }

    /**
     * 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 coll 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<?> coll)
    {
      return c.containsAll(coll);
    }

    /**
     * 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 checked nature.
     *
     * @return a Iterator over the elements of the underlying
     *         collection, in any order.
     */
    public Iterator<E> iterator()
    {
      return new CheckedIterator<E>(c.iterator(), type);
    }

    /**
     * Removes the supplied object from the collection, if it exists.
     *
     * @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).
     */
    public boolean remove(Object o)
    {
      return c.remove(o);
    }

    /**
     * Removes all objects in the supplied collection from the backing
     * collection, if they exist within it.
     *
     * @param coll the collection of objects to remove.
     * @return <code>true</code> if the collection was modified.
     */
    public boolean removeAll(Collection<?> coll)
    {
      return c.removeAll(coll);
    }

    /**
     * Retains all objects specified by the supplied collection which exist
     * within the backing collection, and removes all others.
     *
     * @param coll the collection of objects to retain.
     * @return <code>true</code> if the collection was modified.
     */
    public boolean retainAll(Collection<?> coll)
    {
      return c.retainAll(coll);
    }

    /**
     * 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();
    }

    /**
     * <p>
     * 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.
     * </p>
     * <p>
     * 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.
     * </p>
     * <p>
     * <emph>Note</emph>: 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 <S> S[] toArray(S[] a)
    {
      return c.toArray(a);
    }

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

  /**
   * The implementation of the various iterator methods in the
   * checked classes.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.5
   */
  private static class CheckedIterator<E>
    implements Iterator<E>
  {
    /**
     * The wrapped iterator.
     */
    private final Iterator<E> i;

    /**
     * The type of the elements of this collection.
     * @serial the element type.
     */
    final Class<E> type;

    /**
     * Only trusted code creates a wrapper.
     * @param i the wrapped iterator
     * @param type the type of the elements within the checked list.
     */
    CheckedIterator(Iterator<E> i, Class<E> type)
    {
      this.i = i;
      this.type = type;
    }

    /**
     * Obtains the next element in the underlying collection.
     *
     * @return the next element in the collection.
     * @throws NoSuchElementException if there are no more elements.
     */
    public E 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();
    }

    /**
     * Removes the next element from the collection.
     */
    public void remove()
    {
      i.remove();
    }
  } // class CheckedIterator

  /**
   * <p>
   * Returns a dynamically typesafe view of the given list,
   * where any modification is first checked to ensure that the type
   * of the new data is appropriate.  Although the addition of
   * generics and parametrically-typed collections prevents an
   * incorrect type of element being added to a collection at
   * compile-time, via static type checking, this can be overridden by
   * casting.  In contrast, wrapping the collection within a
   * dynamically-typesafe wrapper, using this and associated methods,
   * <emph>guarantees</emph> that the collection will only contain
   * elements of an appropriate type (provided it only contains such
   * at the type of wrapping, and all subsequent access is via the
   * wrapper).  This can be useful for debugging the cause of a
   * <code>ClassCastException</code> caused by erroneous casting, or
   * for protecting collections from corruption by external libraries.
   * </p>
   * <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.
   * </p>
   *
   * @param l the list to wrap
   * @param type the type of the elements within the checked list.
   * @return a dynamically typesafe view of the list
   * @see Serializable
   * @see RandomAccess
   */
  public static <E> List<E> checkedList(List<E> l, Class<E> type)
  {
    if (l instanceof RandomAccess)
      return new CheckedRandomAccessList<E>(l, type);
    return new CheckedList<E>(l, type);
  }

  /**
   * The implementation of {@link #checkedList(List,Class)} for sequential
   * lists. This class name is required for compatibility with Sun's JDK
   * serializability.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.5
   */
  private static class CheckedList<E>
    extends CheckedCollection<E>
    implements List<E>
  {
    /**
     * Compatible with JDK 1.5.
     */
    private static final long serialVersionUID = 65247728283967356L;

    /**
     * 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<E> list;

    /**
     * Wrap a given list.
     * @param l the list to wrap
     * @param type the type of the elements within the checked list.
     * @throws NullPointerException if l is null
     */
    CheckedList(List<E> l, Class<E> type)
    {
      super(l, type);
      list = l;
    }

    /**
     * Adds the supplied element to the underlying list at the specified
     * index, provided it is of the right type.
     *
     * @param index The index at which to place the new element.
     * @param o the object to add.
     * @throws ClassCastException if the type of the object is not a
     *                            valid type for the underlying collection.
     */
    public void add(int index, E o)
    {
      if (type.isInstance(o))
        list.add(index, o);
      else
        throw new ClassCastException("The object is of the wrong type.");
    }

    /**
     * Adds the members of the supplied collection to the underlying
     * collection at the specified index, provided they are all of the
     * correct type.
     *
     * @param index the index at which to place the new element.
     * @param coll the collections of objects to add.
     * @throws ClassCastException if the type of any element in c is not a
     *                            valid type for the underlying collection.
     */
    public boolean addAll(int index, Collection<? extends E> coll)
    {
      Collection<E> typedColl = (Collection<E>) coll;
      final Iterator<E> it = typedColl.iterator();
      while (it.hasNext())
        {
          if (!type.isInstance(it.next()))
            throw new ClassCastException("A member of the collection is not of the correct type.");
        }
      return list.addAll(index, coll);
    }

    /**
     * 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 the specified index in the underlying list
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
     */
    public E 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 checked nature of this list.
     *
     * @return a <code>CheckedListIterator</code> over the elements of the
     *         underlying list, in order, starting at the beginning.
     */
    public ListIterator<E> listIterator()
    {
      return new CheckedListIterator<E>(list.listIterator(), type);
    }

  /**
   * Obtains a list iterator over the underlying list, starting at the
   * specified index and maintaining the checked 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>CheckedListIterator</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<E> listIterator(int index)
    {
      return new CheckedListIterator<E>(list.listIterator(index), type);
    }

    /**
     * Removes the element at the specified index.
     *
     * @param index The index of the element to remove.
     * @return the removed element.
     */
    public E remove(int index)
    {
      return list.remove(index);
    }

    /**
     * Replaces the element at the specified index in the underlying list
     * with that supplied.
     *
     * @param index the index of the element to replace.
     * @param o the new object to place at the specified index.
     * @return the replaced element.
     */
    public E set(int index, E o)
    {
      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 will be
     * checked, like this list.  Changes to the elements of the
     * returned list will be reflected in the underlying list. The effect
     * of structural modifications is undefined.
     *
     * @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<E> subList(int fromIndex, int toIndex)
    {
      return checkedList(list.subList(fromIndex, toIndex), type);
    }
  } // class CheckedList

  /**
   * The implementation of {@link #checkedList(List)} for random-access
   * lists. This class name is required for compatibility with Sun's JDK
   * serializability.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.5
   */
  private static final class CheckedRandomAccessList<E>
    extends CheckedList<E>
    implements RandomAccess
  {
    /**
     * Compatible with JDK 1.5.
     */
    private static final long serialVersionUID = 1638200125423088369L;

    /**
     * Wrap a given list.
     * @param l the list to wrap
     * @param type the type of the elements within the checked list.
     * @throws NullPointerException if l is null
     */
    CheckedRandomAccessList(List<E> l, Class<E> type)
    {
      super(l, type);
    }
  } // class CheckedRandomAccessList

  /**
   * The implementation of {@link CheckedList#listIterator()}.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.5
   */
  private static final class CheckedListIterator<E>
    extends CheckedIterator<E>
    implements ListIterator<E>
  {
    /**
     * The wrapped iterator, stored both here and in the superclass to
     * avoid excessive casting.
     */
    private final ListIterator<E> li;

    /**
     * Only trusted code creates a wrapper.
     * @param li the wrapped iterator
     */
    CheckedListIterator(ListIterator<E> li, Class<E> type)
    {
      super(li, type);
      this.li = li;
    }

    /**
     * Adds the supplied object at the current iterator position, provided
     * it is of the correct type.
     *
     * @param o the object to add.
     * @throws ClassCastException if the type of the object is not a
     *                            valid type for the underlying collection.
     */
    public void add(E o)
    {
      if (type.isInstance(o))
        li.add(o);
      else
        throw new ClassCastException("The object is of the wrong type.");
    }

    /**
     * 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 E 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();
    }

    /**
     * Sets the next element to that supplied, provided that it is of the
     * correct type.
     *
     * @param o The new object to replace the existing one.
     * @throws ClassCastException if the type of the object is not a
     *                            valid type for the underlying collection.
     */
    public void set(E o)
    {
      if (type.isInstance(o))
        li.set(o);
      else
        throw new ClassCastException("The object is of the wrong type.");
    }
  } // class CheckedListIterator

  /**
   * <p>
   * Returns a dynamically typesafe view of the given map,
   * where any modification is first checked to ensure that the type
   * of the new data is appropriate.  Although the addition of
   * generics and parametrically-typed collections prevents an
   * incorrect type of element being added to a collection at
   * compile-time, via static type checking, this can be overridden by
   * casting.  In contrast, wrapping the collection within a
   * dynamically-typesafe wrapper, using this and associated methods,
   * <emph>guarantees</emph> that the collection will only contain
   * elements of an appropriate type (provided it only contains such
   * at the type of wrapping, and all subsequent access is via the
   * wrapper).  This can be useful for debugging the cause of a
   * <code>ClassCastException</code> caused by erroneous casting, or
   * for protecting collections from corruption by external libraries.
   * </p>
   * <p>
   * The returned Map implements Serializable, but can only be serialized if
   * the map it wraps is likewise Serializable.
   * </p>
   *
   * @param m the map to wrap
   * @param keyType the dynamic type of the map's keys.
   * @param valueType the dynamic type of the map's values.
   * @return a dynamically typesafe view of the map
   * @see Serializable
   */
  public static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType,
                                            Class<V> valueType)
  {
    return new CheckedMap<K, V>(m, keyType, valueType);
  }

  /**
   * The implementation of {@link #checkedMap(Map)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.5
   */
  private static class CheckedMap<K, V>
    implements Map<K, V>, Serializable
  {
    /**
     * Compatible with JDK 1.5.
     */
    private static final long serialVersionUID = 5742860141034234728L;

    /**
     * The wrapped map.
     * @serial the real map
     */
    private final Map<K, V> m;

    /**
     * The type of the map's keys.
     * @serial the key type.
     */
    final Class<K> keyType;

    /**
     * The type of the map's values.
     * @serial the value type.
     */
    final Class<V> valueType;

    /**
     * Cache the entry set.
     */
    private transient Set<Map.Entry<K, V>> entries;

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

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

    /**
     * Wrap a given map.
     * @param m the map to wrap
     * @param keyType the dynamic type of the map's keys.
     * @param valueType the dynamic type of the map's values.
     * @throws NullPointerException if m is null
     */
    CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType)
    {
      this.m = m;
      this.keyType = keyType;
      this.valueType = valueType;
      if (m == null)
        throw new NullPointerException();
    }

    /**
     * Clears all pairs from the map.
     */
    public void clear()
    {
      m.clear();
    }

    /**
     * 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);
    }

    /**
     * <p>
     * Returns a checked set view of the entries in the underlying map.
     * Each element in the set is a unmodifiable variant of
     * <code>Map.Entry</code>.
     * </p>
     * <p>
     * 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.
     * </p>
     *
     * @return the checked set view of all mapping entries.
     * @see Map.Entry
     */
    public Set<Map.Entry<K, V>> entrySet()
    {
      if (entries == null)
        {
          Class<Map.Entry<K,V>> klass =
            (Class<Map.Entry<K,V>>) (Class) Map.Entry.class;
          entries = new CheckedEntrySet<Map.Entry<K,V>,K,V>(m.entrySet(),
                                                            klass,
                                                            keyType,
                                                            valueType);
        }
      return entries;
    }

    /**
     * The implementation of {@link CheckedMap#entrySet()}. This class
     * is <emph>not</emph> serializable.
     *
     * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
     * @since 1.5
     */
    private static final class CheckedEntrySet<E,SK,SV>
      extends CheckedSet<E>
    {
      /**
       * The type of the map's keys.
       * @serial the key type.
       */
      private final Class<SK> keyType;

      /**
       * The type of the map's values.
       * @serial the value type.
       */
      private final Class<SV> valueType;

      /**
       * Wrap a given set of map entries.
       *
       * @param s the set to wrap.
       * @param type the type of the set's entries.
       * @param keyType the type of the map's keys.
       * @param valueType the type of the map's values.
       */
      CheckedEntrySet(Set<E> s, Class<E> type, Class<SK> keyType,
                      Class<SV> valueType)
      {
        super(s, type);
        this.keyType = keyType;
        this.valueType = valueType;
      }

      // The iterator must return checked map entries.
      public Iterator<E> iterator()
      {
        return new CheckedIterator<E>(c.iterator(), type)
        {
          /**
           * 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 E next()
          {
            final Map.Entry e = (Map.Entry) super.next();
            return (E) 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();
              }

              /**
               * Sets the value of this map entry, provided it is of the
               * right type.
               *
               * @param value The new value.
               * @throws ClassCastException if the type of the value is not
               *                            a valid type for the underlying
               *                             map.
               */
              public Object setValue(Object value)
              {
                if (valueType.isInstance(value))
                  return e.setValue(value);
                else
                  throw new ClassCastException("The value is of the wrong type.");
              }

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

    /**
     * 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 V get(Object key)
    {
      return m.get(key);
    }

    /**
     * Adds a new pair to the map, provided both the key and the value are
     * of the correct types.
     *
     * @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 ClassCastException if the type of the key or the value is
     *                            not a valid type for the underlying map.
     */
    public V put(K key, V value)
    {
      if (keyType.isInstance(key))
        {
          if (valueType.isInstance(value))
            return m.put(key,value);
          else
            throw new ClassCastException("The value is of the wrong type.");
        }
      throw new ClassCastException("The key is of the wrong type.");
    }

    /**
     * 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();
    }

    /**
     * <p>
     * Returns a checked 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.
     * </p>
     * <p>
     * Modifications made while an iterator is in progress cause undefined
     * behavior.  These modifications are again limited to the values of
     * the keys.
     * </p>
     *
     * @return the set view of all keys.
     */
    public Set<K> keySet()
    {
      if (keys == null)
        keys = new CheckedSet<K>(m.keySet(), keyType);
      return keys;
    }

    /**
     * Adds all pairs within the supplied map to the underlying map,
     * provided they are all have the correct key and value types.
     *
     * @param map the map, the entries of which should be added
     *          to the underlying map.
     * @throws ClassCastException if the type of a key or value is
     *                            not a valid type for the underlying map.
     */
    public void putAll(Map<? extends K, ? extends V> map)
    {
      Map<K,V> typedMap = (Map<K,V>) map;
      final Iterator<Map.Entry<K,V>> it = typedMap.entrySet().iterator();
      while (it.hasNext())
        {
          final Map.Entry<K,V> entry = it.next();
          if (!keyType.isInstance(entry.getKey()))
            throw new ClassCastException("A key is of the wrong type.");
          if (!valueType.isInstance(entry.getValue()))
            throw new ClassCastException("A value is of the wrong type.");
        }
      m.putAll(typedMap);
    }

    /**
     * Removes a pair from the map.
     *
     * @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 V remove(Object o)
    {
      return m.remove(o);
    }


    /**
     * 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();
    }

    /**
     * <p>
     * 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.
     * </p>
     * <p>
     * Modifications made while an iterator is in progress cause undefined
     * behavior.  These modifications are again limited to the values of
     * the keys.
     * </p>
     *
     * @return the collection view of all values.
     */
    public Collection<V> values()
    {
      if (values == null)
        values = new CheckedCollection<V>(m.values(), valueType);
      return values;
    }
  } // class CheckedMap

  /**
   * <p>
   * Returns a dynamically typesafe view of the given set,
   * where any modification is first checked to ensure that the type
   * of the new data is appropriate.  Although the addition of
   * generics and parametrically-typed collections prevents an
   * incorrect type of element being added to a collection at
   * compile-time, via static type checking, this can be overridden by
   * casting.  In contrast, wrapping the collection within a
   * dynamically-typesafe wrapper, using this and associated methods,
   * <emph>guarantees</emph> that the collection will only contain
   * elements of an appropriate type (provided it only contains such
   * at the type of wrapping, and all subsequent access is via the
   * wrapper).  This can be useful for debugging the cause of a
   * <code>ClassCastException</code> caused by erroneous casting, or
   * for protecting collections from corruption by external libraries.
   * </p>
   * <p>
   * The returned Set implements Serializable, but can only be serialized if
   * the set it wraps is likewise Serializable.
   * </p>
   *
   * @param s the set to wrap.
   * @param type the type of the elements within the checked list.
   * @return a dynamically typesafe view of the set
   * @see Serializable
   */
  public static <E> Set<E> checkedSet(Set<E> s, Class<E> type)
  {
    return new CheckedSet<E>(s, type);
  }

  /**
   * The implementation of {@link #checkedSet(Set)}. This class
   * name is required for compatibility with Sun's JDK serializability.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.5
   */
  private static class CheckedSet<E>
    extends CheckedCollection<E>
    implements Set<E>
  {
    /**
     * Compatible with JDK 1.5.
     */
    private static final long serialVersionUID = 4694047833775013803L;

    /**
     * Wrap a given set.
     *
     * @param s the set to wrap
     * @throws NullPointerException if s is null
     */
    CheckedSet(Set<E> s, Class<E> type)
    {
      super(s, type);
    }

    /**
     * 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 CheckedSet

  /**
   * <p>
   * Returns a dynamically typesafe view of the given sorted map,
   * where any modification is first checked to ensure that the type
   * of the new data is appropriate.  Although the addition of
   * generics and parametrically-typed collections prevents an
   * incorrect type of element being added to a collection at
   * compile-time, via static type checking, this can be overridden by
   * casting.  In contrast, wrapping the collection within a
   * dynamically-typesafe wrapper, using this and associated methods,
   * <emph>guarantees</emph> that the collection will only contain
   * elements of an appropriate type (provided it only contains such
   * at the type of wrapping, and all subsequent access is via the
   * wrapper).  This can be useful for debugging the cause of a
   * <code>ClassCastException</code> caused by erroneous casting, or
   * for protecting collections from corruption by external libraries.
   * </p>
   * <p>
   * The returned SortedMap implements Serializable, but can only be
   * serialized if the map it wraps is likewise Serializable.
   * </p>
   *
   * @param m the map to wrap.
   * @param keyType the dynamic type of the map's keys.
   * @param valueType the dynamic type of the map's values.
   * @return a dynamically typesafe view of the map
   * @see Serializable
   */
  public static <K, V> SortedMap<K, V> checkedSortedMap(SortedMap<K, V> m,
                                                        Class<K> keyType,
                                                        Class<V> valueType)
  {
    return new CheckedSortedMap<K, V>(m, keyType, valueType);
  }

  /**
   * The implementation of {@link #checkedSortedMap(SortedMap,Class,Class)}.
   * This class name is required for compatibility with Sun's JDK
   * serializability.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   */
  private static class CheckedSortedMap<K, V>
    extends CheckedMap<K, V>
    implements SortedMap<K, V>
  {
    /**
     * Compatible with JDK 1.5.
     */
    private static final long serialVersionUID = 1599671320688067438L;

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

    /**
     * Wrap a given map.
     *
     * @param sm the map to wrap
     * @param keyType the dynamic type of the map's keys.
     * @param valueType the dynamic type of the map's values.
     * @throws NullPointerException if sm is null
     */
    CheckedSortedMap(SortedMap<K, V> sm, Class<K> keyType, Class<V> valueType)
    {
      super(sm, keyType, valueType);
      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<? super K> 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 K firstKey()
    {
      return sm.firstKey();
    }

    /**
     * <p>
     * Returns a checked 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>
     * <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>.
     * </p>
     *
     * @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<K, V> headMap(K toKey)
    {
      return new CheckedSortedMap<K, V>(sm.headMap(toKey), keyType, valueType);
    }

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

    /**
     * <p>
     * Returns a checked 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>
     * <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.
     * </p>
     *
     * @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<K, V> subMap(K fromKey, K toKey)
    {
      return new CheckedSortedMap<K, V>(sm.subMap(fromKey, toKey), keyType,
                                        valueType);
    }

    /**
     * <p>
     * Returns a checked 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>
     * <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>.
     * </p>
     *
     * @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<K, V> tailMap(K fromKey)
    {
      return new CheckedSortedMap<K, V>(sm.tailMap(fromKey), keyType,
                                        valueType);
    }
  } // class CheckedSortedMap

  /**
   * <p>
   * Returns a dynamically typesafe view of the given sorted set,
   * where any modification is first checked to ensure that the type
   * of the new data is appropriate.  Although the addition of
   * generics and parametrically-typed collections prevents an
   * incorrect type of element being added to a collection at
   * compile-time, via static type checking, this can be overridden by
   * casting.  In contrast, wrapping the collection within a
   * dynamically-typesafe wrapper, using this and associated methods,
   * <emph>guarantees</emph> that the collection will only contain
   * elements of an appropriate type (provided it only contains such
   * at the type of wrapping, and all subsequent access is via the
   * wrapper).  This can be useful for debugging the cause of a
   * <code>ClassCastException</code> caused by erroneous casting, or
   * for protecting collections from corruption by external libraries.
   * </p>
   * <p>
   * The returned SortedSet implements Serializable, but can only be
   * serialized if the set it wraps is likewise Serializable.
   * </p>
   *
   * @param s the set to wrap.
   * @param type the type of the set's elements.
   * @return a dynamically typesafe view of the set
   * @see Serializable
   */
  public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,
                                                  Class<E> type)
  {
    return new CheckedSortedSet<E>(s, type);
  }

  /**
   * The implementation of {@link #checkedSortedSet(SortedSet,Class)}. This
   * class name is required for compatibility with Sun's JDK serializability.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.5
   */
  private static class CheckedSortedSet<E>
    extends CheckedSet<E>
    implements SortedSet<E>
  {
    /**
     * Compatible with JDK 1.4.
     */
    private static final long serialVersionUID = 1599911165492914959L;

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

    /**
     * Wrap a given set.
     *
     * @param ss the set to wrap.
     * @param type the type of the set's elements.
     * @throws NullPointerException if ss is null
     */
    CheckedSortedSet(SortedSet<E> ss, Class<E> type)
    {
      super(ss, type);
      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<? super E> 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 E first()
    {
      return ss.first();
    }

    /**
     * <p>
     * Returns a checked 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>
     * <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>.
     * </p>
     *
     * @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<E> headSet(E toElement)
    {
      return new CheckedSortedSet<E>(ss.headSet(toElement), type);
    }

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

    /**
     * <p>
     * Returns a checked 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>
     * <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.
     * </p>
     *
     * @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<E> subSet(E fromElement, E toElement)
    {
      return new CheckedSortedSet<E>(ss.subSet(fromElement, toElement), type);
    }

    /**
     * <p>
     * Returns a checked 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>
     * <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>.
     * </p>
     *
     * @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<E> tailSet(E fromElement)
    {
      return new CheckedSortedSet<E>(ss.tailSet(fromElement), type);
    }
  } // class CheckedSortedSet

  /**
   * Returns a view of a {@link Deque} as a stack or LIFO (Last-In-First-Out)
   * {@link Queue}.  Each call to the LIFO queue corresponds to one
   * equivalent method call to the underlying deque, with the exception
   * of {@link Collection#addAll(Collection)}, which is emulated by a series
   * of {@link Deque#push(E)} calls.
   *
   * @param deque the deque to convert to a LIFO queue.
   * @return a LIFO queue.
   * @since 1.6
   */
  public static <T> Queue<T> asLifoQueue(Deque<T> deque)
  {
    return new LIFOQueue<T>(deque);
  }

  /**
   * Returns a set backed by the supplied map.  The resulting set
   * has the same performance, concurrency and ordering characteristics
   * as the original map.  The supplied map must be empty and should not
   * be used after the set is created.  Each call to the set corresponds
   * to one equivalent method call to the underlying map, with the exception
   * of {@link Set#addAll(Collection)} which is emulated by a series of
   * calls to <code>put</code>.
   *
   * @param map the map to convert to a set.
   * @return a set backed by the supplied map.
   * @throws IllegalArgumentException if the map is not empty.
   * @since 1.6
   */
  public static <E> Set<E> newSetFromMap(Map<E,Boolean> map)
  {
    return new MapSet<E>(map);
  }

  /**
   * The implementation of {@link #asLIFOQueue(Deque)}.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.6
   */
  private static class LIFOQueue<T>
    extends AbstractQueue<T>
  {

    /**
     * The backing deque.
     */
    private Deque<T> deque;

    /**
     * Constructs a new {@link LIFOQueue} with the specified
     * backing {@link Deque}.
     *
     * @param deque the backing deque.
     */
    public LIFOQueue(Deque<T> deque)
    {
      this.deque = deque;
    }

    public boolean add(T e)
    {
      return deque.offerFirst(e);
    }

    public boolean addAll(Collection<? extends T> c)
    {
      boolean result = false;
      final Iterator<? extends T> it = c.iterator();
      while (it.hasNext())
        result |= deque.offerFirst(it.next());
      return result;
    }

    public void clear()
    {
      deque.clear();
    }

    public boolean isEmpty()
    {
      return deque.isEmpty();
    }

    public Iterator<T> iterator()
    {
      return deque.iterator();
    }

    public boolean offer(T e)
    {
      return deque.offerFirst(e);
    }

    public T peek()
    {
      return deque.peek();
    }

    public T poll()
    {
      return deque.poll();
    }

    public int size()
    {
      return deque.size();
    }
  } // class LIFOQueue

  /**
   * The implementation of {@link #newSetFromMap(Map)}.
   *
   * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
   * @since 1.6
   */
  private static class MapSet<E>
    extends AbstractSet<E>
  {

    /**
     * The backing map.
     */
    private Map<E,Boolean> map;

    /**
     * Constructs a new {@link MapSet} using the specified
     * backing {@link Map}.
     *
     * @param map the backing map.
     * @throws IllegalArgumentException if the map is not empty.
     */
    public MapSet(Map<E,Boolean> map)
    {
      if (!map.isEmpty())
        throw new IllegalArgumentException("The map must be empty.");
      this.map = map;
    }

    public boolean add(E e)
    {
      return map.put(e, true) == null;
    }

    public boolean addAll(Collection<? extends E> c)
    {
      boolean result = false;
      final Iterator<? extends E> it = c.iterator();
      while (it.hasNext())
        result |= (map.put(it.next(), true) == null);
      return result;
    }

    public void clear()
    {
      map.clear();
    }

    public boolean contains(Object o)
    {
      return map.containsKey(o);
    }

    public boolean isEmpty()
    {
      return map.isEmpty();
    }

    public Iterator<E> iterator()
    {
      return map.keySet().iterator();
    }

    public boolean remove(Object o)
    {
      return map.remove(o) != null;
    }

    public int size()
    {
      return map.size();
    }
  } // class MapSet

} // class Collections
