/* CopyOnWriteArrayList.java
   Copyright (C) 2006 Free Software Foundation

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.concurrent;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import java.lang.reflect.Array;

import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.RandomAccess;

/**
 * A thread-safe implementation of an ArrayList. A CopyOnWriteArrayList is
 * as special ArrayList which performs copies of the underlying storage
 * each time a write (<code>remove</code>, <code>add</code> etc..) operation
 * is performed.<br />
 * <br />
 * The update operation in this class run usually in <code>O(n)</code> or worse,
 * but traversal operations are fast and efficient, especially when running in
 * a multi-thread environment without the need to design complex synchronize
 * mechanisms.<br />
 * <br />
 * <code>Iterator</code>s in this class work on a snapshot of the backing store
 * at the moment the iterator itself was created, hence the iterator will not
 * reflect changes in the underlying storage. Thus, update operation on the
 * <code>Iterator</code>s are not supported, but as interferences from other
 * threads are impossible, no <code>ConcurrentModificationException</code>
 * will be ever thrown from within the <code>Iterator</code>.
 * <br /><br />
 * This class is especially useful when used with event handling, like the
 * following code demonstrates:<br />
 * <code><pre>
 * 
 * CopyOnWriteArrayList<EventListener> listeners =
 *   new CopyOnWriteArrayList<EventListener>();
 * 
 * [...]
 * 
 * for (final EventListener listener : listeners)
 *   {
 *     Runnable dispatcher = new Runnable() {
 *       public void run()
 *       {
 *         listener.preferenceChange(event);
 *       }
 *     };
 *         
 *     Executor executor = Executors.newSingleThreadExecutor();
 *     executor.execute(dispatcher);
 *   }
 * </pre></code>
 * 
 * @since 1.5
 */
