Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/ObservableListView.java')
-rw-r--r--extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/ObservableListView.java352
1 files changed, 352 insertions, 0 deletions
diff --git a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/ObservableListView.java b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/ObservableListView.java
new file mode 100644
index 00000000000..7ae761009e9
--- /dev/null
+++ b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/ObservableListView.java
@@ -0,0 +1,352 @@
+/*****************************************************************************
+ * Copyright (c) 2013 Cedric Dumoulin.
+ *
+ *
+ * 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:
+ * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.layers.stackmodel.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.collect.ForwardingList;
+import com.google.common.collect.Lists;
+import com.google.common.eventbus.EventBus;
+
+/**
+ * An observable list notifying of events on the delegated list.
+ * This view allows to observe a provided list.
+ * The following events are notified:
+ * <ul>
+ * <li>elements added</li>
+ * <li>elements removed</li>
+ * <li></li>
+ * <li></li>
+ * </ul>
+ * @author cedric dumoulin
+ *
+ */
+public class ObservableListView<E> extends ForwardingList<E>{
+
+ protected List<E> delegate;
+
+ protected EventBus eventBus = new EventBus(ObservableListView.class.getName());
+
+ /**
+ * Construct an observable list with a {@link ArrayList} as delegate.
+ * Constructor.
+ *
+ */
+ public ObservableListView() {
+ this( new ArrayList<E>());
+ }
+
+ /**
+ * Constructor.
+ * Build an observable list based on the provided list.
+ *
+ * @param delegate
+ */
+ public ObservableListView(List<E> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ protected List<E> delegate() {
+ return delegate;
+ }
+
+ /**
+ * @return the eventBus
+ */
+ public EventBus getEventBus() {
+ return eventBus;
+ }
+
+ @Override
+ public boolean add(E element) {
+ boolean isModified = delegate().add( element);
+ if( isModified) {
+ eventBus.post(new ObservableListEvent(element));
+ }
+
+ return isModified;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> collection) {
+ boolean isModified = delegate().addAll(collection);
+ if( isModified) {
+ eventBus.post(new ObservableListEvent(collection));
+ }
+
+ return isModified;
+ }
+
+ @Override
+ public void add(int index, E element) {
+ delegate().add(index, element);
+ eventBus.post(new ObservableListEvent(element));
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends E> elements) {
+ // TODO Auto-generated method stub
+ boolean isModified = delegate().addAll(index, elements);
+ if( isModified) {
+ eventBus.post(new ObservableListEvent(elements));
+ }
+
+ return isModified;
+ }
+
+ @Override
+ public E remove(int index) {
+ E removed = super.remove(index);
+ getEventBus().post( new ObservableListEvent(null, removed));
+
+ return removed;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean remove(Object object) {
+ boolean isRemoved = super.remove(object);
+ if( isRemoved ) {
+ getEventBus().post( new ObservableListEvent(null, (E)object));
+ }
+ return isRemoved;
+ }
+
+ /**
+ *
+ * @see com.google.common.collect.ForwardingCollection#removeAll(java.util.Collection)
+ *
+ * @param collection
+ * @return
+ */
+ @Override
+ public boolean removeAll(Collection<?> collection) {
+ // Compute the removed elements (for the events)
+ List<E> removedElements = Lists.newArrayList(delegate());
+ removedElements.retainAll(collection);
+
+ // Do remove
+ boolean isRemoved = super.removeAll(collection);
+ if( isRemoved ) {
+ getEventBus().post( new ObservableListEvent(null, (Collection<? extends E>) removedElements));
+ }
+ return isRemoved;
+ }
+
+ /**
+ * Reset the collection to the specified collection.
+ * Throw events containing the added and removed elements.
+ *
+ * @param collection
+ * @return
+ */
+ public boolean resetTo(Collection<? extends E> collection ) {
+
+ // Compute removed and added
+ Collection<E> elementsToRemove = new ArrayList<E>();
+ Collection<E> elementsToAdd = new ArrayList<E>();
+
+ // Cached list of attached elements
+ Collection<? extends E> attachedElements = delegate();
+
+ // Compute added and removed elements. Walk both list 2 times.
+ // This could certainly be improved.
+ // TODO improve the algorithm
+
+ // Compute added elements
+ for( E o : collection ) {
+ if( !attachedElements.contains(o)) {
+ elementsToAdd.add(o);
+ continue;
+ }
+ }
+
+ // Compute removed elements
+ for( E o : attachedElements ) {
+ if( !collection.contains(o)) {
+ elementsToRemove.add(o);
+ continue;
+ }
+ }
+
+ // Change the list
+ delegate().clear();
+ delegate().addAll(collection);
+
+ // Fire event
+ boolean isModified = !(elementsToAdd.isEmpty() && elementsToRemove.isEmpty() );
+ if( isModified ) {
+ getEventBus().post( new ObservableListEvent(elementsToAdd, elementsToRemove));
+ }
+
+ return isModified;
+ }
+
+ /**
+ * Event used to specify that the list is changed
+ * @author cedric dumoulin
+ *
+ */
+ public class ObservableListEvent {
+
+ Collection<? extends E> addedElements = Collections.emptyList();
+ Collection<? extends E> removedElements = Collections.emptyList();
+
+ /**
+ *
+ * Constructor.
+ *
+ */
+ public ObservableListEvent() {
+ this.addedElements = Collections.emptyList();
+ this.removedElements = Collections.emptyList();
+ }
+
+ /**
+ *
+ * Constructor.
+ *
+ */
+ public ObservableListEvent(Collection<? extends E> addedElements) {
+ if( addedElements!=null ) {
+ this.addedElements = addedElements;
+ }
+ else {
+ this.addedElements = Collections.emptyList();
+ }
+
+ this.removedElements = Collections.emptyList();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param addedElements added elements or null
+ * @param removedElements removed elements or null
+ */
+ public ObservableListEvent(Collection<? extends E> addedElements, Collection<? extends E> removedElements) {
+ if( addedElements!=null ) {
+ this.addedElements = addedElements;
+ }
+ else {
+ this.addedElements = Collections.emptyList();
+ }
+
+ if( removedElements != null ) {
+ this.removedElements = removedElements;
+ }
+ else {
+ this.removedElements = Collections.emptyList();
+ }
+ }
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param addedElement An element added or null;
+ * @param removedElement An element added or null
+ */
+ public ObservableListEvent( E addedElement, E removedElement) {
+
+ if( addedElement!=null ) {
+ addedElements = Collections.singletonList(addedElement);
+ }
+ else {
+ addedElements = Collections.emptyList();
+ }
+
+ if( removedElement != null ) {
+ removedElements = Collections.singletonList(removedElement);
+ }
+ else {
+ removedElements = Collections.emptyList();
+ }
+ }
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param addedElement An element added or null;
+ */
+ public ObservableListEvent( E addedElement) {
+
+ if( addedElement!=null ) {
+ addedElements = Collections.singletonList(addedElement);
+ }
+ else {
+ addedElements = Collections.emptyList();
+ }
+ removedElements = Collections.emptyList();
+ }
+
+ /**
+ * @return the addedElements
+ */
+ public Collection<? extends E> getAddedElements() {
+ return addedElements;
+ }
+
+// /**
+// * @param addedElements the addedElements to set
+// */
+// public void setAddedElements(List<E> addedElements) {
+// this.addedElements = addedElements;
+// }
+//
+// /**
+// * @param addedElements the addedElements to set
+// */
+// public void setAddedElements(E addedElement) {
+// this.addedElements = Collections.singletonList(addedElement);
+// }
+
+ /**
+ * @return the removedElements
+ */
+ public Collection<? extends E> getRemovedElements() {
+ return removedElements;
+ }
+
+// /**
+// * @param removedElements the removedElements to set
+// */
+// public void setRemovedElements(List<E> removedElements) {
+// this.removedElements = removedElements;
+// }
+//
+// /**
+// * @param removedElements the removedElements to set
+// */
+// public void setRemovedElements(E removedElement) {
+// this.removedElements = Collections.singletonList(removedElement);
+// }
+ }
+
+ /**
+ * Return the underlying list. This can be used as an unnotifying version of the list.
+ *
+ * @return
+ */
+ public List<E> getUnnotifyingList() {
+ return delegate();
+
+ }
+}

Back to the top