ca.odell.glazedlists.TransformedList Maven / Gradle / Ivy
Show all versions of glazedlists_java15 Show documentation
/* 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 extends E> 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);
}
}