/*
Copyright (C) 2006 EBI
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the itmplied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.biomart.common.utils;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Iterator;
/**
* This class wraps an existing collection, and causes
* {@link PropertyChangeEvent} events to be fired whenever it changes.
* <p>
* Adding objects to the collection will result in events where the before value
* is null and the after value is the value being added.
* <p>
* Removing them will result in events where the before value is they value
* being removed and the after value is null.
* <p>
* Multiple add/remove events will have both before and after values of null.
* <p>
* All events will have a property of {@link BeanCollection#propertyName}.
*
* @author Richard Holland <holland@ebi.ac.uk>
* @version $Revision: 1.4 $, $Date: 2007-10-31 10:32:56 $, modified by
* $Author: rh4 $
* @since 0.7
*/
public class BeanCollection extends WeakPropertyChangeSupport implements Collection {
private static final long serialVersionUID = 1L;
/**
* This field is for use by subclasses which need to access the delegate
* directly.
*/
protected final Collection delegate;
/**
* The property key used in events generated by this map.
*/
public static final String propertyName = "CollectionEntry";
/**
* Construct a new instance that wraps the delegate collection and produces
* {@link PropertyChangeEvent} events whenever the delegate collection
* changes.
*
* @param delegate
* the delegate collection.
*/
public BeanCollection(final Collection delegate) {
super(delegate);
this.delegate = delegate;
}
/**
* Construct a new instance that wraps the delegate collection and produces
* {@link PropertyChangeEvent} events whenever the delegate collection
* changes.
* <p>
* As the delegate is a {@link BeanCollection} instance, it doesn't wrap the
* collection directly, instead it finds out the delegate's delegate and
* wraps that instead. It will also notify all listeners that are already
* listening to the delegate.
*
* @param delegate
* the delegate collection.
*/
public BeanCollection(final BeanCollection delegate) {
this(delegate.delegate);
final PropertyChangeListener[] listeners = delegate
.getPropertyChangeListeners();
for (int i = 0; i < listeners.length; i++)
this.addPropertyChangeListener(listeners[i]);
}
public boolean add(final Object arg0) {
final boolean result = this.delegate.add(arg0);
if (result)
this.firePropertyChange(BeanCollection.propertyName, null, arg0);
return result;
}
public boolean addAll(final Collection arg0) {
final boolean result = this.delegate.addAll(arg0);
if (result)
this.firePropertyChange(BeanCollection.propertyName, null, null);
return result;
}
public void clear() {
this.delegate.clear();
this.firePropertyChange(BeanCollection.propertyName, null, null);
}
public boolean contains(final Object o) {
return this.delegate.contains(o);
}
public boolean containsAll(final Collection arg0) {
return this.delegate.containsAll(arg0);
}
public boolean isEmpty() {
return this.delegate.isEmpty();
}
private final PropertyChangeListener iteratorListener = new PropertyChangeListener() {
public void propertyChange(final PropertyChangeEvent evt) {
BeanCollection.this.firePropertyChange(
BeanCollection.propertyName, evt.getOldValue(), evt
.getNewValue());
}
};
public Iterator iterator() {
// Wrap the entry set in a BeanIterator.
final BeanIterator beanIterator = new BeanIterator(this.delegate
.iterator());
// Add a PropertyChangeListener to the BeanSet
// which fires events as if they came from us.
beanIterator.addPropertyChangeListener(this.iteratorListener);
// Return the wrapped entry set.
return beanIterator;
}
public boolean remove(final Object o) {
final boolean result = this.delegate.remove(o);
if (result)
this.firePropertyChange(BeanCollection.propertyName, o, null);
return result;
}
public boolean removeAll(final Collection arg0) {
final boolean result = this.delegate.removeAll(arg0);
if (result)
this.firePropertyChange(BeanCollection.propertyName, null, null);
return result;
}
public boolean retainAll(final Collection arg0) {
final boolean result = this.delegate.retainAll(arg0);
if (result)
this.firePropertyChange(BeanCollection.propertyName, null, null);
return result;
}
public int size() {
return this.delegate.size();
}
public Object[] toArray() {
return this.delegate.toArray();
}
public Object[] toArray(final Object[] arg0) {
return this.delegate.toArray(arg0);
}
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
public boolean equals(final Object obj) {
if (obj == this)
return true;
else if (obj instanceof BeanCollection)
return this.delegate.equals(((BeanCollection) obj).delegate);
else if (obj instanceof Collection)
return this.delegate.equals(obj);
else
return false;
}
public int hashCode() {
return this.delegate.hashCode();
}
public String toString() {
return this.delegate.toString();
}
}