Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCedric Dumoulin2014-01-06 16:31:13 +0000
committerCedric Dumoulin2014-01-27 13:57:20 +0000
commite1898665a62032926f02c75b2696c66fe0b165b0 (patch)
tree03a08acc33760e95dd206512882a753a0a0528b2 /extraplugins/layers/org.eclipse.papyrus.layers.stackmodel
parenta1bde794fe892116019876b33570985c35062eb4 (diff)
downloadorg.eclipse.papyrus-e1898665a62032926f02c75b2696c66fe0b165b0.tar.gz
org.eclipse.papyrus-e1898665a62032926f02c75b2696c66fe0b165b0.tar.xz
org.eclipse.papyrus-e1898665a62032926f02c75b2696c66fe0b165b0.zip
bugs 330199 - Try to improve the ExpressionMatcher
Diffstat (limited to 'extraplugins/layers/org.eclipse.papyrus.layers.stackmodel')
-rw-r--r--extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcher.java77
-rw-r--r--extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ValueChangedEventNotifier.java6
-rw-r--r--extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/layers/impl/RegExpLayerImpl.java77
-rw-r--r--extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/Collections3.java75
-rw-r--r--extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/ObservableListView.java9
-rw-r--r--extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/test/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcherTest.java21
6 files changed, 178 insertions, 87 deletions
diff --git a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcher.java b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcher.java
index 09e45735281..8274b285d33 100644
--- a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcher.java
+++ b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcher.java
@@ -35,15 +35,18 @@ import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.ecore.OCL;
import org.eclipse.papyrus.layers.stackmodel.LayersException;
+import org.eclipse.papyrus.layers.stackmodel.util.Collections3;
import org.eclipse.papyrus.layers.stackmodel.util.ObservableListView;
/**
* This class evaluate its associated expression against the associated models.
* It provide a list of elements matching the expression in the model.
- * It fire some events when the list of matching elements change.
- * The expression is evaluated each time a change impacting the result occurs in the model.
+ * The list of matching elements is synchronized by the matcher. The list can be provided at construction
+ * time. The ExpressinMatcher takes care to minimize the number of write to the underlying list of matching elements.
+ * Usually, there is two writes (see {@link Collections3#resetListTo(Collection, Collection)}.
+ * <br>
+ * It is possible to be inform of changes in the underlying list by wrapping it in an {@link ObservableListView}.
*
- * It maybe necessary to adjust the listeners on model changes to improve performances.
*
* @author cedric dumoulin
*
@@ -56,7 +59,7 @@ public class ExpressionMatcher implements IValueChangedEventListener {
* List of element matching the expression.
* This class maintains the list.
*/
- protected ObservableListView<View> matchingElements;
+ protected List<View> matchingElements;
/**
* List of element used as starting point for search.
@@ -70,11 +73,16 @@ public class ExpressionMatcher implements IValueChangedEventListener {
protected OCL ocl;
+ /**
+ *
+ * Constructor.
+ *
+ */
public ExpressionMatcher() {
this.expression = "";
this.searchRoots = Collections.emptyList();
// init matchingElements
- matchingElements = new ObservableListView<View>(new ArrayList<View>());
+ matchingElements = new ArrayList<View>();
}
/**
@@ -84,22 +92,39 @@ public class ExpressionMatcher implements IValueChangedEventListener {
* @param searchRoots
* @throws LayersException
*/
- public ExpressionMatcher(List<EObject> searchRoots) {
+ public ExpressionMatcher(List<View> matchingElementsList) {
this.expression = "";
- setSearchRoots(searchRoots);
+ this.searchRoots = Collections.emptyList();
// init matchingElements
- matchingElements = new ObservableListView<View>(new ArrayList<View>());
+ matchingElements = matchingElementsList;
}
/**
*
* Constructor.
*
+ * @param searchRoots
+ * @throws LayersException
+ */
+// public ExpressionMatcher(List<EObject> searchRoots) {
+// this.expression = "";
+// setSearchRoots(searchRoots);
+// // init matchingElements
+// matchingElements = new ObservableListView<View>(new ArrayList<View>());
+// }
+
+ /**
+ *
+ * Constructor.
+ *
* @param searchRoot
* @throws LayersException
*/
public ExpressionMatcher(EObject searchRoot) {
- this(Collections.singletonList(searchRoot));
+ this.expression = "";
+ setSearchRoots(Collections.singletonList(searchRoot));
+ // init matchingElements
+ matchingElements = new ArrayList<View>();
}
/**
@@ -111,7 +136,22 @@ public class ExpressionMatcher implements IValueChangedEventListener {
*/
public ExpressionMatcher(String expression, List<EObject> searchRoots) throws LayersException {
this.searchRoots = searchRoots;
- matchingElements = new ObservableListView<View>(new ArrayList<View>());
+ matchingElements = new ArrayList<View>();
+
+ // compute expr
+ setExpression(expression);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param expression
+ * @param searchRoots
+ * @throws LayersException If the Condition can't be computed from the expression.
+ */
+ public ExpressionMatcher(String expression, List<View> matchingElementsList, List<EObject> searchRoots) throws LayersException {
+ this.searchRoots = searchRoots;
+ matchingElements = matchingElementsList;
// compute expr
setExpression(expression);
@@ -129,6 +169,17 @@ public class ExpressionMatcher implements IValueChangedEventListener {
}
/**
+ * Constructor.
+ *
+ * @param expression
+ * @param searchRoots
+ * @throws LayersException If the Condition can't be computed from the expression.
+ */
+ public ExpressionMatcher(String expression, List<View> matchingElementsList, EObject searchRoot) throws LayersException {
+ this(expression, matchingElementsList, Collections.singletonList(searchRoot));
+ }
+
+ /**
* Compute the condition from the expr.
*/
private void computeCondition() throws LayersException {
@@ -196,9 +247,11 @@ public class ExpressionMatcher implements IValueChangedEventListener {
*
* @param results
*/
+ @SuppressWarnings("unchecked")
private void resetMatchingElements(Collection<?> newElements) {
- matchingElements.resetTo((Collection<View>)newElements);
+ Collections3.resetListTo(matchingElements, (Collection<View>)newElements);
+// matchingElements.resetTo((Collection<View>)newElements);
// // Compute views to add
// // This are views in the newElements, but not in the actual list of matchingElement
@@ -265,7 +318,7 @@ public class ExpressionMatcher implements IValueChangedEventListener {
/**
* @return the matchingElements
*/
- public ObservableListView<View> getMatchingElements() {
+ public List<View> getMatchingElements() {
return matchingElements;
}
diff --git a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ValueChangedEventNotifier.java b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ValueChangedEventNotifier.java
index 0a32cbf7c07..adf6abe1cd3 100644
--- a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ValueChangedEventNotifier.java
+++ b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ValueChangedEventNotifier.java
@@ -11,18 +11,12 @@
package org.eclipse.papyrus.layers.stackmodel.exprmatcher;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
-import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EContentAdapter;
-import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.View;
diff --git a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/layers/impl/RegExpLayerImpl.java b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/layers/impl/RegExpLayerImpl.java
index ede42349c03..bd162ebc367 100644
--- a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/layers/impl/RegExpLayerImpl.java
+++ b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/layers/impl/RegExpLayerImpl.java
@@ -209,12 +209,12 @@ public class RegExpLayerImpl extends AbstractLayerImpl implements RegExpLayer {
super();
// Initialize expressionmatcher
- expressionMatcher = new ExpressionMatcher();
+ // The expression Macher use this class views list.
+ // When expressionMatcher::refreshMatchingElements() is called, the provided list is refreshed.
+ // So, views is synchronized and events are fired.
+ expressionMatcher = new ExpressionMatcher(getViews());
resetExpressionMatcherRoots();
- // listen to expression matcher changes
- expressionMatcher.getMatchingElements().getEventBus().register(this);
-
}
/**
@@ -267,22 +267,22 @@ public class RegExpLayerImpl extends AbstractLayerImpl implements RegExpLayer {
* they can be unsync after the model was loaded by EMF.
* <b>
* This method is used to correct the bug where both list are unsync after the model was loaded by EMF.
- *
+ * @Deprecated Not needed anymore
*/
private void checkViewsAndMatchingElementsSync() {
- // Check if both list have the same size.
- // We don't to check the content, because we want a quick check
- // Actually, unsync appear only after the model was reloded by EMF.
- if( getViews().size() == expressionMatcher.getMatchingElements().size() ) {
- // ok
- return;
- }
-
- // Sync is required
- List<View> matchElements = expressionMatcher.getMatchingElements().getUnnotifyingList();
- matchElements.clear();
- matchElements.addAll(getViews());
+// // Check if both list have the same size.
+// // We don't to check the content, because we want a quick check
+// // Actually, unsync appear only after the model was reloded by EMF.
+// if( getViews().size() == expressionMatcher.getMatchingElements().size() ) {
+// // ok
+// return;
+// }
+//
+// // Sync is required
+// List<View> matchElements = expressionMatcher.getMatchingElements().getUnnotifyingList();
+// matchElements.clear();
+// matchElements.addAll(getViews());
}
@@ -1002,47 +1002,4 @@ public class RegExpLayerImpl extends AbstractLayerImpl implements RegExpLayer {
}
- /**
- * Reset the toChange list to the content of the newContent list.
- * Minimize the change calls on the toChange list.
- * This method ensure that there is at most 2 writing calls to the list to modify: one
- * removeAll(toBeRemoved) and one addAll(toBeAdded).
- *
- * @param toChange
- * @param newContent
- */
- static <E> void resetListTo(Collection<E> toChange, Collection<E> newContent) {
-
- // Compute removed and added
- Collection<E> elementsToRemove = new ArrayList<E>();
- Collection<E> elementsToAdd = new ArrayList<E>();
-
- // 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 : newContent ) {
- if( !toChange.contains(o)) {
- elementsToAdd.add(o);
- continue;
- }
- }
-
- // Compute removed elements
- for( E o : toChange ) {
- if( !newContent.contains(o)) {
- elementsToRemove.add(o);
- continue;
- }
- }
-
- // Change the list
- if( ! elementsToRemove.isEmpty()) {
- toChange.removeAll(elementsToRemove);
- }
- if( !elementsToAdd.isEmpty()) {
- toChange.addAll(elementsToAdd);
- }
- }
} //RegExpLayerImpl
diff --git a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/Collections3.java b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/Collections3.java
new file mode 100644
index 00000000000..7d6269fecff
--- /dev/null
+++ b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/src/org/eclipse/papyrus/layers/stackmodel/util/Collections3.java
@@ -0,0 +1,75 @@
+/*****************************************************************************
+ * 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 com.google.common.collect.Collections2;
+
+/**
+ * Set of utility methods for Collections.
+ * @see Collections2
+ *
+ * @author cedric dumoulin
+ *
+ */
+public class Collections3 {
+
+ /**
+ * Reset the toChange list to the content of the newContent list.
+ * Minimize the change calls on the toChange list.
+ * This method ensure that there is at most 2 writing calls to the list to modify: one
+ * removeAll(toBeRemoved) and one addAll(toBeAdded).
+ *
+ * @param toChange
+ * @param newContent
+ */
+ public static <E> void resetListTo(Collection<E> toChange, Collection<E> newContent) {
+
+ // Compute removed and added
+ Collection<E> elementsToRemove = new ArrayList<E>();
+ Collection<E> elementsToAdd = new ArrayList<E>();
+
+ // 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 : newContent ) {
+ if( !toChange.contains(o)) {
+ elementsToAdd.add(o);
+ continue;
+ }
+ }
+
+ // Compute removed elements
+ for( E o : toChange ) {
+ if( !newContent.contains(o)) {
+ elementsToRemove.add(o);
+ continue;
+ }
+ }
+
+ // Change the list
+ if( ! elementsToRemove.isEmpty()) {
+ toChange.removeAll(elementsToRemove);
+ }
+ if( !elementsToAdd.isEmpty()) {
+ toChange.addAll(elementsToAdd);
+ }
+ }
+
+}
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
index a7b8631b5a0..7ae761009e9 100644
--- 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
@@ -43,6 +43,15 @@ public class ObservableListView<E> extends ForwardingList<E>{
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.
*
diff --git a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/test/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcherTest.java b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/test/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcherTest.java
index 8342bd85bf6..74bbf353ed8 100644
--- a/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/test/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcherTest.java
+++ b/extraplugins/layers/org.eclipse.papyrus.layers.stackmodel/test/org/eclipse/papyrus/layers/stackmodel/exprmatcher/ExpressionMatcherTest.java
@@ -312,10 +312,11 @@ public class ExpressionMatcherTest {
int addedElementCount = 0;
int expectedEventCount = 1;
- FakeObservableListListener<View> notifyingListListener = new FakeObservableListListener<View>();
- ExpressionMatcher expressionMatcher = new ExpressionMatcher(expression, diagram);
+ ObservableListView<View> matchingElements = new ObservableListView<View>();
+ ExpressionMatcher expressionMatcher = new ExpressionMatcher(expression, matchingElements, diagram);
- expressionMatcher.getMatchingElements().getEventBus().register(notifyingListListener);
+ FakeObservableListListener<View> notifyingListListener = new FakeObservableListListener<View>();
+ matchingElements.getEventBus().register(notifyingListListener);
// Action
notifyingListListener.traces.clear();
@@ -350,10 +351,11 @@ public class ExpressionMatcherTest {
int expectedEventCount = 1;
int viewsCount = diagram.getChildren().size();
- FakeObservableListListener<View> notifyingListListener = new FakeObservableListListener<View>();
- ExpressionMatcher expressionMatcher = new ExpressionMatcher(expression, diagram);
+ ObservableListView<View> matchingElements = new ObservableListView<View>();
+ ExpressionMatcher expressionMatcher = new ExpressionMatcher(expression, matchingElements, diagram);
- expressionMatcher.getMatchingElements().getEventBus().register(notifyingListListener);
+ FakeObservableListListener<View> notifyingListListener = new FakeObservableListListener<View>();
+ matchingElements.getEventBus().register(notifyingListListener);
// Action
notifyingListListener.traces.clear();
@@ -391,10 +393,11 @@ public class ExpressionMatcherTest {
int expectedEventCount = 1;
int viewsCount = diagram.getChildren().size();
- FakeObservableListListener<View> notifyingListListener = new FakeObservableListListener<View>();
- ExpressionMatcher expressionMatcher = new ExpressionMatcher(expression, diagram);
+ ObservableListView<View> matchingElements = new ObservableListView<View>();
+ ExpressionMatcher expressionMatcher = new ExpressionMatcher(expression, matchingElements, diagram);
- expressionMatcher.getMatchingElements().getEventBus().register(notifyingListListener);
+ FakeObservableListListener<View> notifyingListListener = new FakeObservableListListener<View>();
+ matchingElements.getEventBus().register(notifyingListListener);
// Action
notifyingListListener.traces.clear();

Back to the top