net.sf.jcommon.collect.ObservableCollection Maven / Gradle / Ivy
package net.sf.jcommon.collect;
import java.util.*;
import com.google.common.collect.ForwardingCollection;
import com.google.common.collect.ForwardingIterator;
/** A collection that decorates another collection
* and triggers {@link CollectionListener}'s for every change.
* @see CollectionEvent
*/
public class ObservableCollection extends ForwardingCollection {
/** An iterator that decorates another iterator and
* triggers {@link CollectionListener}'s every time an element is removed.
* The triggered listeners are the ones from the enclosing collection.
*/
protected class ObservableIterator extends ForwardingIterator {
/** The underlying iterator. */
private Iterator decorated;
/** The current element. */
protected E current;
public ObservableIterator(Iterator decorated) {
this.decorated = decorated;
}
@Override
protected Iterator delegate() {
return decorated;
}
@Override
public E next() {
current = delegate().next();
return current;
}
@Override
public void remove() {
CollectionEvent evt = new CollectionEvent(ObservableCollection.this, current, CollectionEvent.Operation.REMOVE);
firePreEvent(evt);
delegate().remove();
firePostEvent(evt);
}
}
/** The underlying collection. */
private Collection decorated;
/** The listeners that needs to be triggered for every change. */
private Collection> listeners = new ArrayList>();
/** Creates a new collection by decorating the given collection. */
public ObservableCollection(Collection decorated) {
this.decorated = decorated;
}
@Override
protected Collection delegate() {
return decorated;
}
protected void firePreEvent(CollectionEvent evt) {
for (CollectionListener listener : listeners) {
listener.pre(evt);
}
}
protected void firePostEvent(CollectionEvent evt) {
for (CollectionListener listener : listeners) {
listener.post(evt);
}
}
public void addCollectionListener(CollectionListener listener) {
listeners.add(listener);
}
public void removeCollectionListener(CollectionListener listener) {
listeners.remove(listener);
}
public boolean add(E e) {
CollectionEvent evt = new CollectionEvent(this, e, CollectionEvent.Operation.ADD);
firePreEvent(evt);
if (delegate().add(e)) {
firePostEvent(evt);
return true;
}
return false;
}
public boolean addAll(Collection extends E> c) {
CollectionEvent evt = new CollectionEvent(this, c, CollectionEvent.Operation.ADD);
firePreEvent(evt);
if (delegate().addAll(c)) {
firePostEvent(evt);
return true;
}
return false;
}
public void clear() {
CollectionEvent evt = new CollectionEvent(this, CollectionEvent.Operation.CLEAR);
firePreEvent(evt);
delegate().clear();
firePostEvent(evt);
}
public Iterator iterator() {
return new ObservableIterator(delegate().iterator());
}
@SuppressWarnings("unchecked")
public boolean remove(Object e) {
CollectionEvent evt = new CollectionEvent(this, (E)e, CollectionEvent.Operation.REMOVE);
firePreEvent(evt);
boolean retval = delegate().remove(e);
if (retval)
firePostEvent(evt);
return retval;
}
@SuppressWarnings("unchecked")
public boolean removeAll(Collection> c) {
CollectionEvent evt = new CollectionEvent(this, (Collection)c, CollectionEvent.Operation.REMOVE);
firePreEvent(evt);
boolean retval = delegate().removeAll(c);
if (retval)
firePostEvent(evt);
return retval;
}
public boolean retainAll(Collection> c) {
Collection toRemove = new HashSet();
for (E e : delegate()) {
if (!c.contains(e)) {
toRemove.add(e);
}
}
CollectionEvent evt = new CollectionEvent(this, toRemove, CollectionEvent.Operation.REMOVE);
firePreEvent(evt);
boolean retval = delegate().retainAll(c);
if (retval)
firePostEvent(evt);
return retval;
}
}