package edu.ualberta.med.biobank.common.util; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public class DelegatingList<E> extends AbstractListChangeSource<E> implements List<E> { private final ModifierChangeHandler modifierChangeHandler = new ModifierChangeHandler(); private final List<ListChangeSource<E>> modifiers = new ArrayList<ListChangeSource<E>>(); private List<E> delegate; public DelegatingList() { this(new ArrayList<E>()); } public DelegatingList(List<E> delegate) { setDelegate(delegate); } public void setDelegate(List<E> delegate) { if (delegate == null) { throw new IllegalArgumentException("delegate is required"); //$NON-NLS-1$ } // no need to delegate to ourselves or reset the delegate if (this == delegate || this.delegate == delegate) { return; } clearModifiers(); this.delegate = delegate; fireListChangeEvent(); } @Override public boolean add(E e) { boolean result = delegate.add(e); fireListChangeEvent(); return result; } @Override public void add(int index, E element) { delegate.add(index, element); fireListChangeEvent(); } @Override public boolean addAll(Collection<? extends E> c) { boolean changed = delegate.addAll(c); fireListChangeEvent(); return changed; } @Override public boolean addAll(int index, Collection<? extends E> c) { boolean changed = delegate.addAll(index, c); fireListChangeEvent(); return changed; } @Override public void clear() { delegate.clear(); fireListChangeEvent(); } @Override public boolean contains(Object o) { return delegate.contains(o); } @Override public boolean containsAll(Collection<?> c) { return delegate.containsAll(c); } @Override public E get(int index) { return delegate.get(index); } @Override public int indexOf(Object o) { return delegate.indexOf(o); } @Override public boolean isEmpty() { return delegate.isEmpty(); } @Override public Iterator<E> iterator() { ListChangeSourceIterator<E> iterator = new ListChangeSourceIterator<E>( delegate.iterator()); iterator.addListChangeHandler(modifierChangeHandler); modifiers.add(iterator); return iterator; } @Override public int lastIndexOf(Object o) { return delegate.lastIndexOf(o); } @Override public ListIterator<E> listIterator() { ListChangeSourceListIterator<E> iterator = new ListChangeSourceListIterator<E>( delegate.listIterator()); iterator.addListChangeHandler(modifierChangeHandler); modifiers.add(iterator); return iterator; } @Override public ListIterator<E> listIterator(int index) { ListChangeSourceListIterator<E> iterator = new ListChangeSourceListIterator<E>( delegate.listIterator(index)); iterator.addListChangeHandler(modifierChangeHandler); modifiers.add(iterator); return iterator; } @Override public boolean remove(Object o) { boolean changed = delegate.remove(o); fireListChangeEvent(); return changed; } @Override public E remove(int index) { E removed = delegate.remove(index); fireListChangeEvent(); return removed; } @Override public boolean removeAll(Collection<?> c) { boolean changed = delegate.removeAll(c); fireListChangeEvent(); return changed; } @Override public boolean retainAll(Collection<?> c) { boolean changed = delegate.retainAll(c); fireListChangeEvent(); return changed; } @Override public E set(int index, E element) { E previous = delegate.set(index, element); fireListChangeEvent(); return previous; } @Override public int size() { return delegate.size(); } @Override public List<E> subList(int fromIndex, int toIndex) { List<E> view = delegate.subList(fromIndex, toIndex); DelegatingList<E> delegatingView = new DelegatingList<E>(view); delegatingView.addListChangeHandler(modifierChangeHandler); modifiers.add(delegatingView); return delegatingView; } @Override public Object[] toArray() { return delegate.toArray(); } @Override public <T> T[] toArray(T[] a) { return delegate.toArray(a); } private static class ListChangeSourceIterator<E> extends AbstractListChangeSource<E> implements Iterator<E> { private final Iterator<E> iterator; private ListChangeSourceIterator(Iterator<E> iterator) { this.iterator = iterator; } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public E next() { return iterator.next(); } @Override public void remove() { iterator.remove(); fireListChangeEvent(); } } private static class ListChangeSourceListIterator<E> extends AbstractListChangeSource<E> implements ListIterator<E> { private final ListIterator<E> iterator; private ListChangeSourceListIterator(ListIterator<E> iterator) { this.iterator = iterator; } @Override public void add(E e) { iterator.add(e); fireListChangeEvent(); } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public boolean hasPrevious() { return iterator.hasPrevious(); } @Override public E next() { return iterator.next(); } @Override public int nextIndex() { return iterator.nextIndex(); } @Override public E previous() { return iterator.previous(); } @Override public int previousIndex() { return iterator.previousIndex(); } @Override public void remove() { iterator.remove(); fireListChangeEvent(); } @Override public void set(E e) { iterator.set(e); fireListChangeEvent(); } } private void clearModifiers() { for (ListChangeSource<E> modifier : modifiers) { modifier.removeListChangeHandler(modifierChangeHandler); } modifiers.clear(); } private class ModifierChangeHandler implements ListChangeHandler<E> { @Override public void onListChange(ListChangeEvent<E> event) { fireListChangeEvent(); } } }