//
// This file is part of the prose package.
//
// The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// The Original Code is prose.
//
// The Initial Developer of the Original Code is Angela Nicoara. Portions
// created by Angela Nicoara are Copyright (C) 2004 Angela Nicoara.
// All Rights Reserved.
//
// Contributor(s):
// $Id: WeakSet.java,v 1.2 2008/11/18 11:44:47 anicoara Exp $
// =====================================================================
//
package ch.ethz.prose;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.lang.ref.WeakReference;
/**
* Wrapper for a <CODE>Set</CODE> using weak references
* to store values. The refered objects may be garbage
* collected...
*
* @see java.util.Set
* @see java.lang.ref.WeakReference
*
* @version $Revision: 1.2 $
* @author Angela Nicoara
* @author Gerald Linhofer
*/
public class WeakSet implements Set {
/// The wrapped <CODE>Set</CODE>.
private Set realSet;
/**
* Default constructor uses a <CODE>HashSet</CODE>
* as set implementation.
*
*/
public WeakSet() {
realSet = new HashSet();
}
/**
* Constructor, which allows to pass the set implementation
* as parameter. The passed set may not be null and has to be
* empty.
*
* @param baseSet an empty set that will be used internal as
* set implementation.
*/
public WeakSet(Set baseSet) {
if(! baseSet.isEmpty())
throw new RuntimeException( this.getClass().getName() + " must be initialized with an empty Set");
realSet = baseSet;
}
//
// *** Forwarding methods *********************************
//
/* Returns the size of the set.
* @see java.util.Set#size()
*/
public int size() {
return realSet.size();
}
/* (non-Javadoc)
* @see java.util.Set#isEmpty()
*/
public boolean isEmpty() {
return realSet.isEmpty();
}
/* (non-Javadoc)
* @see java.util.Set#contains(java.lang.Object)
*/
public boolean contains(Object o) {
WeakReference wr = new WeakReference(o);
return realSet.contains(wr);
}
/**
* Returns an iterator over the elements in this set.
* The elements are returned in no particular order
* (unless this set uses an instance of some class that
* provides a guarantee).
*
* @return an iterator over the elements in this set.
*
* @see java.util.Set#iterator()
*/
public Iterator iterator() {
return new Iterator() {
private Iterator realIter = realSet.iterator();
public boolean hasNext() {
return realIter.hasNext();
}
public Object next() {
WeakReference wr = (WeakReference) realIter.next();
return wr.get();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/* (non-Javadoc)
* @see java.util.Set#toArray()
*/
public Object[] toArray() {
int i = 0;
Object[] retval = new Object[realSet.size()];
for( Iterator iter = iterator();
iter.hasNext();
retval[i++] = iter.next())
{}
return retval;
}
/* (non-Javadoc)
* @see java.util.Set#toArray(T[])
*/
public Object[] toArray(Object[] a) {
int i = 0;
for( Iterator iter = iterator();
iter.hasNext();
a[i++] = iter.next())
{}
return a;
}
/**
* Adds the specified element to this set if it is not
* already present (optional operation). More formally,
* adds the specified element, o, to this set if this
* set contains no element e such that (o==null ? e==null
* : o.equals(e)). If this set already contains the
* specified element, the call leaves this set unchanged
* and returns false. In combination with the restriction
* on constructors, this ensures that sets never contain
* duplicate elements.
*
* @see java.util.Set#add
*/
public boolean add(Object o) {
WeakReference wr = new WeakReference(o);
return realSet.add(wr);
}
/**
* Removes the specified element from this set if it is
* present (optional operation). More formally, removes
* an element e such that (o==null ? e==null : o.equals(e)),
* if the set contains such an element. Returns true if
* the set contained the specified element (or equivalently,
* if the set changed as a result of the call). (The set
* will not contain the specified element once the call
* returns.)
*
* @param o - object to be removed from this set, if present.
* @return <CODE>true</CODE> if the set contained the specified
* element.
*
* @throws ClassCastException if the type of the specified
* element is incompatible with this set (optional).
* @throws NullPointerException if the specified element is
* null and this set does not support null elements (optional).
* @throws UnsupportedOperationException if the remove method
* is not supported by the underlying set.
*
* @see java.util.Set#remove(java.lang.Object)
*/
public boolean remove(Object o) {
WeakReference wr = new WeakReference(o);
return realSet.remove(wr);
}
/**
* Returns true if this set contains all of the elements
* of the specified collection. If the specified collection
* is also a set, this method returns true if it is a
* subset of this set.
*
* @param c collection to be checked for containment in this set.
* @return <CODE>true</CODE> if this set contains all of the
* elements of the specified collection.
*
* @throws ClassCastException if the types of one or more elements
* in the specified collection are incompatible with this
* set (optional).
* @throws NullPointerException if the specified collection contains
* one or more null elements and this set does not support
* null elements (optional). Or if the specified collection
* is null.
*
* @see java.util.Set#containsAll(java.util.Collection)
*/
public boolean containsAll(Collection c) {
boolean retval = true;
for( Iterator iter = c.iterator();
iter.hasNext();
retval = retval && contains(iter.next()))
{}
return retval;
}
/**
* Adds all of the elements in the specified collection
* to this set if they're not already present.
*
* @param c Adds all of the elements in the specified
* collection to this set if they're not
* already present
* @return <CODE>true</CODE> if this set was changed during operation
*
* @throws ClassCastException if the class of some element of the specified collection prevents it from being added to this set.
* @throws NullPointerException if the specified collection contains one or more null elements and this set does not support null elements, or if the specified collection is null.
* @throws IllegalArgumentException if some aspect of some element of the specified collection prevents it from being added to this set.
*
* @see java.util.Set#addAll(java.util.Collection)
*/
public boolean addAll(Collection c) {
boolean retval = false;
for( Iterator iter = c.iterator();
iter.hasNext();
retval = retval || add(iter.next()))
{}
return retval;
}
/**
* Not implemented.
*
* @see java.util.Set#retainAll(java.util.Collection)
*/
public boolean retainAll(Collection c) {
throw new UnsupportedOperationException();
}
/** Not implemented.
*
* @see java.util.Set#removeAll(java.util.Collection)
*/
public boolean removeAll(Collection c) {
throw new UnsupportedOperationException();
}
/* (non-Javadoc)
* @see java.util.Set#clear()
*/
public void clear() {
realSet.clear();
}
/**
* WeakReference implementation for WeakSet
* @author Gerald Linhofer
*
*/
private class SetReference extends WeakReference {
SetReference(Object o) {
super(o);
}
public void clear() {
super.clear();
realSet.remove(this);
}
}
}