mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1855 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1855 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* Collections.java -- Utility class with methods to operate on collections
 | |
|    Copyright (C) 1998, 1999, 2000 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., 59 Temple Place, Suite 330, Boston, MA
 | |
| 02111-1307 USA.
 | |
| 
 | |
| As a special exception, if you link this library with other files to
 | |
| produce an executable, this library does not by itself cause the
 | |
| resulting executable to be covered by the GNU General Public License.
 | |
| This exception does not however invalidate any other reasons why the
 | |
| executable file might be covered by the GNU General Public License. */
 | |
| 
 | |
| 
 | |
| // TO DO:
 | |
| // ~ Serialization is very much broken. Blame Sun for not specifying it.
 | |
| // ~ The synchronized* and unmodifiable* methods don't have doc-comments.
 | |
| 
 | |
| package java.util;
 | |
| 
 | |
| import java.io.Serializable;
 | |
| 
 | |
| /**
 | |
|  * Utility class consisting of static methods that operate on, or return
 | |
|  * Collections. Contains methods to sort, search, reverse, fill and shuffle
 | |
|  * Collections, methods to facilitate interoperability with legacy APIs that
 | |
|  * are unaware of collections, a method to return a list which consists of
 | |
|  * multiple copies of one element, and methods which "wrap" collections to give
 | |
|  * them extra properties, such as thread-safety and unmodifiability.
 | |
|  */
 | |
| public class Collections
 | |
