All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 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;
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy