/*
* @(#)AbstractCollection.java 1.24 03/01/18
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package instrumented.java.util;
/**
* This class provides a skeletal implementation of the <tt>Collection</tt>
* interface, to minimize the effort required to implement this interface. <p>
*
* To implement an unmodifiable collection, the programmer needs only to
* extend this class and provide implementations for the <tt>iterator</tt> and
* <tt>size</tt> methods. (The iterator returned by the <tt>iterator</tt>
* method must implement <tt>hasNext</tt> and <tt>next</tt>.)<p>
*
* To implement a modifiable collection, the programmer must additionally
* override this class's <tt>add</tt> method (which otherwise throws an
* <tt>UnsupportedOperationException</tt>), and the iterator returned by the
* <tt>iterator</tt> method must additionally implement its <tt>remove</tt>
* method.<p>
*
* The programmer should generally provide a void (no argument) and
* <tt>Collection</tt> constructor, as per the recommendation in the
* <tt>Collection</tt> interface specification.<p>
*
* The documentation for each non-abstract methods in this class describes its
* implementation in detail. Each of these methods may be overridden if
* the collection being implemented admits a more efficient implementation.<p>
*
* This class is a member of the
* <a href="{@docRoot}/../guide/collections/index.html">
* Java Collections Framework</a>.
*
* @author Josh Bloch
* @version 1.24, 01/18/03
* @see Collection
* @since 1.2
*/
public abstract class AbstractCollection implements Collection {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractCollection() {
}
// Query Operations
/**
* Returns an iterator over the elements contained in this collection.
*
* @return an iterator over the elements contained in this collection.
*/
public abstract Iterator iterator();
/**
* Returns the number of elements in this collection. If the collection
* contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
*
* @return the number of elements in this collection.
*/
public abstract int size();
/**
* Returns <tt>true</tt> if this collection contains no elements.<p>
*
* This implementation returns <tt>size() == 0</tt>.
*
* @return <tt>true</tt> if this collection contains no elements.
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* Returns <tt>true</tt> if this collection contains the specified
* element. More formally, returns <tt>true</tt> if and only if this
* collection contains at least one element <tt>e</tt> such that
* <tt>(o==null ? e==null : o.equals(e))</tt>.<p>
*
* This implementation iterates over the elements in the collection,
* checking each element in turn for equality with the specified element.
*
* @param o object to be checked for containment in this collection.
* @return <tt>true</tt> if this collection contains the specified element.
*/
public boolean contains(Object o) {
Iterator e = iterator();
if (o==null) {
while (e.hasNext())
if (e.next()==null)
return true;
} else {
while (e.hasNext())
if (o.equals(e.next()))
return true;
}
return false;
}
/**
* Returns an array containing all of the elements in this collection. If
* the collection makes any guarantees as to what order its elements are
* returned by its iterator, this method must return the elements in the
* same order. The returned array will be "safe" in that no references to
* it are maintained by the collection. (In other words, this method must
* allocate a new array even if the collection is backed by an Array).
* The caller is thus free to modify the returned array.<p>
*
* This implementation allocates the array to be returned, and iterates
* over the elements in the collection, storing each object reference in
* the next consecutive element of the array, starting with element 0.
*
* @return an array containing all of the elements in this collection.
*/
public Object[] toArray() {
Object[] result = new Object[size()];
Iterator e = iterator();
for (int i=0; e.hasNext(); i++)
result[i] = e.next();
return result;
}
/**
* Returns an array containing all of the elements in this collection;
* the runtime type of the returned array is that of the specified array.
* If the collection fits in the specified array, it is returned therein.
* Otherwise, a new array is allocated with the runtime type of the
* specified array and the size of this collection.<p>
*
* If the collection fits in the specified array with room to spare (i.e.,
* the array has more elements than the collection), the element in the
* array immediately following the end of the collection is set to
* <tt>null</tt>. This is useful in determining the length of the
* collection <i>only</i> if the caller knows that the collection does
* not contain any <tt>null</tt> elements.)<p>
*
* If this collection makes any guarantees as to what order its elements
* are returned by its iterator, this method must return the elements in
* the same order. <p>
*
* This implementation checks if the array is large enough to contain the
* collection; if not, it allocates a new array of the correct size and
* type (using reflection). Then, it iterates over the collection,
* storing each object reference in the next consecutive element of the
* array, starting with element 0. If the array is larger than the
* collection, a <tt>null</tt> is stored in the first location after the
* end of the collection.
*
* @param a the array into which the elements of the collection are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose.
* @return an array containing the elements of the collection.
*
* @throws NullPointerException if the specified array is <tt>null</tt>.
*
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in this
* collection.
*/
public Object[] toArray(Object a[]) {
int size = size();
if (a.length < size)
a = (Object[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
Iterator it=iterator();
for (int i=0; i<size; i++)
a[i] = it.next();
if (a.length > size)
a[size] = null;
return a;
}
// Modification Operations
/**
* Ensures that this collection contains the specified element (optional
* operation). Returns <tt>true</tt> if the collection changed as a
* result of the call. (Returns <tt>false</tt> if this collection does
* not permit duplicates and already contains the specified element.)
* Collections that support this operation may place limitations on what
* elements may be added to the collection. In particular, some
* collections will refuse to add <tt>null</tt> elements, and others will
* impose restrictions on the type of elements that may be added.
* Collection classes should clearly specify in their documentation any
* restrictions on what elements may be added.<p>
*
* This implementation always throws an
* <tt>UnsupportedOperationException</tt>.
*
* @param o element whose presence in this collection is to be ensured.
* @return <tt>true</tt> if the collection changed as a result of the call.
*
* @throws UnsupportedOperationException if the <tt>add</tt> method is not
* supported by this collection.
*
* @throws NullPointerException if this collection does not permit
* <tt>null</tt> elements, and the specified element is
* <tt>null</tt>.
*
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this collection.
*
* @throws IllegalArgumentException if some aspect of this element
* prevents it from being added to this collection.
*/
public boolean add(Object o) {
throw new UnsupportedOperationException();
}
/**
* Removes a single instance of the specified element from this
* collection, if it is present (optional operation). More formally,
* removes an element <tt>e</tt> such that <tt>(o==null ? e==null :
* o.equals(e))</tt>, if the collection contains one or more such
* elements. Returns <tt>true</tt> if the collection contained the
* specified element (or equivalently, if the collection changed as a
* result of the call).<p>
*
* This implementation iterates over the collection looking for the
* specified element. If it finds the element, it removes the element
* from the collection using the iterator's remove method.<p>
*
* Note that this implementation throws an
* <tt>UnsupportedOperationException</tt> if the iterator returned by this
* collection's iterator method does not implement the <tt>remove</tt>
* method and this collection contains the specified object.
*
* @param o element to be removed from this collection, if present.
* @return <tt>true</tt> if the collection contained the specified
* element.
* @throws UnsupportedOperationException if the <tt>remove</tt> method is
* not supported by this collection.
*/
public boolean remove(Object o) {
Iterator e = iterator();
if (o==null) {
while (e.hasNext()) {
if (e.next()==null) {
e.remove();
return true;
}
}
} else {
while (e.hasNext()) {
if (o.equals(e.next())) {
e.remove();
return true;
}
}
}
return false;
}
// Bulk Operations
/**
* Returns <tt>true</tt> if this collection contains all of the elements
* in the specified collection. <p>
*
* This implementation iterates over the specified collection, checking
* each element returned by the iterator in turn to see if it's
* contained in this collection. If all elements are so contained
* <tt>true</tt> is returned, otherwise <tt>false</tt>.
*
* @param c collection to be checked for containment in this collection.
* @return <tt>true</tt> if this collection contains all of the elements
* in the specified collection.
* @throws NullPointerException if the specified collection is null.
*
* @see #contains(Object)
*/
public boolean containsAll(Collection c) {
Iterator e = c.iterator();
while (e.hasNext())
if(!contains(e.next()))
return false;
return true;
}
/**
* Adds all of the elements in the specified collection to this collection
* (optional operation). The behavior of this operation is undefined if
* the specified collection is modified while the operation is in
* progress. (This implies that the behavior of this call is undefined if
* the specified collection is this collection, and this collection is
* nonempty.) <p>
*
* This implementation iterates over the specified collection, and adds
* each object returned by the iterator to this collection, in turn.<p>
*
* Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> unless <tt>add</tt> is
* overridden (assuming the specified collection is non-empty).
*
* @param c collection whose elements are to be added to this collection.
* @return <tt>true</tt> if this collection changed as a result of the
* call.
* @throws UnsupportedOperationException if this collection does not
* support the <tt>addAll</tt> method.
* @throws NullPointerException if the specified collection is null.
*
* @see #add(Object)
*/
public boolean addAll(Collection c) {
boolean modified = false;
Iterator e = c.iterator();
while (e.hasNext()) {
if(add(e.next()))
modified = true;
}
return modified;
}
/**
* Removes from this collection all of its elements that are contained in
* the specified collection (optional operation). <p>
*
* This implementation iterates over this collection, checking each
* element returned by the iterator in turn to see if it's contained
* in the specified collection. If it's so contained, it's removed from
* this collection with the iterator's <tt>remove</tt> method.<p>
*
* Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by the
* <tt>iterator</tt> method does not implement the <tt>remove</tt> method
* and this collection contains one or more elements in common with the
* specified collection.
*
* @param c elements to be removed from this collection.
* @return <tt>true</tt> if this collection changed as a result of the
* call.
* @throws UnsupportedOperationException if the <tt>removeAll</tt> method
* is not supported by this collection.
* @throws NullPointerException if the specified collection is null.
*
* @see #remove(Object)
* @see #contains(Object)
*/
public boolean removeAll(Collection c) {
boolean modified = false;
Iterator e = iterator();
while (e.hasNext()) {
if(c.contains(e.next())) {
e.remove();
modified = true;
}
}
return modified;
}
/**
* Retains only the elements in this collection that are contained in the
* specified collection (optional operation). In other words, removes
* from this collection all of its elements that are not contained in the
* specified collection. <p>
*
* This implementation iterates over this collection, checking each
* element returned by the iterator in turn to see if it's contained
* in the specified collection. If it's not so contained, it's removed
* from this collection with the iterator's <tt>remove</tt> method.<p>
*
* Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by the
* <tt>iterator</tt> method does not implement the <tt>remove</tt> method
* and this collection contains one or more elements not present in the
* specified collection.
*
* @param c elements to be retained in this collection.
* @return <tt>true</tt> if this collection changed as a result of the
* call.
* @throws UnsupportedOperationException if the <tt>retainAll</tt> method
* is not supported by this Collection.
* @throws NullPointerException if the specified collection is null.
*
* @see #remove(Object)
* @see #contains(Object)
*/
public boolean retainAll(Collection c) {
boolean modified = false;
Iterator e = iterator();
while (e.hasNext()) {
if(!c.contains(e.next())) {
e.remove();
modified = true;
}
}
return modified;
}
/**
* Removes all of the elements from this collection (optional operation).
* The collection will be empty after this call returns (unless it throws
* an exception).<p>
*
* This implementation iterates over this collection, removing each
* element using the <tt>Iterator.remove</tt> operation. Most
* implementations will probably choose to override this method for
* efficiency.<p>
*
* Note that this implementation will throw an
* <tt>UnsupportedOperationException</tt> if the iterator returned by this
* collection's <tt>iterator</tt> method does not implement the
* <tt>remove</tt> method and this collection is non-empty.
*
* @throws UnsupportedOperationException if the <tt>clear</tt> method is
* not supported by this collection.
*/
public void clear() {
Iterator e = iterator();
while (e.hasNext()) {
e.next();
e.remove();
}
}
// String conversion
/**
* Returns a string representation of this collection. The string
* representation consists of a list of the collection's elements in the
* order they are returned by its iterator, enclosed in square brackets
* (<tt>"[]"</tt>). Adjacent elements are separated by the characters
* <tt>", "</tt> (comma and space). Elements are converted to strings as
* by <tt>String.valueOf(Object)</tt>.<p>
*
* This implementation creates an empty string buffer, appends a left
* square bracket, and iterates over the collection appending the string
* representation of each element in turn. After appending each element
* except the last, the string <tt>", "</tt> is appended. Finally a right
* bracket is appended. A string is obtained from the string buffer, and
* returned.
*
* @return a string representation of this collection.
*/
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("[");
Iterator i = iterator();
boolean hasNext = i.hasNext();
while (hasNext) {
Object o = i.next();
buf.append(o == this ? "(this Collection)" : String.valueOf(o));
hasNext = i.hasNext();
if (hasNext)
buf.append(", ");
}
buf.append("]");
return buf.toString();
}
}