/* 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(); } }