| {
 | |
|   /**
 | |
|    * This class is non-instantiable.
 | |
|    */
 | |
|   private Collections()
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * An immutable, empty Set.
 | |
|    * Note: This implementation isn't Serializable, although it should be by the
 | |
|    * spec.
 | |
|    */
 | |
|   public static final Set EMPTY_SET = new AbstractSet()
 | |
|   {
 | |
|     public int size()
 | |
|     {
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     // This is really cheating! I think it's perfectly valid, though - the
 | |
|     // more conventional code is here, commented out, in case anyone disagrees.
 | |
|     public Iterator iterator()
 | |
|     {
 | |
|       return EMPTY_LIST.iterator();
 | |
|     }
 | |
| 
 | |
|     // public Iterator iterator() {
 | |
|     //   return new Iterator() {
 | |
|     // 
 | |
|     //     public boolean hasNext() {
 | |
|     //       return false;
 | |
|     //     }
 | |
|     // 
 | |
|     //     public Object next() {
 | |
|     //       throw new NoSuchElementException();
 | |
|     //     }
 | |
|     // 
 | |
|     //     public void remove() {
 | |
|     //       throw new UnsupportedOperationException();
 | |
|     //     }
 | |
|     //   };
 | |
|     // }
 | |
| 
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * An immutable, empty List.
 | |
|    * Note: This implementation isn't serializable, although it should be by the
 | |
|    * spec.
 | |
|    */
 | |
|   public static final List EMPTY_LIST = new AbstractList()
 | |
|   {
 | |
|     public int size()
 | |
|     {
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     public Object get(int index)
 | |
|     {
 | |
|       throw new IndexOutOfBoundsException();
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * An immutable, empty Map.
 | |
|    * Note: This implementation isn't serializable, although it should be by the
 | |
|    * spec.
 | |
|    */
 | |
|   public static final Map EMPTY_MAP = new AbstractMap()
 | |
|   {
 | |
|     public Set entrySet()
 | |
|     {
 | |
|       return EMPTY_SET;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * 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 same code is used in Arrays (for sort as well as search)
 | |
|    */
 | |
|   private static int compare(Object o1, Object o2, Comparator c)
 | |
|   {
 | |
|     if (c == null)
 | |
|       {
 | |
| 	return ((Comparable) o1).compareTo(o2);
 | |
|       }
 | |
|     else
 | |
|       {
 | |
| 	return c.compare(o1, o2);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * The hard work for the search routines. If the Comparator given is null,
 | |
|    * uses the natural ordering of the elements.
 | |
|    */
 | |
|   private static int search(List l, Object key, final Comparator c)
 | |
|   {
 | |
|     int pos = 0;
 | |
| 
 | |
|     // We use a linear search using an iterator if we can guess that the list
 | |
|     // is sequential-access.
 | |
|     if (l instanceof AbstractSequentialList)
 | |
|       {
 | |
| 	ListIterator itr = l.listIterator();
 | |
|     	for (int i = l.size() - 1; i >= 0; --i)
 | |
| 	  {
 | |
| 	    final int d = compare(key, itr.next(), c);
 | |
| 	    if (d == 0)
 | |
| 	      {
 | |
| 		return pos;
 | |
| 	      }
 | |
| 	    else if (d < 0)
 | |
| 	      {
 | |
| 		return -pos - 1;
 | |
| 	      }
 | |
| 	    pos++;
 | |
| 	  }
 | |
| 
 | |
| 	// We assume the list is random-access, and use a binary search
 | |
|       }
 | |
|     else
 | |
|       {
 | |
| 	int low = 0;
 | |
| 	int hi = l.size() - 1;
 | |
| 	while (low <= hi)
 | |
| 	  {
 | |
| 	    pos = (low + hi) >> 1;
 | |
| 	    final int d = compare(key, l.get(pos), c);
 | |
| 	    if (d == 0)
 | |
| 	      {
 | |
| 		return pos;
 | |
| 	      }
 | |
| 	    else if (d < 0)
 | |
| 	      {
 | |
| 		hi = pos - 1;
 | |
| 	      }
 | |
| 	    else
 | |
| 	      {
 | |
| 		low = ++pos;	// This gets the insertion point right on the last loop
 | |
| 	      }
 | |
| 	  }
 | |
|       }
 | |
| 
 | |
|     // If we failed to find it, we do the same whichever search we did.
 | |
|     return -pos - 1;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * 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 behaviour 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. To
 | |
|    * avoid pathological behaviour on sequential-access lists, a linear search
 | |
|    * is used if (l instanceof AbstractSequentialList). 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
 | |
|    * @returns 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.
 | |
|    * @exception ClassCastException if key could not be compared with one of the
 | |
|    *   elements of l
 | |
|    * @exception NullPointerException if a null element has compareTo called
 | |
|    */
 | |
|   public static int binarySearch(List l, Object key)
 | |
|   {
 | |
|     return search(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 behaviour 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. To avoid pathological behaviour on sequential-access lists, a
 | |
|    * linear search is used if (l instanceof AbstractSequentialList). 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
 | |
|    * @returns 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.
 | |
|    * @exception ClassCastException if key could not be compared with one of the
 | |
|    *   elements of l
 | |
|    */
 | |
|   public static int binarySearch(List l, Object key, Comparator c)
 | |
|   {
 | |
|     if (c == null)
 | |
|       {
 | |
| 	throw new NullPointerException();
 | |
|       }
 | |
|     return search(l, key, c);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * 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.
 | |
|    * @exception IndexOutOfBoundsException if the destination list is shorter
 | |
|    *   than the source list (the elements that can be copied will be, prior to
 | |
|    *   the exception being thrown).
 | |
|    * @exception UnsupportedOperationException if dest.listIterator() does not
 | |
|    *   support the set operation.
 | |
|    */
 | |
|   public static void copy(List dest, List source)
 | |
|   {
 | |
|     Iterator i1 = source.iterator();
 | |
|     ListIterator i2 = dest.listIterator();
 | |
| 
 | |
|     try
 | |
|       {
 | |
| 	for (int i = source.size() - 1; i >= 0; --i)
 | |
| 	  {
 | |
| 	    i2.next();
 | |
| 	    i2.set(i1.next());
 | |
| 	  }
 | |
|       }
 | |
|     catch (NoSuchElementException x)
 | |
|       {
 | |
| 	throw new IndexOutOfBoundsException("Source doesn't fit in dest.");      
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * 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
 | |
|    * @returns an Enumeration backed by an Iterator over c
 | |
|    */
 | |
|   public static Enumeration enumeration(Collection c)
 | |
|   {
 | |
|     final Iterator i = c.iterator();
 | |
|     return new Enumeration()
 | |
|     {
 | |
|       public final boolean hasMoreElements()
 | |
|       {
 | |
| 	return i.hasNext();
 | |
|       }
 | |
|       public final Object nextElement()
 | |
|       {
 | |
| 	return i.next();
 | |
|       }
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Replace every element of a list with a given value. This method runs in
 | |
|    * linear time.
 | |
|    *
 | |
|    * @param l the list to fill.
 | |
|    * @param val the object to vill the list with.
 | |
|    * @exception UnsupportedOperationException if l.listIterator() does not
 | |
|    *   support the set operation.
 | |
|    */
 | |
|   public static void fill(List l, Object val)
 | |
|   {
 | |
|     ListIterator itr = l.listIterator();
 | |
|     for (int i = l.size() - 1; i >= 0; --i)
 | |
|       {
 | |
| 	itr.next();
 | |
| 	itr.set(val);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * 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
 | |
|    * @returns the maximum element of c
 | |
|    * @exception NoSuchElementException if c is empty
 | |
|    * @exception ClassCastException if elements in c are not mutually comparable
 | |
|    * @exception NullPointerException if null.compareTo is called
 | |
|    */
 | |
|   public static Object max(Collection c)
 | |
|   {
 | |
|     Iterator itr = c.iterator();
 | |
|     Comparable max = (Comparable) itr.next();	// throws NoSuchElementException
 | |
|     int csize = c.size();
 | |
|     for (int i = 1; i < csize; i++)
 | |
|       {
 | |
| 	Object o = itr.next();
 | |
| 	if (max.compareTo(o) < 0)
 | |
| 	  {
 | |
| 	    max = (Comparable) o;
 | |
| 	  }
 | |
|       }
 | |
|     return max;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * 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
 | |
|    * @returns the maximum element of c
 | |
|    * @exception NoSuchElementException if c is empty
 | |
|    * @exception ClassCastException if elements in c are not mutually comparable
 | |
|    */
 | |
|   public static Object max(Collection c, Comparator order)
 | |
|   {
 | |
|     Iterator itr = c.iterator();
 | |
|     Object max = itr.next();	// throws NoSuchElementException
 | |
|     int csize = c.size();
 | |
|     for (int i = 1; i < csize; i++)
 | |
|       {
 | |
| 	Object o = itr.next();
 | |
| 	if (order.compare(max, o) < 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
 | |
|    * @returns the minimum element of c
 | |
|    * @exception NoSuchElementException if c is empty
 | |
|    * @exception ClassCastException if elements in c are not mutually comparable
 | |
|    * @exception NullPointerException if null.compareTo is called
 | |
|    */
 | |
|   public static Object min(Collection c)
 | |
|   {
 | |
|     Iterator itr = c.iterator();
 | |
|     Comparable min = (Comparable) itr.next();	// throws NoSuchElementException
 | |
|     int csize = c.size();
 | |
|     for (int i = 1; i < csize; i++)
 | |
|       {
 | |
| 	Object o = itr.next();
 | |
| 	if (min.compareTo(o) > 0)
 | |
| 	  min = (Comparable) o;
 | |
|       }
 | |
|     return min;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * 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
 | |
|    * @returns the minimum element of c
 | |
|    * @exception NoSuchElementException if c is empty
 | |
|    * @exception ClassCastException if elements in c are not mutually comparable
 | |
|    */
 | |
|   public static Object min(Collection c, Comparator order)
 | |
|   {
 | |
|     Iterator itr = c.iterator();
 | |
|     Object min = itr.next();	// throws NoSuchElementExcception
 | |
|     int csize = c.size();
 | |
|     for (int i = 1; i < csize; i++)
 | |
|       {
 | |
| 	Object o = itr.next();
 | |
| 	if (order.compare(min, o) > 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.
 | |
|    *
 | |
|    * @param n the number of times to repeat the object
 | |
|    * @param o the object to repeat
 | |
|    * @returns a List consisting of n copies of o
 | |
|    * @throws IllegalArgumentException if n < 0
 | |
|    */
 | |
|   // It's not Serializable, because the serialized form is unspecced.
 | |
|   // Also I'm only assuming that it should be because I don't think it's
 | |
|   // stated - I just would be amazed if it isn't...
 | |
|   public static List nCopies(final int n, final Object o)
 | |
|   {
 | |
|     // Check for insane arguments
 | |
|     if (n < 0)
 | |
|       {
 | |
| 	throw new IllegalArgumentException();
 | |
|       }
 | |
| 
 | |
|     // Create a minimal implementation of List
 | |
|     return new AbstractList()
 | |
|     {
 | |
|       public int size()
 | |
|       {
 | |
| 	return n;
 | |
|       }
 | |
| 
 | |
|       public Object get(int index)
 | |
|       {
 | |
| 	if (index < 0 || index >= n)
 | |
| 	  {
 | |
| 	    throw new IndexOutOfBoundsException();
 | |
| 	  }
 | |
| 	return o;
 | |
|       }
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Reverse a given list. This method works in linear time.
 | |
|    *
 | |
|    * @param l the list to reverse.
 | |
|    * @exception UnsupportedOperationException if l.listIterator() does not
 | |
|    *   support the set operation.
 | |
|    */
 | |
|   public static void reverse(List l)
 | |
|   {
 | |
|     ListIterator i1 = l.listIterator();
 | |
|     int pos1 = 0;
 | |
|     int pos2 = l.size();
 | |
|     ListIterator i2 = l.listIterator(pos2);
 | |
|     while (pos1 < pos2)
 | |
|       {
 | |
| 	Object o = i1.next();
 | |
| 	i1.set(i2.previous());
 | |
| 	i2.set(o);
 | |
| 	++pos1;
 | |
| 	--pos2;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   static class ReverseComparator implements Comparator, Serializable
 | |
|   {
 | |
|     public int compare(Object a, Object b)
 | |
|     {
 | |
|       return -((Comparable) a).compareTo(b);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   static ReverseComparator rcInstance = new ReverseComparator();
 | |
|   
 | |
|   /**
 | |
|    * Get a comparator that implements the reverse of natural ordering. This is
 | |
|    * intended to make it easy to sort into reverse order, by simply passing
 | |
|    * Collections.reverseOrder() to the sort method. The return value of this
 | |
|    * method is Serializable.
 | |
|    */
 | |
|   public static Comparator reverseOrder()
 | |
|   {
 | |
|     return rcInstance;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Shuffle a list according to a default source of randomness. The algorithm
 | |
|    * used would result in a perfectly fair shuffle (that is, each element would
 | |
|    * have an equal chance of ending up in any position) with a perfect source
 | |
|    * of randomness; in practice the results are merely very close to perfect.
 | |
|    * <p>
 | |
|    * This method operates in linear time on a random-access list, but may take
 | |
|    * quadratic time on a sequential-access list.
 | |
|    * Note: this (classpath) implementation will never take quadratic time, but
 | |
|    * it does make a copy of the list. This is in line with the behaviour of the
 | |
|    * sort methods and seems preferable.
 | |
|    *
 | |
|    * @param l the list to shuffle.
 | |
|    * @exception 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 occuring: 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 on a random-access list, but may take
 | |
|    * quadratic time on a sequential-access list.
 | |
|    * Note: this (classpath) implementation will never take quadratic time, but
 | |
|    * it does make a copy of the list. This is in line with the behaviour of the
 | |
|    * sort methods and seems preferable.
 | |
|    *
 | |
|    * @param l the list to shuffle.
 | |
|    * @param r the source of randomness to use for the shuffle.
 | |
|    * @exception UnsupportedOperationException if l.listIterator() does not
 | |
|    *   support the set operation.
 | |
|    */
 | |
|   public static void shuffle(List l, Random r)
 | |
|   {
 | |
|     Object[] a = l.toArray();	// Dump l into an array
 | |
|     int lsize = l.size();
 | |
|     ListIterator i = l.listIterator(lsize);
 | |
| 
 | |
|     // Iterate backwards over l
 | |
|     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 swapth element of the array with the next element of the
 | |
| 	// list.
 | |
| 	Object o = a[swap];
 | |
| 	a[swap] = a[pos];
 | |
| 	a[pos] = o;
 | |
| 
 | |
| 	// Set the element in the original list accordingly.
 | |
| 	i.previous();
 | |
| 	i.set(o);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Obtain an immutable Set consisting of a single element. The return value
 | |
|    * of this method is Serializable.
 | |
|    *
 | |
|    * @param o the single element.
 | |
|    * @returns an immutable Set containing only o.
 | |
|    */
 | |
|   // It's not serializable because the spec is broken.
 | |
|   public static Set singleton(final Object o)
 | |
|   {
 | |
|     return new AbstractSet()
 | |
|     {
 | |
|       public int size()
 | |
|       {
 | |
| 	return 1;
 | |
|       }
 | |
| 
 | |
|       public Iterator iterator()
 | |
|       {
 | |
| 	return new Iterator()
 | |
| 	{
 | |
| 	  private boolean hasNext = true;
 | |
| 
 | |
| 	  public boolean hasNext()
 | |
| 	  {
 | |
| 	    return hasNext;
 | |
| 	  }
 | |
| 
 | |
| 	  public Object next()
 | |
| 	  {
 | |
| 	    if (hasNext)
 | |
| 	      {
 | |
| 		hasNext = false;
 | |
| 		return o;
 | |
| 	      }
 | |
| 	    else
 | |
| 	      {
 | |
| 		throw new NoSuchElementException();
 | |
| 	      }
 | |
| 	  }
 | |
| 
 | |
| 	  public void remove()
 | |
| 	  {
 | |
| 	    throw new UnsupportedOperationException();
 | |
| 	  }
 | |
| 	};
 | |
|       }
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Obtain an immutable List consisting of a single element. The return value
 | |
|    * of this method is Serializable.
 | |
|    *
 | |
|    * @param o the single element.
 | |
|    * @returns an immutable List containing only o.
 | |
|    */
 | |
|   // It's not serializable because the spec is broken.
 | |
|   public static List singletonList(final Object o)
 | |
|   {
 | |
|     return new AbstractList()
 | |
|     {
 | |
|       public int size()
 | |
|       {
 | |
| 	return 1;
 | |
|       }
 | |
| 
 | |
|       public Object get(int index)
 | |
|       {
 | |
| 	if (index == 0)
 | |
| 	  {
 | |
| 	    throw new IndexOutOfBoundsException();
 | |
| 	  }
 | |
| 	else
 | |
| 	  {
 | |
| 	    return o;
 | |
| 	  }
 | |
|       }
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * 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.
 | |
|    * @returns an immutable Map containing only the single key value pair.
 | |
|    */
 | |
|   // It's not serializable because the spec is broken.
 | |
|   public static Map singletonMap(final Object key, final Object value)
 | |
|   {
 | |
|     return new AbstractMap()
 | |
|     {
 | |
|       public Set entrySet()
 | |
|       {
 | |
| 	return singleton(new HashMap.Entry(key, value));
 | |
|       }
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * 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
 | |
|    * @exception ClassCastException if some items are not mutually comparable
 | |
|    * @exception UnsupportedOperationException if the List is not modifiable
 | |
|    */
 | |
|   public static void sort(List l)
 | |
|   {
 | |
|     Object[] a = l.toArray();
 | |
|     Arrays.sort(a);
 | |
|     ListIterator i = l.listIterator();
 | |
|     for (int pos = 0; pos < a.length; pos++)
 | |
|       {
 | |
| 	i.next();
 | |
| 	i.set(a[pos]);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sort a list according to a specified Comparator. The list must be
 | |
|    * modifiable, but can be of fixed size. The sort algorithm is precisely that
 | |
|    * used by Arrays.sort(Object[], Comparator), which offers guaranteed
 | |
|    * nlog(n) performance. This implementation dumps the list into an array,
 | |
|    * sorts the array, and then iterates over the list setting each element from
 | |
|    * the array.
 | |
|    *
 | |
|    * @param l the List to sort
 | |
|    * @param c the Comparator specifying the ordering for the elements
 | |
|    * @exception ClassCastException if c will not compare some pair of items
 | |
|    * @exception UnsupportedOperationException if the List is not modifiable
 | |
|    */
 | |
|   public static void sort(List l, Comparator c)
 | |
|   {
 | |
|     Object[] a = l.toArray();
 | |
|     Arrays.sort(a, c);
 | |
|     ListIterator i = l.listIterator();
 | |
|     for (int pos = 0; pos < a.length; pos++)
 | |
|       {
 | |
| 	i.next();
 | |
| 	i.set(a[pos]);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   // All the methods from here on in require doc-comments.
 | |
| 
 | |
|   public static Collection synchronizedCollection(Collection c)
 | |
|   {
 | |
|     return new SynchronizedCollection(c);
 | |
|   }
 | |
|   public static List synchronizedList(List l)
 | |
|   {
 | |
|     return new SynchronizedList(l);
 | |
|   }
 | |
|   public static Map synchronizedMap(Map m)
 | |
|   {
 | |
|     return new SynchronizedMap(m);
 | |
|   }
 | |
|   public static Set synchronizedSet(Set s)
 | |
|   {
 | |
|     return new SynchronizedSet(s);
 | |
|   }
 | |
|   public static SortedMap synchronizedSortedMap(SortedMap m)
 | |
|   {
 | |
|     return new SynchronizedSortedMap(m);
 | |
|   }
 | |
|   public static SortedSet synchronizedSortedSet(SortedSet s)
 | |
|   {
 | |
|     return new SynchronizedSortedSet(s);
 | |
|   }
 | |
|   public static Collection unmodifiableCollection(Collection c)
 | |
|   {
 | |
|     return new UnmodifiableCollection(c);
 | |
|   }
 | |
|   public static List unmodifiableList(List l)
 | |
|   {
 | |
|     return new UnmodifiableList(l);
 | |
|   }
 | |
|   public static Map unmodifiableMap(Map m)
 | |
|   {
 | |
|     return new UnmodifiableMap(m);
 | |
|   }
 | |
|   public static Set unmodifiableSet(Set s)
 | |
|   {
 | |
|     return new UnmodifiableSet(s);
 | |
|   }
 | |
|   public static SortedMap unmodifiableSortedMap(SortedMap m)
 | |
|   {
 | |
|     return new UnmodifiableSortedMap(m);
 | |
|   }
 | |
|   public static SortedSet unmodifiableSortedSet(SortedSet s)
 | |
|   {
 | |
|     return new UnmodifiableSortedSet(s);
 | |
|   }
 | |
| 
 | |
|   // Sun's spec will need to be checked for the precise names of these
 | |
|   // classes, for serializability's sake. However, from what I understand,
 | |
|   // serialization is broken for these classes anyway.
 | |
| 
 | |
|   // Note: although this code is largely uncommented, it is all very
 | |
|   // mechanical and there's nothing really worth commenting.
 | |
|   // When serialization of these classes works, we'll need doc-comments on
 | |
|   // them to document the serialized form.
 | |
| 
 | |
|   private static class UnmodifiableIterator implements Iterator
 | |
|   {
 | |
|     private Iterator i;
 | |
| 
 | |
|     public UnmodifiableIterator(Iterator i)
 | |
|     {
 | |
|       this.i = i;
 | |
|     }
 | |
| 
 | |
|     public Object next()
 | |
|     {
 | |
|       return i.next();
 | |
|     }
 | |
|     public boolean hasNext()
 | |
|     {
 | |
|       return i.hasNext();
 | |
|     }
 | |
|     public void remove()
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class UnmodifiableListIterator extends UnmodifiableIterator
 | |
|     implements ListIterator
 | |
|   {
 | |
|     // This is stored both here and in the superclass, to avoid excessive
 | |
|     // casting.
 | |
|     private ListIterator li;
 | |
| 
 | |
|     public UnmodifiableListIterator(ListIterator li)
 | |
|     {
 | |
|       super(li);
 | |
|       this.li = li;
 | |
|     }
 | |
| 
 | |
|     public boolean hasPrevious()
 | |
|     {
 | |
|       return li.hasPrevious();
 | |
|     }
 | |
|     public Object previous()
 | |
|     {
 | |
|       return li.previous();
 | |
|     }
 | |
|     public int nextIndex()
 | |
|     {
 | |
|       return li.nextIndex();
 | |
|     }
 | |
|     public int previousIndex()
 | |
|     {
 | |
|       return li.previousIndex();
 | |
|     }
 | |
|     public void add(Object o)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public void set(Object o)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class UnmodifiableCollection implements Collection,
 | |
|     Serializable
 | |
|   {
 | |
|     Collection c;
 | |
| 
 | |
|     public UnmodifiableCollection(Collection c)
 | |
|     {
 | |
|       this.c = c;
 | |
|     }
 | |
| 
 | |
|     public boolean add(Object o)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public boolean addAll(Collection c)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public void clear()
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public boolean contains(Object o)
 | |
|     {
 | |
|       return c.contains(o);
 | |
|     }
 | |
|     public boolean containsAll(Collection c1)
 | |
|     {
 | |
|       return c.containsAll(c1);
 | |
|     }
 | |
|     public boolean isEmpty()
 | |
|     {
 | |
|       return c.isEmpty();
 | |
|     }
 | |
|     public Iterator iterator()
 | |
|     {
 | |
|       return new UnmodifiableIterator(c.iterator());
 | |
|     }
 | |
|     public boolean remove(Object o)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public boolean removeAll(Collection c)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public boolean retainAll(Collection c)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public int size()
 | |
|     {
 | |
|       return c.size();
 | |
|     }
 | |
|     public Object[] toArray()
 | |
|     {
 | |
|       return c.toArray();
 | |
|     }
 | |
|     public Object[] toArray(Object[]a)
 | |
|     {
 | |
|       return c.toArray(a);
 | |
|     }
 | |
|     public String toString()
 | |
|     {
 | |
|       return c.toString();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class UnmodifiableList extends UnmodifiableCollection
 | |
|     implements List
 | |
|   {
 | |
|     // This is stored both here and in the superclass, to avoid excessive
 | |
|     // casting.
 | |
|     List l;
 | |
| 
 | |
|     public UnmodifiableList(List l)
 | |
|     {
 | |
|       super(l);
 | |
|       this.l = l;
 | |
|     }
 | |
| 
 | |
|     public void add(int index, Object o)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public boolean addAll(int index, Collection c)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public boolean equals(Object o)
 | |
|     {
 | |
|       return l.equals(o);
 | |
|     }
 | |
|     public Object get(int index)
 | |
|     {
 | |
|       return l.get(index);
 | |
|     }
 | |
|     public int hashCode()
 | |
|     {
 | |
|       return l.hashCode();
 | |
|     }
 | |
|     public int indexOf(Object o)
 | |
|     {
 | |
|       return l.indexOf(o);
 | |
|     }
 | |
|     public int lastIndexOf(Object o)
 | |
|     {
 | |
|       return l.lastIndexOf(o);
 | |
|     }
 | |
|     public ListIterator listIterator()
 | |
|     {
 | |
|       return new UnmodifiableListIterator(l.listIterator());
 | |
|     }
 | |
|     public ListIterator listIterator(int index)
 | |
|     {
 | |
|       return new UnmodifiableListIterator(l.listIterator(index));
 | |
|     }
 | |
|     public Object remove(int index)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public Object set(int index, Object o)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public List subList(int fromIndex, int toIndex)
 | |
|     {
 | |
|       return new UnmodifiableList(l.subList(fromIndex, toIndex));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class UnmodifiableSet extends UnmodifiableCollection
 | |
|     implements Set
 | |
|   {
 | |
|     public UnmodifiableSet(Set s)
 | |
|     {
 | |
|       super(s);
 | |
|     }
 | |
|     public boolean equals(Object o)
 | |
|     {
 | |
|       return c.equals(o);
 | |
|     }
 | |
|     public int hashCode()
 | |
|     {
 | |
|       return c.hashCode();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class UnmodifiableSortedSet extends UnmodifiableSet
 | |
|     implements SortedSet
 | |
|   {
 | |
|     // This is stored both here and in the superclass, to avoid excessive
 | |
|     // casting.
 | |
|     private SortedSet ss;
 | |
| 
 | |
|     public UnmodifiableSortedSet(SortedSet ss)
 | |
|     {
 | |
|       super(ss);
 | |
|       this.ss = ss;
 | |
|     }
 | |
| 
 | |
|     public Comparator comparator()
 | |
|     {
 | |
|       return ss.comparator();
 | |
|     }
 | |
|     public Object first()
 | |
|     {
 | |
|       return ss.first();
 | |
|     }
 | |
|     public Object last()
 | |
|     {
 | |
|       return ss.last();
 | |
|     }
 | |
|     public SortedSet headSet(Object toElement)
 | |
|     {
 | |
|       return new UnmodifiableSortedSet(ss.headSet(toElement));
 | |
|     }
 | |
|     public SortedSet tailSet(Object fromElement)
 | |
|     {
 | |
|       return new UnmodifiableSortedSet(ss.tailSet(fromElement));
 | |
|     }
 | |
|     public SortedSet subSet(Object fromElement, Object toElement)
 | |
|     {
 | |
|       return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class UnmodifiableMap implements Map, Serializable
 | |
|   {
 | |
|     Map m;
 | |
| 
 | |
|     public UnmodifiableMap(Map m)
 | |
|     {
 | |
|       this.m = m;
 | |
|     }
 | |
| 
 | |
|     public void clear()
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public boolean containsKey(Object key)
 | |
|     {
 | |
|       return m.containsKey(key);
 | |
|     }
 | |
|     public boolean containsValue(Object value)
 | |
|     {
 | |
|       return m.containsValue(value);
 | |
|     }
 | |
| 
 | |
|     // This is one of the ickiest cases of nesting I've ever seen. It just
 | |
|     // means "return an UnmodifiableSet, except that the iterator() method
 | |
|     // returns an UnmodifiableIterator whos next() method returns an
 | |
|     // unmodifiable wrapper around its normal return value".
 | |
|     public Set entrySet()
 | |
|     {
 | |
|       return new UnmodifiableSet(m.entrySet())
 | |
|       {
 | |
| 	public Iterator iterator()
 | |
| 	{
 | |
| 	  return new UnmodifiableIterator(c.iterator())
 | |
| 	  {
 | |
| 	    public Object next()
 | |
| 	    {
 | |
| 	      final Map.Entry e = (Map.Entry) super.next();
 | |
| 	      return new Map.Entry()
 | |
| 	      {
 | |
| 		public Object getKey()
 | |
| 		{
 | |
| 		  return e.getKey();
 | |
| 		}
 | |
| 		public Object getValue()
 | |
| 		{
 | |
| 		  return e.getValue();
 | |
| 		}
 | |
| 		public Object setValue(Object value)
 | |
| 		{
 | |
| 		  throw new UnsupportedOperationException();
 | |
| 		}
 | |
| 		public int hashCode()
 | |
| 		{
 | |
| 		  return e.hashCode();
 | |
| 		}
 | |
| 		public boolean equals(Object o)
 | |
| 		{
 | |
| 		  return e.equals(o);
 | |
| 		}
 | |
| 	      };
 | |
| 	    }
 | |
| 	  };
 | |
| 	}
 | |
|       };
 | |
|     }
 | |
|     public boolean equals(Object o)
 | |
|     {
 | |
|       return m.equals(o);
 | |
|     }
 | |
|     public Object get(Object key)
 | |
|     {
 | |
|       return m.get(key);
 | |
|     }
 | |
|     public Object put(Object key, Object value)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public int hashCode()
 | |
|     {
 | |
|       return m.hashCode();
 | |
|     }
 | |
|     public boolean isEmpty()
 | |
|     {
 | |
|       return m.isEmpty();
 | |
|     }
 | |
|     public Set keySet()
 | |
|     {
 | |
|       return new UnmodifiableSet(m.keySet());
 | |
|     }
 | |
|     public void putAll(Map m)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public Object remove(Object o)
 | |
|     {
 | |
|       throw new UnsupportedOperationException();
 | |
|     }
 | |
|     public int size()
 | |
|     {
 | |
|       return m.size();
 | |
|     }
 | |
|     public Collection values()
 | |
|     {
 | |
|       return new UnmodifiableCollection(m.values());
 | |
|     }
 | |
|     public String toString()
 | |
|     {
 | |
|       return m.toString();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class UnmodifiableSortedMap extends UnmodifiableMap
 | |
|     implements SortedMap
 | |
|   {
 | |
|     // This is stored both here and in the superclass, to avoid excessive
 | |
|     // casting.
 | |
|     private SortedMap sm;
 | |
| 
 | |
|     public UnmodifiableSortedMap(SortedMap sm)
 | |
|     {
 | |
|       super(sm);
 | |
|       this.sm = sm;
 | |
|     }
 | |
| 
 | |
|     public Comparator comparator()
 | |
|     {
 | |
|       return sm.comparator();
 | |
|     }
 | |
|     public Object firstKey()
 | |
|     {
 | |
|       return sm.firstKey();
 | |
|     }
 | |
|     public Object lastKey()
 | |
|     {
 | |
|       return sm.lastKey();
 | |
|     }
 | |
|     public SortedMap headMap(Object toKey)
 | |
|     {
 | |
|       return new UnmodifiableSortedMap(sm.headMap(toKey));
 | |
|     }
 | |
|     public SortedMap tailMap(Object fromKey)
 | |
|     {
 | |
|       return new UnmodifiableSortedMap(sm.tailMap(fromKey));
 | |
|     }
 | |
|     public SortedMap subMap(Object fromKey, Object toKey)
 | |
|     {
 | |
|       return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // All the "Synchronized" wrapper objects include a "sync" field which
 | |
|   // specifies what object to synchronize on. That way, nested wrappers such as
 | |
|   // UnmodifiableMap.keySet synchronize on the right things.
 | |
| 
 | |
|   private static class SynchronizedIterator implements Iterator
 | |
|   {
 | |
|     Object sync;
 | |
|     private Iterator i;
 | |
| 
 | |
|     public SynchronizedIterator(Object sync, Iterator i)
 | |
|     {
 | |
|       this.sync = sync;
 | |
|       this.i = i;
 | |
|     }
 | |
| 
 | |
|     public Object next()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return i.next();
 | |
|       }
 | |
|     }
 | |
|     public boolean hasNext()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return i.hasNext();
 | |
|       }
 | |
|     }
 | |
|     public void remove()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	i.remove();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class SynchronizedListIterator extends SynchronizedIterator
 | |
|     implements ListIterator
 | |
|   {
 | |
|     // This is stored both here and in the superclass, to avoid excessive
 | |
|     // casting.
 | |
|     private ListIterator li;
 | |
| 
 | |
|     public SynchronizedListIterator(Object sync, ListIterator li)
 | |
|     {
 | |
|       super(sync, li);
 | |
|       this.li = li;
 | |
|     }
 | |
| 
 | |
|     public boolean hasPrevious()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return li.hasPrevious();
 | |
|       }
 | |
|     }
 | |
|     public Object previous()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return li.previous();
 | |
|       }
 | |
|     }
 | |
|     public int nextIndex()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return li.nextIndex();
 | |
|       }
 | |
|     }
 | |
|     public int previousIndex()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return li.previousIndex();
 | |
|       }
 | |
|     }
 | |
|     public void add(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	li.add(o);
 | |
|       }
 | |
|     }
 | |
|     public void set(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	li.set(o);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class SynchronizedCollection implements Collection,
 | |
|     Serializable
 | |
|   {
 | |
|     Object sync;
 | |
|     Collection c;
 | |
| 
 | |
|     public SynchronizedCollection(Collection c)
 | |
|     {
 | |
|       this.sync = this;
 | |
|       this.c = c;
 | |
|     }
 | |
|     public SynchronizedCollection(Object sync, Collection c)
 | |
|     {
 | |
|       this.c = c;
 | |
|       this.sync = sync;
 | |
|     }
 | |
| 
 | |
|     public boolean add(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.add(o);
 | |
|       }
 | |
|     }
 | |
|     public boolean addAll(Collection col)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.addAll(col);
 | |
|       }
 | |
|     }
 | |
|     public void clear()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	c.clear();
 | |
|       }
 | |
|     }
 | |
|     public boolean contains(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.contains(o);
 | |
|       }
 | |
|     }
 | |
|     public boolean containsAll(Collection c1)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.containsAll(c1);
 | |
|       }
 | |
|     }
 | |
|     public boolean isEmpty()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.isEmpty();
 | |
|       }
 | |
|     }
 | |
|     public Iterator iterator()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedIterator(sync, c.iterator());
 | |
|       }
 | |
|     }
 | |
|     public boolean remove(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.remove(o);
 | |
|       }
 | |
|     }
 | |
|     public boolean removeAll(Collection col)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.removeAll(col);
 | |
|       }
 | |
|     }
 | |
|     public boolean retainAll(Collection col)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.retainAll(col);
 | |
|       }
 | |
|     }
 | |
|     public int size()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.size();
 | |
|       }
 | |
|     }
 | |
|     public Object[] toArray()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.toArray();
 | |
|       }
 | |
|     }
 | |
|     public Object[] toArray(Object[]a)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.toArray(a);
 | |
|       }
 | |
|     }
 | |
|     public String toString()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.toString();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class SynchronizedList extends SynchronizedCollection
 | |
|     implements List
 | |
|   {
 | |
|     // This is stored both here and in the superclass, to avoid excessive
 | |
|     // casting.
 | |
|     List l;
 | |
| 
 | |
|     public SynchronizedList(Object sync, List l)
 | |
|     {
 | |
|       super(sync, l);
 | |
|       this.l = l;
 | |
|     }
 | |
|     public SynchronizedList(List l)
 | |
|     {
 | |
|       super(l);
 | |
|       this.l = l;
 | |
|     }
 | |
| 
 | |
|     public void add(int index, Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	l.add(index, o);
 | |
|       }
 | |
|     }
 | |
|     public boolean addAll(int index, Collection c)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return l.addAll(index, c);
 | |
|       }
 | |
|     }
 | |
|     public boolean equals(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return l.equals(o);
 | |
|       }
 | |
|     }
 | |
|     public Object get(int index)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return l.get(index);
 | |
|       }
 | |
|     }
 | |
|     public int hashCode()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return l.hashCode();
 | |
|       }
 | |
|     }
 | |
|     public int indexOf(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return l.indexOf(o);
 | |
|       }
 | |
|     }
 | |
|     public int lastIndexOf(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return l.lastIndexOf(o);
 | |
|       }
 | |
|     }
 | |
|     public ListIterator listIterator()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedListIterator(sync, l.listIterator());
 | |
|       }
 | |
|     }
 | |
|     public ListIterator listIterator(int index)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedListIterator(sync, l.listIterator(index));
 | |
|       }
 | |
|     }
 | |
|     public Object remove(int index)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return l.remove(index);
 | |
|       }
 | |
|     }
 | |
|     public boolean remove(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return l.remove(o);
 | |
|       }
 | |
|     }
 | |
|     public Object set(int index, Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return l.set(index, o);
 | |
|       }
 | |
|     }
 | |
|     public List subList(int fromIndex, int toIndex)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedList(l.subList(fromIndex, toIndex));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class SynchronizedSet extends SynchronizedCollection
 | |
|     implements Set
 | |
|   {
 | |
|     public SynchronizedSet(Object sync, Set s)
 | |
|     {
 | |
|       super(sync, s);
 | |
|     }
 | |
|     public SynchronizedSet(Set s)
 | |
|     {
 | |
|       super(s);
 | |
|     }
 | |
| 
 | |
|     public boolean equals(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.equals(o);
 | |
|       }
 | |
|     }
 | |
|     public int hashCode()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return c.hashCode();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class SynchronizedSortedSet extends SynchronizedSet
 | |
|     implements SortedSet
 | |
|   {
 | |
|     // This is stored both here and in the superclass, to avoid excessive
 | |
|     // casting.
 | |
|     private SortedSet ss;
 | |
| 
 | |
|     public SynchronizedSortedSet(Object sync, SortedSet ss)
 | |
|     {
 | |
|       super(sync, ss);
 | |
|       this.ss = ss;
 | |
|     }
 | |
|     public SynchronizedSortedSet(SortedSet ss)
 | |
|     {
 | |
|       super(ss);
 | |
|       this.ss = ss;
 | |
|     }
 | |
| 
 | |
|     public Comparator comparator()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return ss.comparator();
 | |
|       }
 | |
|     }
 | |
|     public Object first()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return ss.first();
 | |
|       }
 | |
|     }
 | |
|     public Object last()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return ss.last();
 | |
|       }
 | |
|     }
 | |
|     public SortedSet headSet(Object toElement)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedSortedSet(sync, ss.headSet(toElement));
 | |
|       }
 | |
|     }
 | |
|     public SortedSet tailSet(Object fromElement)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedSortedSet(sync, ss.tailSet(fromElement));
 | |
|       }
 | |
|     }
 | |
|     public SortedSet subSet(Object fromElement, Object toElement)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedSortedSet(sync,
 | |
| 					 ss.subSet(fromElement, toElement));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class SynchronizedMap implements Map, Serializable
 | |
|   {
 | |
|     Object sync;
 | |
|     Map m;
 | |
| 
 | |
|     public SynchronizedMap(Object sync, Map m)
 | |
|     {
 | |
|       this.sync = sync;
 | |
|       this.m = m;
 | |
|     }
 | |
|     public SynchronizedMap(Map m)
 | |
|     {
 | |
|       this.m = m;
 | |
|       this.sync = this;
 | |
|     }
 | |
| 
 | |
|     public void clear()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	m.clear();
 | |
|       }
 | |
|     }
 | |
|     public boolean containsKey(Object key)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return m.containsKey(key);
 | |
|       }
 | |
