| /******************************************************************************* |
| * Copyright (c) 2007, 2009 Oracle. All rights reserved. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v1.0, which accompanies this distribution |
| * and is available at http://www.eclipse.org/legal/epl-v10.html. |
| * |
| * Contributors: |
| * Oracle - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.jpt.utility.internal.model.value; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.ListIterator; |
| |
| import org.eclipse.jpt.utility.internal.CollectionTools; |
| import org.eclipse.jpt.utility.internal.model.AbstractModel; |
| import org.eclipse.jpt.utility.internal.model.ChangeSupport; |
| import org.eclipse.jpt.utility.internal.model.SingleAspectChangeSupport; |
| import org.eclipse.jpt.utility.model.listener.ListChangeListener; |
| import org.eclipse.jpt.utility.model.value.ListValueModel; |
| import org.eclipse.jpt.utility.model.value.WritableListValueModel; |
| |
| /** |
| * Implementation of {@link ListValueModel} and {@link List} that simply holds a |
| * list and notifies listeners of any changes. |
| */ |
| public class SimpleListValueModel<E> |
| extends AbstractModel |
| implements WritableListValueModel<E>, List<E> |
| { |
| /** The list. */ |
| protected List<E> list; |
| |
| |
| // ********** constructors ********** |
| |
| /** |
| * Construct a list value model for the specified list. |
| */ |
| public SimpleListValueModel(List<E> list) { |
| super(); |
| if (list == null) { |
| throw new NullPointerException(); |
| } |
| this.list = list; |
| } |
| |
| /** |
| * Construct a list value model with an empty initial list. |
| */ |
| public SimpleListValueModel() { |
| this(new ArrayList<E>()); |
| } |
| |
| @Override |
| protected ChangeSupport buildChangeSupport() { |
| return new SingleAspectChangeSupport(this, ListChangeListener.class, LIST_VALUES); |
| } |
| |
| |
| // ********** ListValueModel implementation ********** |
| |
| public Iterator<E> iterator() { |
| return new LocalIterator<E>(this.list.iterator()); |
| } |
| |
| public ListIterator<E> listIterator() { |
| return new LocalListIterator<E>(this.list.listIterator()); |
| } |
| |
| public int size() { |
| return this.list.size(); |
| } |
| |
| public E get(int index) { |
| return this.list.get(index); |
| } |
| |
| |
| // ********** WritableListValueModel implementation ********** |
| |
| /** |
| * Allow the list's elements to be replaced. |
| */ |
| public void setListValues(Iterable<E> list) { |
| if (list == null) { |
| throw new NullPointerException(); |
| } |
| this.list.clear(); |
| CollectionTools.addAll(this.list, list); |
| this.fireListChanged(LIST_VALUES, this.list); |
| } |
| |
| |
| // ********** List implementation ********** |
| |
| public boolean isEmpty() { |
| return this.list.isEmpty(); |
| } |
| |
| public boolean contains(Object o) { |
| return this.list.contains(o); |
| } |
| |
| public Object[] toArray() { |
| return this.list.toArray(); |
| } |
| |
| public <T extends Object> T[] toArray(T[] a) { |
| return this.list.toArray(a); |
| } |
| |
| public boolean add(E o) { |
| return this.addItemToList(o, this.list, LIST_VALUES); |
| } |
| |
| public boolean remove(Object o) { |
| return this.removeItemFromList(o, this.list, LIST_VALUES); |
| } |
| |
| public boolean containsAll(Collection<?> c) { |
| return this.list.containsAll(c); |
| } |
| |
| public boolean addAll(Collection<? extends E> c) { |
| return this.addItemsToList(c, this.list, LIST_VALUES); |
| } |
| |
| public boolean addAll(int index, Collection<? extends E> c) { |
| return this.addItemsToList(index, c, this.list, LIST_VALUES); |
| } |
| |
| public boolean removeAll(Collection<?> c) { |
| return this.removeItemsFromList(c, this.list, LIST_VALUES); |
| } |
| |
| public boolean retainAll(Collection<?> c) { |
| return this.retainItemsInList(c, this.list, LIST_VALUES); |
| } |
| |
| public void clear() { |
| this.clearList(this.list, LIST_VALUES); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o == this) { |
| return true; |
| } |
| if ((o instanceof List<?>) && (o instanceof ListValueModel<?>)) { |
| List<E> l1 = CollectionTools.list(this.list); |
| @SuppressWarnings("unchecked") |
| List<E> l2 = CollectionTools.list(((List<E>) o).iterator()); |
| return l1.equals(l2); |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return this.list.hashCode(); |
| } |
| |
| public E set(int index, E element) { |
| return this.setItemInList(index, element, this.list, LIST_VALUES); |
| } |
| |
| public void add(int index, E element) { |
| this.addItemToList(index, element, this.list, LIST_VALUES); |
| } |
| |
| public E remove(int index) { |
| return this.removeItemFromList(index, this.list, LIST_VALUES); |
| } |
| |
| public int indexOf(Object o) { |
| return this.list.indexOf(o); |
| } |
| |
| public int lastIndexOf(Object o) { |
| return this.list.lastIndexOf(o); |
| } |
| |
| public ListIterator<E> listIterator(int index) { |
| return new LocalListIterator<E>(this.list.listIterator(index)); |
| } |
| |
| public List<E> subList(int fromIndex, int toIndex) { |
| // TODO hmmm ~bjv |
| throw new UnsupportedOperationException(); |
| } |
| |
| |
| // ********** additional behavior ********** |
| |
| /** |
| * Move a single element. |
| */ |
| public void move(int targetIndex, int sourceIndex) { |
| this.moveItemInList(targetIndex, sourceIndex, this.list, LIST_VALUES); |
| } |
| |
| /** |
| * Move a sub-list of elements. |
| */ |
| public void move(int targetIndex, int sourceIndex, int length) { |
| this.moveItemsInList(targetIndex, sourceIndex, length, this.list, LIST_VALUES); |
| } |
| |
| /** |
| * Remove a range of elements. |
| */ |
| public void remove(int index, int length) { |
| this.removeItemsFromList(index, length, this.list, LIST_VALUES); |
| } |
| |
| /** |
| * Set a range of elements. |
| */ |
| public void set(int index, List<E> elements) { |
| this.setItemsInList(index, elements, this.list, LIST_VALUES); |
| } |
| |
| @Override |
| public void toString(StringBuilder sb) { |
| sb.append(this.list); |
| } |
| |
| |
| // ********** iterators ********** |
| |
| private class LocalIterator<T> implements Iterator<T> { |
| private final Iterator<T> iterator; |
| private int index = -1; |
| private T next; |
| |
| LocalIterator(Iterator<T> iterator) { |
| super(); |
| this.iterator = iterator; |
| } |
| |
| public boolean hasNext() { |
| return this.iterator.hasNext(); |
| } |
| |
| public T next() { |
| this.next = this.iterator.next(); |
| this.index++; |
| return this.next; |
| } |
| |
| @SuppressWarnings("synthetic-access") |
| public void remove() { |
| this.iterator.remove(); |
| SimpleListValueModel.this.fireItemRemoved(LIST_VALUES, this.index, this.next); |
| } |
| |
| } |
| |
| private class LocalListIterator<T> implements ListIterator<T> { |
| private final ListIterator<T> iterator; |
| private int last = -1; |
| private int next = 0; |
| private T current; |
| |
| LocalListIterator(ListIterator<T> iterator) { |
| super(); |
| this.iterator = iterator; |
| } |
| |
| public boolean hasNext() { |
| return this.iterator.hasNext(); |
| } |
| |
| public T next() { |
| this.current = this.iterator.next(); |
| this.last = this.next++; |
| return this.current; |
| } |
| |
| public int nextIndex() { |
| return this.iterator.nextIndex(); |
| } |
| |
| public boolean hasPrevious() { |
| return this.iterator.hasPrevious(); |
| } |
| |
| public T previous() { |
| this.current = this.iterator.previous(); |
| this.last = --this.next; |
| return this.current; |
| } |
| |
| public int previousIndex() { |
| return this.iterator.previousIndex(); |
| } |
| |
| @SuppressWarnings("synthetic-access") |
| public void set(T o) { |
| this.iterator.set(o); |
| SimpleListValueModel.this.fireItemReplaced(LIST_VALUES, this.last, o, this.current); |
| } |
| |
| @SuppressWarnings("synthetic-access") |
| public void add(T o) { |
| this.iterator.add(o); |
| SimpleListValueModel.this.fireItemAdded(LIST_VALUES, this.next, o); |
| } |
| |
| @SuppressWarnings("synthetic-access") |
| public void remove() { |
| this.iterator.remove(); |
| SimpleListValueModel.this.fireItemRemoved(LIST_VALUES, this.last, this.current); |
| } |
| |
| } |
| |
| } |