public class CopyOnWriteArrayList<E> 
  implements List<E>, RandomAccess, Cloneable, Serializable
{
  /**
   * 
   */
  private static final long serialVersionUID = 8673264195747942595L;
  
  /**
   * Where the data is stored.
   */
  private transient E[] data;

  /**
   * Construct a new ArrayList with the default capacity (16).
   */
  public CopyOnWriteArrayList()
  {
    data = (E[]) new Object[0];
  }

  /**
   * Construct a new ArrayList, and initialize it with the elements in the
   * supplied Collection. The initial capacity is 110% of the Collection's size.
   * 
   * @param c
   *          the collection whose elements will initialize this list
   * @throws NullPointerException
   *           if c is null
   */
  public CopyOnWriteArrayList(Collection< ? extends E> c)
  {
    // FIXME ... correct?  use c.toArray()
    data = (E[]) new Object[c.size()];
    int index = 0;
    for (E value : c)
      data[index++] = value;
  }

  /**
   * Construct a new ArrayList, and initialize it with the elements in the
   * supplied array.
   * 
   * @param array
   *          the array used to initialize this list
   * @throws NullPointerException
   *           if array is null
   */
  public CopyOnWriteArrayList(E[] array)
  {
    data = (E[]) array.clone();
  }

  /**
   * Returns the number of elements in this list.
   * 
   * @return the list size
   */
  public int size()
  {
    return data.length;
  }

  /**
   * Checks if the list is empty.
   * 
   * @return true if there are no elements
   */
  public boolean isEmpty()
  {
    return data.length == 0;
  }

  /**
   * Returns true if element is in this ArrayList.
   * 
   * @param e
   *          the element whose inclusion in the List is being tested
   * @return true if the list contains e
   */
  public boolean contains(Object e)
  {
    return indexOf(e) != -1;
  }

  /**
   * Tests whether this collection contains all the elements in a given
   * collection. This implementation iterates over the given collection,
   * testing whether each element is contained in this collection. If any one
   * is not, false is returned. Otherwise true is returned.
   *
   * @param c the collection to test against
   * @return true if this collection contains all the elements in the given
   *         collection
   * @throws NullPointerException if the given collection is null
   * @see #contains(Object)
   */
  public boolean containsAll(Collection<?> c)
  {
    Iterator<?> itr = c.iterator();
    int pos = c.size();
    while (--pos >= 0)
      if (!contains(itr.next()))
        return false;
    return true;
  }

  /**
   * Returns the lowest index at which element appears in this List, or -1 if it
   * does not appear.
   * 
   * @param e
   *          the element whose inclusion in the List is being tested
   * @return the index where e was found
   */
  public int indexOf(Object e)
  {
    E[] data = this.data;
    for (int i = 0; i < data.length; i++)
      if (equals(e, data[i]))
        return i;
    return -1;
  }

  /**
   * Return the lowest index greater equal <code>index</code> at which
   * <code>e</code> appears in this List, or -1 if it does not
   * appear.
   *
   * @param e the element whose inclusion in the list is being tested
   * @param index the index at which the search begins
   * @return the index where <code>e</code> was found
   */
  public int indexOf(E e, int index)
  {
    E[] data = this.data;

    for (int i = index; i < data.length; i++)
      if (equals(e, data[i]))
        return i;
    return -1;
  }

  /**
   * Returns the highest index at which element appears in this List, or -1 if
   * it does not appear.
   * 
   * @param e
   *          the element whose inclusion in the List is being tested
   * @return the index where e was found
   */
  public int lastIndexOf(Object e)
  {
    E[] data = this.data;
    for (int i = data.length - 1; i >= 0; i--)
      if (equals(e, data[i]))
        return i;
    return -1;
  }

  /**
   * Returns the highest index lesser equal <code>index</code> at
   * which <code>e</code> appears in this List, or -1 if it does not
   * appear.
   *
   * @param e the element whose inclusion in the list is being tested
   * @param index the index at which the search begins
   * @return the index where <code>e</code> was found
   */
  public int lastIndexOf(E e, int index)
  {
    E[] data = this.data;

    for (int i = index; i >= 0; i--)
      if (equals(e, data[i]))
        return i;
    return -1;
  }

  /**
   * Creates a shallow copy of this ArrayList (elements are not cloned).
   * 
   * @return the cloned object
   */
  public Object clone()
  {
    CopyOnWriteArrayList<E> clone = null;
    try
      {
        clone = (CopyOnWriteArrayList<E>) super.clone();
      }
    catch (CloneNotSupportedException e)
      {
        // Impossible to get here.
      }
    return clone;
  }

  /**
   * Returns an Object array containing all of the elements in this ArrayList.
   * The array is independent of this list.
   * 
   * @return an array representation of this list
   */
  public Object[] toArray()
  {
    E[] data = this.data;
    E[] array = (E[]) new Object[data.length];
    System.arraycopy(data, 0, array, 0, data.length);
    return array;
  }

  /**
   * Returns an Array whose component type is the runtime component type of the
   * passed-in Array. The returned Array is populated with all of the elements
   * in this ArrayList. If the passed-in Array is not large enough to store all
   * of the elements in this List, a new Array will be created and returned; if
   * the passed-in Array is <i>larger</i> than the size of this List, then
   * size() index will be set to null.
   * 
   * @param a
   *          the passed-in Array
   * @return an array representation of this list
   * @throws ArrayStoreException
   *           if the runtime type of a does not allow an element in this list
   * @throws NullPointerException
   *           if a is null
   */
  public <T> T[] toArray(T[] a)
  {
    E[] data = this.data;
    if (a.length < data.length)
      a = (T[]) Array.newInstance(a.getClass().getComponentType(), data.length);
    else if (a.length > data.length)
      a[data.length] = null;
    System.arraycopy(data, 0, a, 0, data.length);
    return a;
  }

  /**
   * Retrieves the element at the user-supplied index.
   * 
   * @param index
   *          the index of the element we are fetching
   * @throws IndexOutOfBoundsException
   *           if index &lt; 0 || index &gt;= size()
   */
  public E get(int index)
  {
    return data[index];
  }

  /**
   * Sets the element at the specified index. The new element, e, can be an
   * object of any type or null.
   * 
   * @param index
   *          the index at which the element is being set
   * @param e
   *          the element to be set
   * @return the element previously at the specified index
   * @throws IndexOutOfBoundsException
   *           if index &lt; 0 || index &gt;= 0
   */
  public synchronized E set(int index, E e)
  {
    E result = data[index];
    E[] newData = (E[]) data.clone();
    newData[index] = e;
    data = newData;
    return result;
  }

  /**
   * Appends the supplied element to the end of this list. The element, e, can
   * be an object of any type or null.
   * 
   * @param e
   *          the element to be appended to this list
   * @return true, the add will always succeed
   */
  public synchronized boolean add(E e)
  {
    E[] data = this.data;
    E[] newData = (E[]) new Object[data.length + 1];
    System.arraycopy(data, 0, newData, 0, data.length);
    newData[data.length] = e;
    this.data = newData;
    return true;
  }

  /**
   * Adds the supplied element at the specified index, shifting all elements
   * currently at that index or higher one to the right. The element, e, can be
   * an object of any type or null.
   * 
   * @param index
   *          the index at which the element is being added
   * @param e
   *          the item being added
   * @throws IndexOutOfBoundsException
   *           if index &lt; 0 || index &gt; size()
   */
  public synchronized void add(int index, E e)
  {
    E[] data = this.data;
    E[] newData = (E[]) new Object[data.length + 1];
    System.arraycopy(data, 0, newData, 0, index);
    newData[index] = e;
    System.arraycopy(data, index, newData, index + 1, data.length - index);
    this.data = newData;
  }

  /**
   * Removes the element at the user-supplied index.
   * 
   * @param index
   *          the index of the element to be removed
   * @return the removed Object
   * @throws IndexOutOfBoundsException
   *           if index &lt; 0 || index &gt;= size()
   */
  public synchronized E remove(int index)
  {
    if (index < 0 || index >= this.size())
      throw new IndexOutOfBoundsException("index = " +  index);
    
    E[] snapshot = this.data;
    E[] newData = (E[]) new Object[snapshot.length - 1];
    
    E result = snapshot[index];
    
    if (index > 0)
      System.arraycopy(snapshot, 0, newData, 0, index);
    
    System.arraycopy(snapshot, index + 1, newData, index,
                     snapshot.length - index - 1);
    
    this.data = newData;
    
    return result;
  }

  /**
   * Remove the first occurrence, if any, of the given object from this list,
   * returning <code>true</code> if the object was removed, <code>false</code>
   * otherwise.
   * 
   * @param element the object to be removed.
   * @return true if element was removed, false otherwise. false means also that
   * the underlying storage was unchanged after this operation concluded.
   */
  public synchronized boolean remove(Object element)
  {
    E[] snapshot = this.data;
    E[] newData = (E[]) new Object[snapshot.length - 1];
    
    // search the element to remove while filling the backup array
    // this way we can run this method in O(n)
    int elementIndex = -1;
    for (int i = 0; i < snapshot.length; i++)
      {
        if (equals(element, snapshot[i]))
          {
            elementIndex = i;
            break;
          }
        
        if (i < newData.length)
          newData[i] = snapshot[i];
      }
    
    if (elementIndex < 0)
      return false;
     
    System.arraycopy(snapshot, elementIndex + 1, newData, elementIndex,
                     snapshot.length - elementIndex - 1);
    this.data = newData;
    
    return true;
  }
  
  /**
   * Removes all the elements contained in the given collection.
   * This method removes the elements that are contained in both
   * this list and in the given collection.
   * 
   * @param c the collection containing the elements to be removed from this
   * list.
   * @return true if at least one element was removed, indicating that
   * the list internal storage changed as a result, false otherwise. 
   */
  public synchronized boolean removeAll(Collection<?> c)
  {
    if (c.size() == 0)
      return false;
    
    E [] snapshot = this.data;
    E [] storage = (E[]) new Object[this.data.length]; 
    boolean changed = false;
    
    int length = 0;
    for (E element : snapshot)
      {
        // copy all the elements, including null values
        // if the collection can hold it
        // FIXME: slow operation
        if (c.contains(element))
          changed = true;
        else
          storage[length++] = element;
      }
    
    if (!changed)
      return false;
    
    E[] newData = (E[]) new Object[length];
    System.arraycopy(storage, 0, newData, 0, length);
    
    this.data = newData;
    
    return true;
  }
  
  /**
   * Removes all the elements that are not in the passed collection.
   * If the collection is void, this method has the same effect of
   * <code>clear()</code>.
   * Please, note that this method is extremely slow (unless the argument has
   * <code>size == 0</code>) and has bad performance is both space and time
   * usage.
   * 
   * @param c the collection containing the elements to be retained by this
   * list.
   * @return true the list internal storage changed as a result of this
   * operation, false otherwise.
   */
  public synchronized boolean retainAll(Collection<?> c)
  {
    // if the given collection does not contain elements
    // we remove all the elements from our storage
    if (c.size() == 0)
      {
        this.clear();
        return true;
      }
    
    E [] snapshot = this.data;
    E [] storage = (E[]) new Object[this.data.length]; 
    
    int length = 0;
    for (E element : snapshot)
      {
        if (c.contains(element))
          storage[length++] = element;
      }
    
    // means we retained all the elements previously in our storage
    // we are running already slow here, but at least we avoid copying
    // another array and changing the internal storage
    if (length == snapshot.length)
      return false;
    
    E[] newData = (E[]) new Object[length];
    System.arraycopy(storage, 0, newData, 0, length);
    
    this.data = newData;
    
    return true;
  }
  
  /**
   * Removes all elements from this List
   */
  public synchronized void clear()
  {
    data = (E[]) new Object[0];
  }

  /**
   * Add each element in the supplied Collection to this List. It is undefined
   * what happens if you modify the list while this is taking place; for
   * example, if the collection contains this list. c can contain objects of any
   * type, as well as null values.
   * 
   * @param c
   *          a Collection containing elements to be added to this List
   * @return true if the list was modified, in other words c is not empty
   * @throws NullPointerException
   *           if c is null
   */
  public synchronized boolean addAll(Collection< ? extends E> c)
  {
    return addAll(data.length, c);
  }

  /**
   * Add all elements in the supplied collection, inserting them beginning at
   * the specified index. c can contain objects of any type, as well as null
   * values.
   * 
   * @param index
   *          the index at which the elements will be inserted
   * @param c
   *          the Collection containing the elements to be inserted
   * @throws IndexOutOfBoundsException
   *           if index &lt; 0 || index &gt; 0
   * @throws NullPointerException
   *           if c is null
   */
  public synchronized boolean addAll(int index, Collection< ? extends E> c)
  {
    if (index < 0 || index > this.size())
      throw new IndexOutOfBoundsException("index = " +  index);
    
    int csize = c.size();
    if (csize == 0)
      return false;
    
    E[] data = this.data;
    Iterator<? extends E> itr = c.iterator();
    
    E[] newData = (E[]) new Object[data.length + csize];
    
    // avoid this call at all if we were asked to put the elements at the
    // beginning of our storage
    if (index != 0)
      System.arraycopy(data, 0, newData, 0, index);
    
    int itemsLeft = index;
    
    for (E value : c)
      newData[index++] = value;
    
    // now copy the remaining elements
    System.arraycopy(data, itemsLeft, newData, 0, data.length - itemsLeft);
    
    this.data = newData;
    
    return true;
  }
  
  /**
   * Adds an element if the list does not contains it already.
   * 
   * @param val the element to add to the list.
   * @return true if the element was added, false otherwise.
   */
  public synchronized boolean addIfAbsent(E val)
  {
    if (contains(val))
      return false;
    add(val);
    return true;
  }

  /**
   * Adds all the element from the given collection that are not already
   * in this list.
   * 
   * @param c the Collection containing the elements to be inserted
   * @return true the list internal storage changed as a result of this
   * operation, false otherwise.
   */
  public synchronized int addAllAbsent(Collection<? extends E> c)
  {
    int size = c.size();
    if (size == 0)
      return 0;
    
    E [] snapshot = this.data;
    E [] storage = (E[]) new Object[size];
    
    size = 0;
    for (E val : c)
      {
        if (!this.contains(val))
          storage[size++] = val;
      }
    
    if (size == 0)
      return 0;
    
    // append storage to data
    E [] newData = (E[]) new Object[snapshot.length + size];
    
    System.arraycopy(snapshot, 0, newData, 0, snapshot.length);
    System.arraycopy(storage, 0, newData, snapshot.length, size);
    
    this.data = newData;
    
    return size;
  }

  public String toString()
  {
    return Arrays.toString(this.data);
  }

  public boolean equals(Object o)
  {
    if (o == null)
      return false;
    
    if (this == o)
      return true;
    
    // let's see if 'o' is a list, if so, we need to compare the elements
    // as returned by the iterator
    if (o instanceof List)
      {
        List<?> source = (List<?>) o;
        
        if (source.size() != this.size())
          return false;
        
        Iterator<?> sourceIterator = source.iterator();
        for (E element : this)
          {
            if (!element.equals(sourceIterator.next()))
              return false;
          }

        return true;
      }
    
    return false;
  }
  
  public int hashCode()
  {
    // see http://java.sun.com/6/docs/api/java/util/List.html#hashcode()
    int hashcode = 1;
    for (E element : this)
      {
        hashcode = 31 * hashcode + (element == null ? 0 : element.hashCode());
      }
    return hashcode;
  }
  
  /**
   * Return an Iterator containing the elements of this list.
   * The Iterator uses a snapshot of the state of the internal storage
   * at the moment this method is called and does <strong>not</strong> support
   * update operations, so no synchronization is needed to traverse the
   * iterator.
   * 
   * @return an Iterator containing the elements of this list in sequence.
   */
  public Iterator<E> iterator()
  {
    return new Iterator<E>()
    {
      E [] iteratorData = CopyOnWriteArrayList.this.data;
      int currentElement = 0;
      
      public boolean hasNext()
      {
        return (currentElement < iteratorData.length);
      }

      public E next()
      {
        return iteratorData[currentElement++];
      }

      public void remove()
      {
        throw new UnsupportedOperationException("updating of elements in " +
                                                "iterators is not supported " +
                                                "by this class");
      }
    };
  }
  
  /**
   * Return a ListIterator containing the elements of this list.
   * The Iterator uses a snapshot of the state of the internal storage
   * at the moment this method is called and does <strong>not</strong> support
   * update operations, so no synchronization is needed to traverse the
   * iterator.
   * 
   * @return a ListIterator containing the elements of this list in sequence.
   */
  public ListIterator<E> listIterator()
  {
    return listIterator(0);
  }

  /**
   * Return a ListIterator over the elements of this list starting at
   * the specified index.  An initial call to {@code next()} will thus
   * return the element at {@code index}, while an initial call to
   * {@code previous()} will return the element at {@code index-1}.  The
   * Iterator uses a snapshot of the state of the internal storage
   * at the moment this method is called and does <strong>not</strong> support
   * update operations, so no synchronization is needed to traverse the
   * iterator.
   * 
   * @param index the index at which to start iterating.
   * @return a ListIterator containing the elements of this list in sequence.
   */
  public ListIterator<E> listIterator(final int index)
  {
    if (index < 0 || index > size())
      throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
                                          + size());

    return new ListIterator<E>()
    {
      E [] iteratorData = CopyOnWriteArrayList.this.data;
      int currentElement = index;
      
      public void add(E o)
      {
        throw new UnsupportedOperationException("updating of elements in " +
                                                "iterators is not supported " +
                                                "by this class");
      }

      public boolean hasNext()
      {
        return (currentElement < iteratorData.length);
      }

      public boolean hasPrevious()
      {
        return (currentElement > 0);
      }

      public E next()
      {
        if (hasNext() == false)
          throw new java.util.NoSuchElementException();
        
        return iteratorData[currentElement++];
      }

      public int nextIndex()
      {
        return (currentElement + 1);
      }

      public E previous()
      {
        if (hasPrevious() == false)
          throw new java.util.NoSuchElementException();
        
        return iteratorData[--currentElement];
      }

      public int previousIndex()
      {
        return (currentElement - 1);
      }

      public void remove()
      {
        throw new UnsupportedOperationException("updating of elements in " +
                                                "iterators is not supported " +
                                                "by this class");
      }

      public void set(E o)
      {
        throw new UnsupportedOperationException("updating of elements in " +
                                                "iterators is not supported " +
                                                "by this class");
      }
      
    };
  }
  
  /**
   * Obtain a List view of a subsection of this 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.
   * <p>
   *
   * This implementation returns a subclass of AbstractList. It stores, in
   * private fields, the offset and size of the sublist, and the expected
   * modCount of the backing list. If the backing list implements RandomAccess,
   * the sublist will also.
   * <p>
   *
   * The subclass's <code>set(int, Object)</code>, <code>get(int)</code>,
   * <code>add(int, Object)</code>, <code>remove(int)</code>,
   * <code>addAll(int, Collection)</code> and
   * <code>removeRange(int, int)</code> methods all delegate to the
   * corresponding methods on the backing abstract list, after
   * bounds-checking the index and adjusting for the offset. The
   * <code>addAll(Collection c)</code> method merely returns addAll(size, c).
   * The <code>listIterator(int)</code> method returns a "wrapper object"
   * over a list iterator on the backing list, which is created with the
   * corresponding method on the backing list. The <code>iterator()</code>
   * method merely returns listIterator(), and the <code>size()</code> method
   * merely returns the subclass's size field.
   * <p>
   *
   * All methods first check to see if the actual modCount of the backing
   * list is equal to its expected value, and throw a
   * ConcurrentModificationException if it is not. 
   *
   * @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()
   * @throws IndexOutOfBoundsException if fromIndex &gt; toIndex
   * @see ConcurrentModificationException
   * @see RandomAccess
   */
  public synchronized List<E> subList(int fromIndex, int toIndex)
  {
    // This follows the specification of AbstractList, but is inconsistent
    // with the one in List. Don't you love Sun's inconsistencies?
    if (fromIndex > toIndex)
      throw new IndexOutOfBoundsException(fromIndex + " > " + toIndex);
    if (fromIndex < 0 || toIndex > size())
      throw new IndexOutOfBoundsException();

    if (this instanceof RandomAccess)
      return new RandomAccessSubList<E>(this, fromIndex, toIndex);
    return new SubList<E>(this, fromIndex, toIndex);
  }

  /**
   * This class follows the implementation requirements set forth in
   * {@link AbstractList#subList(int, int)}. It matches Sun's implementation
   * by using a non-public top-level class in the same package.
   *
   * @author Original author unknown
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static class SubList<E> 
    extends AbstractList<E>
  {
    // Package visible, for use by iterator.
    /** The original list. */
    final CopyOnWriteArrayList<E> backingList;
    /** The index of the first element of the sublist. */
    final int offset;
    /** The size of the sublist. */
    int size;
    /** The backing data */
    E[] data;

    /**
     * Construct the sublist.
     *
     * @param backing the list this comes from
     * @param fromIndex the lower bound, inclusive
     * @param toIndex the upper bound, exclusive
     */
    SubList(CopyOnWriteArrayList<E> backing, int fromIndex, int toIndex)
    {
      backingList = backing;
      data = backing.data;
      offset = fromIndex;
      size = toIndex - fromIndex;
    }
    
    /**
     * This method checks the two modCount fields to ensure that there has
     * not been a concurrent modification, returning if all is okay.
     *
     * @throws ConcurrentModificationException if the backing list has been
     *         modified externally to this sublist
     */
    // This can be inlined. Package visible, for use by iterator.
    void checkMod()
    {
      if (data != backingList.data)
        throw new ConcurrentModificationException();
    }
    
    /**
     * This method checks that a value is between 0 and size (inclusive). If
     * it is not, an exception is thrown.
     *
     * @param index the value to check
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
     */
    // This will get inlined, since it is private.
    private void checkBoundsInclusive(int index)
    {
      if (index < 0 || index > size)
        throw new IndexOutOfBoundsException("Index: " + index +
                                            ", Size:" + size);
    }
    
    /**
     * This method checks that a value is between 0 (inclusive) and size
     * (exclusive). If it is not, an exception is thrown.
     *
     * @param index the value to check
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
     */
    // This will get inlined, since it is private.
    private void checkBoundsExclusive(int index)
    {
      if (index < 0 || index >= size)
        throw new IndexOutOfBoundsException("Index: " + index +
                                            ", Size:" + size);
    }
    
    /**
     * Specified by AbstractList.subList to return the private field size.
     *
     * @return the sublist size
     * @throws ConcurrentModificationException if the backing list has been
     *         modified externally to this sublist
     */
    public int size()
    {
      synchronized (backingList)
        {
          checkMod();
          return size;
        }
    }
    
    public void clear()
    {
      synchronized (backingList)
        {
          E[] snapshot = backingList.data;
          E[] newData = (E[]) new Object[snapshot.length - size];

          int toIndex = size + offset;
          
          System.arraycopy(snapshot, 0, newData, 0, offset);
          System.arraycopy(snapshot, toIndex, newData, offset,
                           snapshot.length - toIndex);
          
          backingList.data = newData;
          this.data = backingList.data;
          this.size = 0;
        }
    }
    
    /**
     * Specified by AbstractList.subList to delegate to the backing list.
     *
     * @param index the location to modify
     * @param o the new value
     * @return the old value
     * @throws ConcurrentModificationException if the backing list has been
     *         modified externally to this sublist
     * @throws UnsupportedOperationException if the backing list does not
     *         support the set operation
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
     * @throws ClassCastException if o cannot be added to the backing list due
     *         to its type
     * @throws IllegalArgumentException if o cannot be added to the backing list
     *         for some other reason
     */
    public E set(int index, E o)
    {
      synchronized (backingList)
        {
          checkMod();
          checkBoundsExclusive(index);
          
          E el =  backingList.set(index + offset, o);
          this.data = backingList.data;
          
          return el;
        }
    }
    
    /**
     * Specified by AbstractList.subList to delegate to the backing list.
     *
     * @param index the location to get from
     * @return the object at that location
     * @throws ConcurrentModificationException if the backing list has been
     *         modified externally to this sublist
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
     */
    public E get(int index)
    {
      synchronized (backingList)
      {
        checkMod();
        checkBoundsExclusive(index);
        
        return backingList.get(index + offset);
      }
    }
    
    /**
     * Specified by AbstractList.subList to delegate to the backing list.
     *
     * @param index the index to insert at
     * @param o the object to add
     * @throws ConcurrentModificationException if the backing list has been
     *         modified externally to this sublist
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
     * @throws UnsupportedOperationException if the backing list does not
     *         support the add operation.
     * @throws ClassCastException if o cannot be added to the backing list due
     *         to its type.
     * @throws IllegalArgumentException if o cannot be added to the backing
     *         list for some other reason.
     */
    public void add(int index, E o)
    {
      synchronized (backingList)
      {
        checkMod();
        checkBoundsInclusive(index);
      
        backingList.add(index + offset, o);
        
        this.data = backingList.data;
        size++;
      }
    }
    
    /**
     * Specified by AbstractList.subList to delegate to the backing list.
     *
     * @param index the index to remove
     * @return the removed object
     * @throws ConcurrentModificationException if the backing list has been
     *         modified externally to this sublist
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
     * @throws UnsupportedOperationException if the backing list does not
     *         support the remove operation
     */
    public E remove(int index)
    {
      synchronized (backingList)
      {
        checkMod();
        checkBoundsExclusive(index);
        E o = backingList.remove(index + offset);
        
        this.data = backingList.data;
        size--;
        
        return o;
      }
    }
    
    /**
     * Specified by AbstractList.subList to delegate to the backing list.
     *
     * @param index the location to insert at
     * @param c the collection to insert
     * @return true if this list was modified, in other words, c is non-empty
     * @throws ConcurrentModificationException if the backing list has been
     *         modified externally to this sublist
     * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
     * @throws UnsupportedOperationException if this list does not support the
     *         addAll operation
     * @throws ClassCastException if some element of c cannot be added to this
     *         list due to its type
     * @throws IllegalArgumentException if some element of c cannot be added
     *         to this list for some other reason
     * @throws NullPointerException if the specified collection is null
     */
    public boolean addAll(int index, Collection<? extends E> c)
    {
      synchronized (backingList)
      {
        checkMod();
        checkBoundsInclusive(index);
        int csize = c.size();
        boolean result = backingList.addAll(offset + index, c);
        
        this.data = backingList.data;
        size += csize;
        
        return result;
      }
    }
    
    /**
     * Specified by AbstractList.subList to return addAll(size, c).
     *
     * @param c the collection to insert
     * @return true if this list was modified, in other words, c is non-empty
     * @throws ConcurrentModificationException if the backing list has been
     *         modified externally to this sublist
     * @throws UnsupportedOperationException if this list does not support the
     *         addAll operation
     * @throws ClassCastException if some element of c cannot be added to this
     *         list due to its type
     * @throws IllegalArgumentException if some element of c cannot be added
     *         to this list for some other reason
     * @throws NullPointerException if the specified collection is null
     */
    public boolean addAll(Collection<? extends E> c)
    {
      synchronized (backingList)
      {
        return addAll(size, c);
      }
    }
    
    /**
     * Specified by AbstractList.subList to return listIterator().
     *
     * @return an iterator over the sublist
     */
    public Iterator<E> iterator()
    {
      return listIterator();
    }
    
    /**
     * Specified by AbstractList.subList to return a wrapper around the
     * backing list's iterator.
     *
     * @param index the start location of the iterator
     * @return a list iterator over the sublist
     * @throws ConcurrentModificationException if the backing list has been
     *         modified externally to this sublist
     * @throws IndexOutOfBoundsException if the value is out of range
     */
    public ListIterator<E> listIterator(final int index)
    {
      checkMod();
      checkBoundsInclusive(index);

      return new ListIterator<E>()
      {
        private final ListIterator<E> i =
          backingList.listIterator(index + offset);
        private int position = index;

        /**
         * Tests to see if there are any more objects to
         * return.
         *
         * @return True if the end of the list has not yet been
         *         reached.
         */
        public boolean hasNext()
        {
          return position < size;
        }

        /**
         * Tests to see if there are objects prior to the
         * current position in the list.
         *
         * @return True if objects exist prior to the current
         *         position of the iterator.
         */
        public boolean hasPrevious()
        {
          return position > 0;
        }

        /**
         * Retrieves the next object from the list.
         *
         * @return The next object.
         * @throws NoSuchElementException if there are no
         *         more objects to retrieve.
         * @throws ConcurrentModificationException if the
         *         list has been modified elsewhere.
         */
        public E next()
        {
          if (position == size)
            throw new NoSuchElementException();
          position++;
          return i.next();
        }

        /**
         * Retrieves the previous object from the list.
         *
         * @return The next object.
         * @throws NoSuchElementException if there are no
         *         previous objects to retrieve.
         * @throws ConcurrentModificationException if the
         *         list has been modified elsewhere.
         */
        public E previous()
        {
          if (position == 0)
            throw new NoSuchElementException();
          position--;
          return i.previous();
        }

        /**
         * Returns the index of the next element in the
         * list, which will be retrieved by <code>next()</code>
         *
         * @return The index of the next element.
         */
        public int nextIndex()
        {
          return i.nextIndex() - offset;
        }

        /**
         * Returns the index of the previous element in the
         * list, which will be retrieved by <code>previous()</code>
         *
         * @return The index of the previous element.
         */
        public int previousIndex()
        {
          return i.previousIndex() - offset;
        }

        /**
         * Removes the last object retrieved by <code>next()</code>
         * from the list, if the list supports object removal.
         *
         * @throws IllegalStateException if the iterator is positioned
         *         before the start of the list or the last object has already
         *         been removed.
         * @throws UnsupportedOperationException if the list does
         *         not support removing elements.
         */
        public void remove()
        {
          throw new UnsupportedOperationException("Modification not supported " +
              "on CopyOnWriteArrayList iterators");
        }

        /**
         * Replaces the last object retrieved by <code>next()</code>
         * or <code>previous</code> with o, if the list supports object
         * replacement and an add or remove operation has not already
         * been performed.
         *
         * @throws IllegalStateException if the iterator is positioned
         *         before the start of the list or the last object has already
         *         been removed.
         * @throws UnsupportedOperationException if the list doesn't support
         *         the addition or removal of elements.
         * @throws ClassCastException if the type of o is not a valid type
         *         for this list.
         * @throws IllegalArgumentException if something else related to o
         *         prevents its addition.
         * @throws ConcurrentModificationException if the list
         *         has been modified elsewhere.
         */
        public void set(E o)
        {
          throw new UnsupportedOperationException("Modification not supported " +
              "on CopyOnWriteArrayList iterators");
        }

        /**
         * Adds the supplied object before the element that would be returned
         * by a call to <code>next()</code>, if the list supports addition.
         * 
         * @param o The object to add to the list.
         * @throws UnsupportedOperationException if the list doesn't support
         *         the addition of new elements.
         * @throws ClassCastException if the type of o is not a valid type
         *         for this list.
         * @throws IllegalArgumentException if something else related to o
         *         prevents its addition.
         * @throws ConcurrentModificationException if the list
         *         has been modified elsewhere.
         */
        public void add(E o)
        {
          throw new UnsupportedOperationException("Modification not supported " +
              "on CopyOnWriteArrayList iterators");
        } 
      };
    }
  } // class SubList

  /**
   * This class is a RandomAccess version of SubList, as required by
   * {@link AbstractList#subList(int, int)}.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class RandomAccessSubList<E> extends SubList<E>
    implements RandomAccess
  {
    /**
     * Construct the sublist.
     *
     * @param backing the list this comes from
     * @param fromIndex the lower bound, inclusive
     * @param toIndex the upper bound, exclusive
     */
    RandomAccessSubList(CopyOnWriteArrayList<E> backing, int fromIndex, int toIndex)
    {
      super(backing, fromIndex, toIndex);
    }
  } // class RandomAccessSubList

  /**
   * Serializes this object to the given stream.
   * 
   * @param s
   *          the stream to write to
   * @throws IOException
   *           if the underlying stream fails
   * @serialData the size field (int), the length of the backing array (int),
   *             followed by its elements (Objects) in proper order.
   */
  private void writeObject(ObjectOutputStream s) throws IOException
  {
    // The 'size' field.
    s.defaultWriteObject();
    // We serialize unused list entries to preserve capacity.
    int len = data.length;
    s.writeInt(len);
    // it would be more efficient to just write "size" items,
    // this need readObject read "size" items too.
    for (int i = 0; i < data.length; i++)
      s.writeObject(data[i]);
  }

  /**
   * Deserializes this object from the given stream.
   * 
   * @param s
   *          the stream to read from
   * @throws ClassNotFoundException
   *           if the underlying stream fails
   * @throws IOException
   *           if the underlying stream fails
   * @serialData the size field (int), the length of the backing array (int),
   *             followed by its elements (Objects) in proper order.
   */
  private void readObject(ObjectInputStream s) throws IOException,
      ClassNotFoundException
  {
    // the `size' field.
    s.defaultReadObject();
    int capacity = s.readInt();
    data = (E[]) new Object[capacity];
    for (int i = 0; i < capacity; i++)
      data[i] = (E) s.readObject();
  }

  static final boolean equals(Object o1, Object o2)
  {
    return o1 == null ? o2 == null : o1.equals(o2);
  }
  
  Object[] getArray()
  {
    return data;
  }
}