|     }
 | |
|     public boolean containsValue(Object value)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	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 whos next() method returns a
 | |
|     // synchronized wrapper around its normal return value".
 | |
|     public Set entrySet()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedSet(sync, m.entrySet())
 | |
| 	{
 | |
| 	  public Iterator iterator()
 | |
| 	  {
 | |
| 	    synchronized(SynchronizedMap.this.sync)
 | |
| 	    {
 | |
| 	      return new SynchronizedIterator(SynchronizedMap.this.sync,
 | |
| 					      c.iterator())
 | |
| 	      {
 | |
| 		public Object next()
 | |
| 		{
 | |
| 		  synchronized(SynchronizedMap.this.sync)
 | |
| 		  {
 | |
| 		    final Map.Entry e = (Map.Entry) super.next();
 | |
| 		    return new Map.Entry()
 | |
| 		    {
 | |
| 		      public Object getKey()
 | |
| 		      {
 | |
| 			synchronized(SynchronizedMap.this.sync)
 | |
| 			{
 | |
| 			  return e.getKey();
 | |
| 			}
 | |
| 		      }
 | |
| 		      public Object getValue()
 | |
| 		      {
 | |
| 			synchronized(SynchronizedMap.this.sync)
 | |
| 			{
 | |
| 			  return e.getValue();
 | |
| 			}
 | |
| 		      }
 | |
| 		      public Object setValue(Object value)
 | |
| 		      {
 | |
| 			synchronized(SynchronizedMap.this.sync)
 | |
| 			{
 | |
| 			  return e.setValue(value);
 | |
| 			}
 | |
| 		      }
 | |
| 		      public int hashCode()
 | |
| 		      {
 | |
| 			synchronized(SynchronizedMap.this.sync)
 | |
| 			{
 | |
| 			  return e.hashCode();
 | |
| 			}
 | |
| 		      }
 | |
| 		      public boolean equals(Object o)
 | |
| 		      {
 | |
| 			synchronized(SynchronizedMap.this.sync)
 | |
| 			{
 | |
| 			  return e.equals(o);
 | |
| 			}
 | |
| 		      }
 | |
| 		    };
 | |
| 		  }
 | |
| 		}
 | |
| 	      };
 | |
| 	    }
 | |
| 	  }
 | |
| 	};
 | |
|       }
 | |
|     }
 | |
|     public boolean equals(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return m.equals(o);
 | |
|       }
 | |
|     }
 | |
|     public Object get(Object key)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return m.get(key);
 | |
|       }
 | |
|     }
 | |
|     public Object put(Object key, Object value)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return m.put(key, value);
 | |
|       }
 | |
|     }
 | |
|     public int hashCode()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return m.hashCode();
 | |
|       }
 | |
|     }
 | |
|     public boolean isEmpty()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return m.isEmpty();
 | |
|       }
 | |
|     }
 | |
|     public Set keySet()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedSet(sync, m.keySet());
 | |
|       }
 | |
|     }
 | |
|     public void putAll(Map map)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	m.putAll(map);
 | |
|       }
 | |
|     }
 | |
|     public Object remove(Object o)
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return m.remove(o);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     public int size()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return m.size();
 | |
|       }
 | |
|     }
 | |
|     public Collection values()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return new SynchronizedCollection(sync, m.values());
 | |
|       }
 | |
|     }
 | |
|     public String toString()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return m.toString();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   private static class SynchronizedSortedMap extends SynchronizedMap
 | |
|     implements SortedMap
 | |
|   {
 | |
|     // This is stored both here and in the superclass, to avoid excessive
 | |
|     // casting.
 | |
|     private SortedMap sm;
 | |
| 
 | |
|     public SynchronizedSortedMap(Object sync, SortedMap sm)
 | |
|     {
 | |
|       super(sync, sm);
 | |
|       this.sm = sm;
 | |
|     }
 | |
|     public SynchronizedSortedMap(SortedMap sm)
 | |
|     {
 | |
|       super(sm);
 | |
|       this.sm = sm;
 | |
|     }
 | |
| 
 | |
|     public Comparator comparator()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return sm.comparator();
 | |
|       }
 | |
|     }
 | |
|     public Object firstKey()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return sm.firstKey();
 | |
|       }
 | |
|     }
 | |
|     public Object lastKey()
 | |
|     {
 | |
|       synchronized(sync)
 | |
|       {
 | |
| 	return sm.lastKey();
 | |
|       }
 | |
|     }
 | |
|     public SortedMap headMap(Object toKey)
 | |
|     {
 | |
|       return new SynchronizedSortedMap(sync, sm.headMap(toKey));
 | |
|     }
 | |
|     public SortedMap tailMap(Object fromKey)
 | |
|     {
 | |
|       return new SynchronizedSortedMap(sync, sm.tailMap(fromKey));
 | |
|     }
 | |
|     public SortedMap subMap(Object fromKey, Object toKey)
 | |
|     {
 | |
|       return new SynchronizedSortedMap(sync, sm.subMap(fromKey, toKey));
 | |
|     }
 | |
|   }
 | |
| }
 |