Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkmoore2011-02-05 16:22:02 +0000
committerkmoore2011-02-05 16:22:02 +0000
commit824998d08071af6d9877fb5314aa25d360d1c172 (patch)
tree80d029dbe3dc505c45ea0413e5218fda4b7be5e1 /common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/CollectionListValueModelAdapter.java
parentc73d0c7b4a6a3150dd604d6c747069408ace5719 (diff)
downloadwebtools.dali-824998d08071af6d9877fb5314aa25d360d1c172.tar.gz
webtools.dali-824998d08071af6d9877fb5314aa25d360d1c172.tar.xz
webtools.dali-824998d08071af6d9877fb5314aa25d360d1c172.zip
rename org.eclipse.jpt.utility to org.eclipse.jpt.common.utility and move to common component
Diffstat (limited to 'common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/CollectionListValueModelAdapter.java')
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/CollectionListValueModelAdapter.java217
1 files changed, 217 insertions, 0 deletions
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/CollectionListValueModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/CollectionListValueModelAdapter.java
new file mode 100644
index 0000000000..4c3d8b4cca
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/CollectionListValueModelAdapter.java
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * 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.common.utility.internal.model.value;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+import org.eclipse.jpt.common.utility.internal.iterators.ReadOnlyListIterator;
+import org.eclipse.jpt.common.utility.model.event.CollectionAddEvent;
+import org.eclipse.jpt.common.utility.model.event.CollectionChangeEvent;
+import org.eclipse.jpt.common.utility.model.event.CollectionClearEvent;
+import org.eclipse.jpt.common.utility.model.event.CollectionRemoveEvent;
+import org.eclipse.jpt.common.utility.model.listener.CollectionChangeListener;
+import org.eclipse.jpt.common.utility.model.value.CollectionValueModel;
+import org.eclipse.jpt.common.utility.model.value.ListValueModel;
+
+/**
+ * An adapter that allows us to make a {@link CollectionValueModel} behave like
+ * a read-only {@link ListValueModel}, sorta.
+ * <p>
+ * To maintain a reasonably consistent appearance to client code, we
+ * keep an internal list somewhat in synch with the wrapped collection.
+ * <p>
+ * <strong>NB:</strong> Since we only listen to the wrapped collection when we have
+ * listeners ourselves and we can only stay in synch with the wrapped
+ * collection while we are listening to it, results to various methods
+ * (e.g. {@link #size()}, {@link #get(int)}) will be unpredictable whenever
+ * we do not have any listeners. This should not be too painful since,
+ * most likely, clients will also be listeners.
+ */
+public class CollectionListValueModelAdapter<E>
+ extends AbstractListValueModel
+ implements ListValueModel<E>
+{
+ /** The wrapped collection value model. */
+ protected final CollectionValueModel<? extends E> collectionHolder;
+
+ /** A listener that forwards any events fired by the collection holder. */
+ protected final CollectionChangeListener collectionChangeListener;
+
+ /**
+ * Our internal list, which holds the same elements as
+ * the wrapped collection, but keeps them in order.
+ */
+ // we declare this an ArrayList so we can use #clone() and #ensureCapacity(int)
+ protected final ArrayList<E> list;
+
+
+ // ********** constructors **********
+
+ /**
+ * Wrap the specified collection value model.
+ */
+ public CollectionListValueModelAdapter(CollectionValueModel<? extends E> collectionHolder) {
+ super();
+ if (collectionHolder == null) {
+ throw new NullPointerException();
+ }
+ this.collectionHolder = collectionHolder;
+ this.collectionChangeListener = this.buildCollectionChangeListener();
+ this.list = new ArrayList<E>(collectionHolder.size());
+ // postpone building the list and listening to the underlying collection
+ // until we have listeners ourselves...
+ }
+
+
+ // ********** initialization **********
+
+ /**
+ * The wrapped collection has changed, forward an equivalent
+ * list change event to our listeners.
+ */
+ protected CollectionChangeListener buildCollectionChangeListener() {
+ return new CollectionChangeListener() {
+ public void itemsAdded(CollectionAddEvent event) {
+ CollectionListValueModelAdapter.this.itemsAdded(event);
+ }
+ public void itemsRemoved(CollectionRemoveEvent event) {
+ CollectionListValueModelAdapter.this.itemsRemoved(event);
+ }
+ public void collectionCleared(CollectionClearEvent event) {
+ CollectionListValueModelAdapter.this.collectionCleared(event);
+ }
+ public void collectionChanged(CollectionChangeEvent event) {
+ CollectionListValueModelAdapter.this.collectionChanged(event);
+ }
+ @Override
+ public String toString() {
+ return "collection change listener"; //$NON-NLS-1$
+ }
+ };
+ }
+
+
+ // ********** ListValueModel implementation **********
+
+ public Iterator<E> iterator() {
+ return this.listIterator();
+ }
+
+ public ListIterator<E> listIterator() {
+ return new ReadOnlyListIterator<E>(this.list);
+ }
+
+ public E get(int index) {
+ return this.list.get(index);
+ }
+
+ public int size() {
+ return this.list.size();
+ }
+
+ public Object[] toArray() {
+ return this.list.toArray();
+ }
+
+
+ // ********** behavior **********
+
+ @Override
+ protected void engageModel() {
+ this.collectionHolder.addCollectionChangeListener(CollectionValueModel.VALUES, this.collectionChangeListener);
+ // synch our list *after* we start listening to the collection holder,
+ // since its value might change when a listener is added
+ this.buildList();
+ }
+
+ @Override
+ protected void disengageModel() {
+ this.collectionHolder.removeCollectionChangeListener(CollectionValueModel.VALUES, this.collectionChangeListener);
+ // clear out the list when we are not listening to the collection holder
+ this.list.clear();
+ }
+
+ protected void buildList() {
+ // if the new collection is empty, do nothing
+ int size = this.collectionHolder.size();
+ if (size != 0) {
+ this.buildList(size);
+ }
+ }
+
+ protected void buildList(int size) {
+ this.list.ensureCapacity(size);
+ for (E each : this.collectionHolder) {
+ this.list.add(each);
+ }
+ }
+
+ protected void itemsAdded(CollectionAddEvent event) {
+ this.addItemsToList(this.indexToAddItems(), this.getItems(event), this.list, LIST_VALUES);
+ }
+
+ protected int indexToAddItems() {
+ return this.list.size();
+ }
+
+ // minimize scope of suppressed warnings
+ @SuppressWarnings("unchecked")
+ protected Iterable<E> getItems(CollectionAddEvent event) {
+ return (Iterable<E>) event.getItems();
+ }
+
+ protected void itemsRemoved(CollectionRemoveEvent event) {
+ this.removeItemsFromList(this.getItems(event), this.list, LIST_VALUES);
+ }
+
+ // minimize scope of suppressed warnings
+ @SuppressWarnings("unchecked")
+ protected Iterable<E> getItems(CollectionRemoveEvent event) {
+ return (Iterable<E>) event.getItems();
+ }
+
+ protected void collectionCleared(@SuppressWarnings("unused") CollectionClearEvent event) {
+ this.clearList(this.list, LIST_VALUES);
+ }
+
+ /**
+ * synchronize our internal list with the wrapped collection
+ * and fire the appropriate events
+ */
+ protected void collectionChanged(@SuppressWarnings("unused") CollectionChangeEvent event) {
+ int size = this.collectionHolder.size();
+ if (size == 0) {
+ if (this.list.isEmpty()) {
+ // no change
+ } else {
+ this.clearList(this.list, LIST_VALUES);
+ }
+ } else {
+ if (this.list.isEmpty()) {
+ this.buildList(size);
+ this.fireItemsAdded(LIST_VALUES, 0, this.list);
+ } else {
+ this.synchronizeList(this.buildSyncList(), this.list, LIST_VALUES);
+ }
+ }
+ }
+
+ protected Iterable<? extends E> buildSyncList() {
+ return this.collectionHolder;
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.list);
+ }
+
+}

Back to the top