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

ca.odell.glazedlists.TransformedList Maven / Gradle / Ivy

The newest version!
/* Glazed Lists                                                 (c) 2003-2006 */
/* http://publicobject.com/glazedlists/                      publicobject.com,*/
/*                                                     O'Dell Engineering Ltd.*/
package ca.odell.glazedlists;

// the Glazed Lists' change objects
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;

import java.util.Collection;

/**
 * A convenience class for {@link EventList}s that decorate another {@link EventList}.
 * Extending classes transform their source {@link EventList} by modifying the
 * order, visibility and value of its elements.
 *
 * 

Extending classes may implement the method {@link #getSourceIndex(int)} to * translate between indices of this and indices of the source. * *

Extending classes may implement the method {@link #isWritable()} to make the * source writable via this API. * *

Extending classes must explicitly call {@link #addListEventListener(ListEventListener)} * to receive change notifications from the source {@link EventList}. * *

Warning: This class is * thread ready but not thread safe. See {@link EventList} for an example * of thread safe code. * * @author Jesse Wilson */ public abstract class TransformedList extends AbstractEventList implements ListEventListener { /** the event list to transform */ protected EventList source; /** * Creates a {@link TransformedList} to transform the specified {@link EventList}. * * @param source the {@link EventList} to transform */ protected TransformedList(EventList source) { super(source.getPublisher()); this.source = source; readWriteLock = source.getReadWriteLock(); } /** * Gets the index in the source {@link EventList} that corresponds to the * specified index. More formally, returns the index such that *
this.get(i) == source.get(getSourceIndex(i)) for all * legal values of i. */ protected int getSourceIndex(int mutationIndex) { return mutationIndex; } /** * Gets whether the source {@link EventList} is writable via this API. * *

Extending classes must override this method in order to make themselves * writable. */ protected abstract boolean isWritable(); /** {@inheritDoc} */ public abstract void listChanged(ListEvent listChanges); /** {@inheritDoc} */ @Override public void add(int index, E value) { if(!isWritable()) throw new IllegalStateException("Non-writable List cannot be modified"); if(index < 0 || index > size()) throw new IndexOutOfBoundsException("Cannot add at " + index + " on list of size " + size()); final int sourceIndex = index < size() ? getSourceIndex(index) : source.size(); source.add(sourceIndex, (S) value); } /** {@inheritDoc} */ @Override public boolean addAll(int index, Collection values) { // nest changes and let the other methods compose the event updates.beginEvent(true); try { return super.addAll(index, values); } finally { updates.commitEvent(); } } /** {@inheritDoc} */ @Override public void clear() { // nest changes and let the other methods compose the event updates.beginEvent(true); try { super.clear(); } finally { updates.commitEvent(); } } /** {@inheritDoc} */ @Override public E get(int index) { if(index < 0 || index >= size()) throw new IndexOutOfBoundsException("Cannot get at " + index + " on list of size " + size()); return (E) source.get(getSourceIndex(index)); } /** {@inheritDoc} */ @Override public E remove(int index) { if(!isWritable()) throw new IllegalStateException("Non-writable List cannot be modified"); if(index < 0 || index >= size()) throw new IndexOutOfBoundsException("Cannot remove at " + index + " on list of size " + size()); return (E) source.remove(getSourceIndex(index)); } /** {@inheritDoc} */ @Override public boolean removeAll(Collection collection) { // nest changes and let the other methods compose the event updates.beginEvent(true); try { return super.removeAll(collection); } finally { updates.commitEvent(); } } /** {@inheritDoc} */ @Override public boolean retainAll(Collection values) { // nest changes and let the other methods compose the event updates.beginEvent(true); try { return super.retainAll(values); } finally { updates.commitEvent(); } } /** {@inheritDoc} */ @Override public E set(int index, E value) { if(!isWritable()) throw new IllegalStateException("List " + this.getClass().getName() + " cannot be modified in the current state"); if(index < 0 || index >= size()) throw new IndexOutOfBoundsException("Cannot set at " + index + " on list of size " + size()); return (E) source.set(getSourceIndex(index), (S) value); } /** {@inheritDoc} */ @Override public int size() { return source.size(); } /** * Releases the resources consumed by this {@link TransformedList} so that it * may eventually be garbage collected. * *

A {@link TransformedList} will be garbage collected without a call to * {@link #dispose()}, but not before its source {@link EventList} is garbage * collected. By calling {@link #dispose()}, you allow the {@link TransformedList} * to be garbage collected before its source {@link EventList}. This is * necessary for situations where a {@link TransformedList} is short-lived but * its source {@link EventList} is long-lived. * *

Warning: It is an error * to call any method on a {@link TransformedList} after it has been disposed. */ public void dispose() { source.removeListEventListener(this); } }