Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeremie.tatibouet2015-04-28 09:56:58 -0400
committerArnaud Cuccuru2015-04-30 07:47:46 -0400
commitbbdda04530c5901c986da88c550db65a146aede7 (patch)
treef18967d0e63785d1b1e636f4cd01c6710e43cd09 /extraplugins/alf
parent03c212d7016556ba542f4e69024fc0228c85722e (diff)
downloadorg.eclipse.papyrus-bbdda04530c5901c986da88c550db65a146aede7.tar.gz
org.eclipse.papyrus-bbdda04530c5901c986da88c550db65a146aede7.tar.xz
org.eclipse.papyrus-bbdda04530c5901c986da88c550db65a146aede7.zip
Class, Signal, Enumeration, Datatype and package follows automatically
the evolution of the semantic model. ElementImport, Generalization, PackageImport impacts are also supported. Change-Id: I0178e33f270d8c542d8a6df68cc11b153732d6f2 Signed-off-by: jeremie.tatibouet <jeremie.tatibouet@cea.fr> Reviewed-on: https://git.eclipse.org/r/46748 Reviewed-by: Arnaud Cuccuru <arnaud.cuccuru@cea.fr> Tested-by: Arnaud Cuccuru <arnaud.cuccuru@cea.fr> Reviewed-on: https://git.eclipse.org/r/46799 Tested-by: Hudson CI
Diffstat (limited to 'extraplugins/alf')
-rw-r--r--extraplugins/alf/core/org.eclipse.papyrus.uml.alf.text/src/org/eclipse/papyrus/uml/alf/text/representation/AlfTextualRepresentation.java2
-rw-r--r--extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/ISyncScenario.java11
-rw-r--r--extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/Scenario.java10
-rw-r--r--extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/SyncScenario.java434
-rw-r--r--extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/FUMLElementListener.java7
-rw-r--r--extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/filter/FUMLFilter.java300
6 files changed, 686 insertions, 78 deletions
diff --git a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.text/src/org/eclipse/papyrus/uml/alf/text/representation/AlfTextualRepresentation.java b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.text/src/org/eclipse/papyrus/uml/alf/text/representation/AlfTextualRepresentation.java
index 16f0c0992c7..8616893ffb1 100644
--- a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.text/src/org/eclipse/papyrus/uml/alf/text/representation/AlfTextualRepresentation.java
+++ b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.text/src/org/eclipse/papyrus/uml/alf/text/representation/AlfTextualRepresentation.java
@@ -168,7 +168,7 @@ public class AlfTextualRepresentation extends TextualRepresentation
* @return this - the current textual representation
*/
public AlfTextualRepresentation rebase(AlfTextualRepresentation representation) {
- if (this.getOwner() == representation.getOwner()) {
+ if (representation!= null && this.getOwner() == representation.getOwner()) {
BackupState state = new BackupState();
state.status = representation.getStatus();
state.timestamp = new Timestamp(representation.getModificationDate());
diff --git a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/ISyncScenario.java b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/ISyncScenario.java
index 188833c40b5..4091fc63705 100644
--- a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/ISyncScenario.java
+++ b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/ISyncScenario.java
@@ -12,6 +12,7 @@
*****************************************************************************/
package org.eclipse.papyrus.uml.alf.transaction.commit;
+import java.util.HashMap;
import java.util.List;
import org.eclipse.emf.common.command.Command;
@@ -19,12 +20,6 @@ import org.eclipse.emf.common.notify.Notification;
import org.eclipse.uml2.uml.Element;
public interface ISyncScenario {
- /**
- * The core method of a scenario
- *
- * @param target
- * - the element for which the scenario is executed
- * @return command - a command (that may be compound) to be executed in order to perform the synchronization
- */
- public Command synchronize(Element target, List<Notification> changes);
+
+ public Command synchronize(HashMap<Element, List<Notification>> changes);
}
diff --git a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/Scenario.java b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/Scenario.java
index bcc79b83562..dc5cb875881 100644
--- a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/Scenario.java
+++ b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/Scenario.java
@@ -18,6 +18,8 @@ import org.eclipse.papyrus.uml.alf.text.representation.util.RepresentationParser
import org.eclipse.papyrus.uml.alf.text.representation.util.RepresentationParsingError;
import org.eclipse.uml2.uml.NamedElement;
+import static org.eclipse.papyrus.uml.alf.transaction.ActivatorTransaction.logger;
+
public abstract class Scenario implements IScenario {
/**
@@ -41,13 +43,11 @@ public abstract class Scenario implements IScenario {
}
try {
this.userModelState = RepresentationParser.getInstance().parse(target);
- } catch (RepresentationParsingError e) {
- e.printStackTrace();
- }
- try {
this.currentModelState = RepresentationParser.getInstance().getSnapshot(target);
} catch (RepresentationParsingError e) {
- e.printStackTrace();
+ logger.error("Parsing of ["+target.getName()+"]", e);
+ } catch(RuntimeException e){
+ logger.error("Serialization of ["+target.getName()+"] failed", e);
}
}
}
diff --git a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/SyncScenario.java b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/SyncScenario.java
index 370ca87a7ab..bcdaa3dede3 100644
--- a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/SyncScenario.java
+++ b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/commit/SyncScenario.java
@@ -15,6 +15,7 @@ package org.eclipse.papyrus.uml.alf.transaction.commit;
import static org.eclipse.papyrus.uml.alf.transaction.ActivatorTransaction.logger;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -24,17 +25,30 @@ import org.eclipse.compare.CompareUI;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.window.Window;
import org.eclipse.papyrus.uml.alf.text.merge.manual.AlfCompareEditor;
import org.eclipse.papyrus.uml.alf.text.merge.manual.MergeActionDialog;
import org.eclipse.papyrus.uml.alf.text.representation.AlfTextualRepresentation;
import org.eclipse.papyrus.uml.alf.transaction.commands.AlfCommandFactory;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.uml2.uml.Association;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.ElementImport;
+import org.eclipse.uml2.uml.Enumeration;
+import org.eclipse.uml2.uml.EnumerationLiteral;
+import org.eclipse.uml2.uml.Feature;
import org.eclipse.uml2.uml.Generalization;
+import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.NamedElement;
-import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.PackageImport;
+import org.eclipse.uml2.uml.Property;
+import org.eclipse.uml2.uml.Signal;
+import org.eclipse.uml2.uml.UMLPackage;
public class SyncScenario extends Scenario implements ISyncScenario {
@@ -70,77 +84,405 @@ public class SyncScenario extends Scenario implements ISyncScenario {
this.modelStateToBeCommitted = this.currentModelState;
}
}
+ } else {
+ this.modelStateToBeCommitted = this.userModelState.rebase(this.currentModelState);
}
} else {
this.modelStateToBeCommitted = this.userModelState.rebase(this.currentModelState);
}
}
- protected Set<NamedElement> getRealTargets(Element target, List<Notification> changes) {
- Set<NamedElement> realTargets = new HashSet<NamedElement>();
+ public Command synchronize(HashMap<Element, List<Notification>> changes) {
+ CompoundCommand compoundCommand = new CompoundCommand("synchronize");
+ for (NamedElement affectedElement : this.getSynchronizationPoints(changes)) {
+ compoundCommand.append(this._synchronize(affectedElement));
+ }
+ return compoundCommand;
+ }
+
+ /**
+ * Compute the set of element that need to have their serialization updated
+ *
+ * @param changes
+ * the list of changes per UML element
+ *
+ * @return syncPoints
+ * the list of UML elements that will have their serialization updated
+ */
+ protected Set<NamedElement> getSynchronizationPoints(HashMap<Element, List<Notification>> changes) {
+ Set<NamedElement> syncPoints = new HashSet<NamedElement>();
+ /*1. Take out changes that cannot be handled*/
+ this.preFilter(changes);
+ /*2. Compute synchronization targets according to changes*/
+ for (Element target : changes.keySet()) {
+ //logger.info("[MODIFIED] "+ target.toString());
+ if(target instanceof PackageImport ||target instanceof ElementImport){
+ syncPoints.addAll(this.getUpdateTargets(target, changes.get(target)));
+ }else if(target instanceof Association){
+ syncPoints.addAll(this.getUpdateTargets((Association) target, changes.get(target)));
+ }else if (target instanceof Generalization){
+ syncPoints.addAll(this.getUpdateTargets((Generalization) target, changes.get(target)));
+ }else if (target instanceof Package) {
+ syncPoints.addAll(this.getUpdateTargets((Package) target, changes.get(target)));
+ } else if (target instanceof Classifier) {
+ syncPoints.addAll(this.getUpdateTargets((Classifier) target, changes.get(target)));
+ } else if (target instanceof Feature) {
+ syncPoints.addAll(this.getUpdateTargets((Feature) target, changes.get(target)));
+ } else if(target instanceof EnumerationLiteral){
+ syncPoints.addAll(this.getUpdateTargets((EnumerationLiteral) target, changes.get(target)));
+ }
+ }
+ /*for (NamedElement element : syncPoints) {
+ logger.info("[UPADTED] " + element);
+ }*/
+ return syncPoints;
+ }
+
+ /**
+ * Takes out from a map of changes those that cannot be computed by synchronization engine
+ *
+ * @param changes
+ * the list of notifications per modified object
+ */
+ private void preFilter(HashMap<Element, List<Notification>> changes){
+ for(Element element : changes.keySet()){
+ Iterator<Notification> iterator = changes.get(element).iterator();
+ while(iterator.hasNext()){
+ Notification notification = iterator.next();
+ if(!this.isWorkable(notification)){
+ iterator.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Determine if an ADD notification can be used by the synchronizer or not.
+ * Typically such notification can be used if the new value has a name.
+ *
+ * NOTE: necessity of this check was introduced by the arrival of notification
+ * for which created values (newValue) had no name.
+ *
+ * @return true if the notification can be used false otherwise
+ */
+ private boolean isWorkable(Notification notification){
+ boolean isWorkable = true;
+ if(notification.getNewValue()!=null && notification.getEventType()==Notification.ADD){
+ if(notification.getNewValue() instanceof NamedElement){
+ isWorkable = ((NamedElement)notification.getNewValue()).getName() != null;
+ }
+ }
+ return isWorkable;
+ }
+
+ /**
+ * Get the set of elements that are intended to have their serialization updated
+ *
+ * @param element
+ * the given element can only be an element import or a package import
+ *
+ * @param changes
+ * the list of changes having affected the given element
+ *
+ * @return targets
+ * the of elements that need to have their serialization updated due to the changes
+ */
+ protected Set<NamedElement> getUpdateTargets(Element element, List<Notification> changes) {
+ assert (element instanceof ElementImport || element instanceof PackageImport) : "element can only be an element import or a package import";
+ Set<NamedElement> targets = new HashSet<NamedElement>();;
Iterator<Notification> changesIterator = changes.iterator();
- /* 1. Handle model modifications implied by Generalization */
- if (target instanceof Generalization) {
- while (changesIterator.hasNext()) {
- Notification notification = changesIterator.next();
- switch (notification.getEventType()) {
- /* Handle the case where Class::superClass derived feature changed but no notification was emitted */
- case Notification.SET: {
- /* The specific feature has changed (deletion / update) */
- if (notification.getFeature() == UMLPackage.eINSTANCE.getGeneralization_Specific()
- && notification.getOldValue() != null) {
- realTargets.add((NamedElement) notification.getOldValue());
- }
- /* The general feature has changed (deletion / update) */
- else if (notification.getFeature() == UMLPackage.eINSTANCE.getGeneralization_General()
- && ((Generalization) target).getSpecific() != null) {
- realTargets.add(((Generalization) target).getSpecific());
+ while (changesIterator.hasNext()) {
+ Notification notification = changesIterator.next();
+ switch(notification.getEventType()){
+ case Notification.SET:{
+ EStructuralFeature feature = (EStructuralFeature) notification.getFeature();
+ if(feature == UMLPackage.eINSTANCE.getElementImport_ImportingNamespace()
+ || feature == UMLPackage.eINSTANCE.getElementImport_ImportingNamespace()){
+ /*The old importing namespace has to be updated*/
+ if(notification.getNewValue()==null){
+ targets.addAll(this.getParentPath((Element)notification.getOldValue()));
+ }else{ /*The new importing namespace has to be updated*/
+ targets.addAll(this.getParentPath((Element)notification.getNewValue()));
}
+ }else{
+ targets.addAll(this.getParentPath(element.getOwner()));
}
- break;
+ }break;
+ }
+ }
+ return targets;
+ }
+
+ /**
+ * Get the set of elements that are intended to have their serialization updated
+ *
+ * @param generalization
+ * a generalization relationship that exists between two classifier
+ *
+ * @param changes
+ * the list of changes having affected the given element
+ *
+ * @return targets
+ * the of elements that need to have their serialization updated due to the changes
+ */
+ protected Set<NamedElement> getUpdateTargets(Generalization generalization, List<Notification> changes) {
+ Set<NamedElement> targets = new HashSet<NamedElement>();
+ Iterator<Notification> changesIterator = changes.iterator();
+ while (changesIterator.hasNext()) {
+ Notification notification = changesIterator.next();
+ switch(notification.getEventType()){
+ case Notification.SET:{
+ if(notification.getFeature()==UMLPackage.eINSTANCE.getGeneralization_General()){
+ targets.addAll(this.getParentPath(generalization.getSpecific()));
+ }else if (notification.getFeature()==UMLPackage.eINSTANCE.getGeneralization_Specific()){
+ targets.addAll(this.getParentPath((Element)notification.getOldValue()));
+ targets.addAll(this.getParentPath((Element)notification.getNewValue()));
}
}
+ break;
+ }
}
- /* 2. Handle model modifications implied by Packages */
- else if (target instanceof Package) {
- while (changesIterator.hasNext()) {
- Notification notification = changesIterator.next();
- switch (notification.getEventType()) {
- case Notification.ADD: {
- if (notification.getFeature() == UMLPackage.eINSTANCE.getPackage_PackagedElement()) {
- realTargets.add((NamedElement) notification.getNewValue());
+ return targets;
+ }
+
+ /**
+ * Get the set of elements that are intended to have their serialization updated
+ *
+ * @param element
+ * the package that was modified
+ *
+ * @param changes
+ * the list of changes describing updates applied on this package
+ *
+ * @return targets
+ * the set of element to update
+ */
+ protected Set<NamedElement> getUpdateTargets(Package element, List<Notification> changes) {
+ Set<NamedElement> targets = new HashSet<NamedElement>();
+ Iterator<Notification> changesIterator = changes.iterator();
+ while (changesIterator.hasNext()) {
+ Notification notification = changesIterator.next();
+ switch (notification.getEventType()) {
+ case Notification.ADD: {
+ if (notification.getFeature() == UMLPackage.eINSTANCE.getPackage_PackagedElement()) {
+ targets.addAll(this.getUpdateTarget((NamedElement) notification.getNewValue()));
+ }
+ }
+ break;
+ case Notification.REMOVE: {
+ EStructuralFeature feature = (EStructuralFeature)notification.getFeature();
+ if (feature == UMLPackage.eINSTANCE.getPackage_PackagedElement()) {
+ NamedElement oldValue = (NamedElement) notification.getOldValue();
+ if (oldValue.getModel() != null) {
+ targets.addAll(this.getUpdateTarget((NamedElement) notification.getOldValue()));
}
+ }else if(feature == UMLPackage.eINSTANCE.getNamespace_PackageImport()
+ || feature == UMLPackage.eINSTANCE.getNamespace_ElementImport()){
+ targets.addAll(this.getParentPath(element));
}
- break;
- case Notification.REMOVE: {
- if (notification.getFeature() == UMLPackage.eINSTANCE.getPackage_PackagedElement()) {
- NamedElement oldValue = (NamedElement) notification.getOldValue();
- /* In case a element is deleted from the package */
- if (oldValue.getModel() != null) {
- realTargets.add((NamedElement) notification.getOldValue());
+ }
+ break;
+ }
+ }
+ targets.addAll(this.getUpdateTarget(element));
+ return targets;
+ }
+
+ /**
+ * Retrieve the set of elements that need to be updated afterwards that the given target was modified
+ *
+ * @param target
+ * the source element
+ *
+ * @return targets
+ * the set of elements to update
+ */
+ protected Set<NamedElement> getUpdateTarget(Element target) {
+ Set<NamedElement> targets = new HashSet<NamedElement>();
+ targets.addAll(this.getParentPath(target));
+ targets.addAll(this.getChildren(target));
+ return targets;
+ }
+
+ /**
+ * Find out from a given element the set of children that need to be updated
+ *
+ * @param root
+ *
+ * @return
+ */
+ private Set<NamedElement> getChildren(Element root) {
+ Set<NamedElement> children = new HashSet<NamedElement>();
+ for (Element element : root.getOwnedElements()) {
+ if (element instanceof Package
+ || element instanceof Class) {
+ children.add((NamedElement) element);
+ children.addAll(this.getChildren(element));
+ } else if (element instanceof Enumeration) {
+ children.add((NamedElement) element);
+ } else if (element instanceof DataType) {
+ children.add((NamedElement) element);
+ } else if (element instanceof Signal) {
+ children.add((NamedElement) element);
+ } else if (element instanceof Association) {
+ children.add((NamedElement) element);
+ }
+ }
+ return children;
+ }
+
+ /**
+ * Rewind the parent of the target until the top level package or class
+ *
+ * @param target
+ * the starting point of the of the search
+ *
+ * @return the list of elements that need to be traversed to reach the top level element
+ */
+ private Set<NamedElement> getParentPath(Element target) {
+ Set<NamedElement> targets = new HashSet<NamedElement>();
+ Element owner = target.getOwner();
+ if (owner == null || owner instanceof Model) {
+ targets.add((NamedElement) target);
+ return targets;
+ } else if (owner instanceof Class || owner instanceof Package || owner instanceof Enumeration) {
+ targets.addAll(this.getParentPath(owner));
+ if(!(target instanceof Property)){
+ targets.add((NamedElement) target);
+ }
+ return targets;
+ } else {
+ return targets;
+ }
+ }
+
+ /**
+ * Retrieve all target that need to be updated when a class is modified (e.g. by the adding of a nested classifier)
+ *
+ * @param classifier
+ * the class that was modified
+ *
+ * @param changes
+ * the list of changes registered for this class
+ *
+ * @return targets
+ * the list of targets
+ */
+ protected Set<NamedElement> getUpdateTargets(Classifier classifier, List<Notification> changes) {
+ Set<NamedElement> targets = new HashSet<NamedElement>();
+ Iterator<Notification> changesIterator = changes.iterator();
+ while (changesIterator.hasNext()) {
+ Notification notification = changesIterator.next();
+ switch (notification.getEventType()) {
+
+ /*
+ * 1. if a nested classifier is added, it means parents of the currently modified
+ * element must be synchronized as well as its children. Otherwise (e.g. when a property is added)
+ * only the parents are synchronized.
+ */
+ case Notification.ADD: {
+ if (notification.getFeature() == UMLPackage.eINSTANCE.getClass_NestedClassifier()) {
+ targets.addAll(this.getUpdateTarget((Element) notification.getNewValue()));
+ } else {
+ if(notification.getNewValue() instanceof EnumerationLiteral){
+ Enumeration owner = ((EnumerationLiteral) notification.getNewValue()).getClassifier();
+ if(owner!=null){
+ targets.addAll(this.getParentPath(owner));
}
+ }else if(notification.getNewValue() instanceof Generalization
+ || notification.getNewValue() instanceof ElementImport){
+ targets.addAll(this.getParentPath(classifier));
+ }else{
+ targets.addAll(this.getParentPath((Element) notification.getNewValue()));
}
}
- break;
+ }
+ break;
+
+ /*
+ * 2. if an element is removed from the class then only parents need to be synchronized
+ */
+ case Notification.REMOVE: {
+ EStructuralFeature feature = (EStructuralFeature) notification.getFeature();
+ if(feature == UMLPackage.eINSTANCE.getClassifier_Generalization()
+ || feature == UMLPackage.eINSTANCE.getNamespace_ElementImport()){
+ targets.addAll(this.getParentPath(classifier));
+ }else{
+ NamedElement oldValue = (NamedElement) notification.getOldValue();
+ if (oldValue != null) {
+ targets.addAll(this.getParentPath(classifier));
+ }
}
}
- realTargets.add((Package) target);
+ break;
+ /*
+ * 3. When a property of the class (e.g. its name) is modified then both parents and children
+ * of the currently modified element need to be synchronized
+ */
+ case Notification.SET: {
+ targets.addAll(this.getUpdateTarget(classifier));
+ }
+ break;
+ }
}
- /* 3. */
- else {
- realTargets.add((NamedElement) target);
+ return targets;
+ }
+
+ /**
+ * Retrieve all target that need to be updated when a Feature (e.g. property, operation, reception) is modified
+ *
+ * @param property
+ * the property currently modified
+ *
+ * @param changes
+ * the list of changes registered for this property
+ *
+ * @return target
+ * the set of elements that need to be updated
+ */
+ protected Set<NamedElement> getUpdateTargets(Feature feature, List<Notification> changes) {
+ Set<NamedElement> targets = new HashSet<NamedElement>();
+ Iterator<Notification> changesIterator = changes.iterator();
+ while (changesIterator.hasNext()) {
+ Notification notification = changesIterator.next();
+ switch (notification.getEventType()) {
+ case Notification.SET: {
+ targets.addAll(this.getParentPath(feature.getOwner()));
+ }
+ break;
+ case Notification.REMOVE:{
+ if(notification.getFeature() == UMLPackage.eINSTANCE.getBehavioralFeature_OwnedParameter()){
+ targets.addAll(this.getParentPath(feature.getOwner()));
+ }
+ }
+ break;
+ case Notification.ADD_MANY:{
+ if(notification.getFeature() == UMLPackage.eINSTANCE.getBehavioralFeature_OwnedParameter()){
+ targets.addAll(this.getParentPath(feature.getOwner()));
+ }
+ }
+ break;
+ }
}
- return realTargets;
+ return targets;
}
- public Command synchronize(Element target, List<Notification> changes) {
- CompoundCommand compoundCommand = new CompoundCommand("synchronize");
- for (NamedElement affectedElement : this.getRealTargets(target, changes)) {
- compoundCommand.append(this._synchronize(affectedElement));
+ protected Set<NamedElement> getUpdateTargets(EnumerationLiteral enumerationLiteral, List<Notification> changes) {
+ Set<NamedElement> targets = new HashSet<NamedElement>();
+ Iterator<Notification> changesIterator = changes.iterator();
+ while (changesIterator.hasNext()) {
+ Notification notification = changesIterator.next();
+ switch (notification.getEventType()) {
+ case Notification.SET: {
+ targets.addAll(this.getParentPath(enumerationLiteral.getOwner()));
+ }
+ break;
+ }
}
- return compoundCommand;
+ return targets;
}
+
/**
* Provide a synchronization command for the given target
*
diff --git a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/FUMLElementListener.java b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/FUMLElementListener.java
index 99091e7d039..1c2c9402bde 100644
--- a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/FUMLElementListener.java
+++ b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/FUMLElementListener.java
@@ -68,10 +68,11 @@ public class FUMLElementListener extends ResourceSetListenerImpl {
}
/* 2.2. Calculate synchronization actions through a synchronization scenario */
ISyncScenario scenario = ScenarioFactory.getInstance().createSyncScenario();
- for (Element key : modifications.keySet()) {
- subCommands.append(scenario.synchronize(key, modifications.get(key)));
- }
+ subCommands.append(scenario.synchronize(modifications));
}
return subCommands;
}
+
+
}
+
diff --git a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/filter/FUMLFilter.java b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/filter/FUMLFilter.java
index 6f0a6dbca83..073b5eea365 100644
--- a/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/filter/FUMLFilter.java
+++ b/extraplugins/alf/core/org.eclipse.papyrus.uml.alf.transaction/src/org/eclipse/papyrus/uml/alf/transaction/observation/listener/filter/FUMLFilter.java
@@ -23,16 +23,25 @@ import org.eclipse.uml2.uml.CommunicationPath;
import org.eclipse.uml2.uml.Component;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Enumeration;
+import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.Extension;
+import org.eclipse.uml2.uml.ExtensionEnd;
import org.eclipse.uml2.uml.Generalization;
+import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Node;
+import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Profile;
+import org.eclipse.uml2.uml.Property;
+import org.eclipse.uml2.uml.Reception;
import org.eclipse.uml2.uml.Signal;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.PackageImport;
+import org.eclipse.uml2.uml.Port;
import org.eclipse.uml2.uml.UMLPackage;
import org.eclipse.uml2.uml.resource.UMLResource;
@@ -57,14 +66,28 @@ public class FUMLFilter extends NotificationFilter.Custom {
return this.isDatatypeFeatureListened((EStructuralFeature) feature);
} else if (this.isPackage(notifier)) {
return this.isPackageFeatureListened((EStructuralFeature) feature);
- } else if (this.isAssociation(notifier)) {
+ }/* else if (this.isAssociation(notifier)) {
return this.isAssociationFeatureListener((EStructuralFeature) feature);
- } else if (this.isSignal(notifier)) {
+ }*/ else if (this.isSignal(notifier)) {
return this.isSignalFeatureListened((EStructuralFeature) feature);
} else if (this.isClass(notifier)) {
return this.isClassFeatureListened((EStructuralFeature) feature);
} else if (this.isGeneralization(notifier)) {
return this.isGeneralizationtFeatureListened((EStructuralFeature) feature);
+ }else if(this.isProperty(notifier)){
+ return this.isPropertyFeatureListened((EStructuralFeature)feature);
+ }else if(this.isOperation(notifier)){
+ return this.isOperationFeatureListened((EStructuralFeature)feature);
+ }else if(this.isReception(notifier)){
+ return this.isReceptionFeatureListened((EStructuralFeature)feature);
+ }else if(this.isLiteralUnlimitedNatural(notifier)){
+ return this.isLiteralUnlimitedNaturalFeatureListened((EStructuralFeature)feature);
+ }else if(this.isEnumerationLiteral(notifier)){
+ return this.isEnumerationLiteralFeatureListened((EStructuralFeature)feature);
+ }else if(this.isPackageImport(notifier)){
+ return this.isPackageImportFeatureListened((EStructuralFeature)feature);
+ }else if(this.isElementImport(notifier)){
+ return this.isElementImportFeatureListened((EStructuralFeature)feature);
}
}
return false;
@@ -84,15 +107,12 @@ public class FUMLFilter extends NotificationFilter.Custom {
/*----------------------------------------------------------------------------*/
/* Enforce the filter to respect the fUML subset */
/*----------------------------------------------------------------------------*/
-
- private boolean isGeneralization(Object notifier) {
- return notifier instanceof Generalization;
- }
-
/**
+ * Check if the given notifier is strictly a Class
*
* @param notifier
- * @return
+ *
+ * @return true if constraint is verified false otherwise
*/
private boolean isClass(Object notifier) {
if (notifier instanceof Class &&
@@ -107,18 +127,22 @@ public class FUMLFilter extends NotificationFilter.Custom {
}
/**
+ * Check if the given notifier is strictly a Signal
*
* @param notifier
- * @return
+ *
+ * @return true if constraint is verified false otherwise
*/
private boolean isSignal(Object notifier) {
return notifier instanceof Signal;
}
/**
+ * Check if the given notifier is strictly a DataType
*
* @param notifier
- * @return
+ *
+ * @return true if constraint is verified false otherwise
*/
private boolean isDataType(Object notifier) {
if (notifier instanceof DataType
@@ -129,9 +153,11 @@ public class FUMLFilter extends NotificationFilter.Custom {
}
/**
+ * Check if the given notifier is strictly a Package
*
* @param notifier
- * @return
+ *
+ * @return true if constraint is verified false otherwise
*/
private boolean isPackage(Object notifier) {
if (notifier != null
@@ -144,19 +170,24 @@ public class FUMLFilter extends NotificationFilter.Custom {
}
/**
+ * Check if the given notifier is strictly an Enumeration
*
* @param notifier
- * @return
+ *
+ * @return true if constraint is verified false otherwise
*/
private boolean isEnumeration(Object notifier) {
return notifier instanceof Enumeration;
}
/**
+ * Check if the given notifier is strictly an Association
*
* @param notifier
- * @return
+ *
+ * @return true if constraint is verified false otherwise
*/
+ @SuppressWarnings("unused")
private boolean isAssociation(Object notifier) {
if (notifier instanceof Association
&& !(notifier instanceof AssociationClass)
@@ -166,6 +197,93 @@ public class FUMLFilter extends NotificationFilter.Custom {
}
return false;
}
+
+ /**
+ * Check if the given notifier is strictly a Generalization
+ *
+ * @param notifier
+ *
+ * @return true if constraint is verified false otherwise
+ */
+ private boolean isGeneralization(Object notifier) {
+ return notifier instanceof Generalization;
+ }
+
+ /**
+ * Check if the given notifier is strictly a property
+ *
+ * @param notifier
+ *
+ * @return true if constraint is verified false otherwise
+ */
+ private boolean isProperty(Object notifier){
+ if(notifier instanceof Property
+ && !(notifier instanceof Port)
+ && !(notifier instanceof ExtensionEnd) ){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isLiteralUnlimitedNatural(Object notifier){
+ return notifier instanceof LiteralUnlimitedNatural;
+ }
+
+ /**
+ * Check if the given notifier is strictly an Operation
+ *
+ * @param notifier
+ *
+ * @return true if constraint is verified false otherwise
+ */
+ private boolean isOperation(Object notifier){
+ return notifier instanceof Operation;
+ }
+
+
+ /**
+ * Check if the given notifier is strictly a Reception
+ *
+ * @param notifier
+ *
+ * @return true if constraint is verified false otherwise
+ */
+ private boolean isReception(Object notifier){
+ return notifier instanceof Reception;
+ }
+
+ /**
+ * Check if the given notifier is strictly an Enumeration literal
+ *
+ * @param notifier
+ *
+ * @return true if constraint is verified false otherwise
+ */
+ private boolean isEnumerationLiteral(Object notifier){
+ return notifier instanceof EnumerationLiteral;
+ }
+
+ /**
+ * Check if the given notifier is strictly a PackageImport
+ *
+ * @param notifier
+ *
+ * @return true if constraint is verified false otherwise
+ */
+ private boolean isPackageImport(Object notifier){
+ return notifier instanceof PackageImport;
+ }
+
+ /**
+ * Check if the given notifier is strictly an ElementImport
+ *
+ * @param notifier
+ *
+ * @return true if constraint is verified false otherwise
+ */
+ private boolean isElementImport(Object notifier){
+ return notifier instanceof ElementImport;
+ }
/*----------------------------------------------------------------------------*/
/* Low level checks encoding the UML meta-model hierarchy */
@@ -196,7 +314,7 @@ public class FUMLFilter extends NotificationFilter.Custom {
private boolean isNamespaceFeatureListened(EStructuralFeature feature) {
if (UMLPackage.eINSTANCE.getNamespace_ElementImport() == feature
- || UMLPackage.eINSTANCE.getNamespace_ImportedMember() == feature
+ //|| UMLPackage.eINSTANCE.getNamespace_ImportedMember() == feature [Detected when element import changes]
|| UMLPackage.eINSTANCE.getNamespace_Member() == feature
|| UMLPackage.eINSTANCE.getNamespace_OwnedMember() == feature
|| UMLPackage.eINSTANCE.getNamespace_PackageImport() == feature
@@ -228,7 +346,7 @@ public class FUMLFilter extends NotificationFilter.Custom {
|| UMLPackage.eINSTANCE.getClassifier_IsAbstract() == feature
|| UMLPackage.eINSTANCE.getClassifier_Attribute() == feature
|| UMLPackage.eINSTANCE.getClassifier_Feature() == feature
- || UMLPackage.eINSTANCE.getClassifier_General() == feature
+ //|| UMLPackage.eINSTANCE.getClassifier_General() == feature [Detected when generalization changes]
|| UMLPackage.eINSTANCE.getClassifier_Generalization() == feature
|| this.isNamespaceFeatureListened(feature)
|| this.isTypeFeatureListened(feature)) {
@@ -271,6 +389,7 @@ public class FUMLFilter extends NotificationFilter.Custom {
return false;
}
+ @SuppressWarnings("unused")
private boolean isAssociationFeatureListener(EStructuralFeature feature) {
return UMLPackage.eINSTANCE.getAssociation_OwnedEnd() == feature || this.isClassifierFeatureListened(feature);
}
@@ -286,4 +405,155 @@ public class FUMLFilter extends NotificationFilter.Custom {
private boolean isEnumerationFeatureListened(EStructuralFeature feature) {
return UMLPackage.eINSTANCE.getEnumeration_OwnedLiteral() == feature || this.isDatatypeFeatureListened(feature);
}
+
+ private boolean isRedefinableElementFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getRedefinableElement_IsLeaf() == feature
+ || UMLPackage.eINSTANCE.getRedefinableElement_RedefinedElement() == feature
+ || UMLPackage.eINSTANCE.getRedefinableElement_RedefinitionContext() == feature
+ || this.isNamedElementFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isFeatureFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getFeature_IsStatic() == feature
+ || UMLPackage.eINSTANCE.getFeature_FeaturingClassifier() == feature
+ || this.isRedefinableElementFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isMultiplicityElementFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getMultiplicityElement_IsOrdered() == feature
+ || UMLPackage.eINSTANCE.getMultiplicityElement_IsUnique() == feature
+ || UMLPackage.eINSTANCE.getMultiplicityElement_Lower() == feature
+ || UMLPackage.eINSTANCE.getMultiplicityElement_Upper() == feature){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isTypedElementFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getTypedElement_Type() == feature
+ || this.isNamedElementFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isStructuralFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getStructuralFeature_IsReadOnly() == feature
+ || this.isFeatureFeatureListened(feature)
+ || this.isMultiplicityElementFeatureListened(feature)
+ || this.isTypedElementFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isPropertyFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getProperty_Aggregation() == feature
+ || UMLPackage.eINSTANCE.getProperty_IsComposite() == feature
+ || UMLPackage.eINSTANCE.getProperty_IsDerived() == feature
+ || UMLPackage.eINSTANCE.getProperty_IsDerivedUnion() == feature
+ || UMLPackage.eINSTANCE.getProperty_IsID()==feature
+ || UMLPackage.eINSTANCE.getProperty_Association() == feature
+ || UMLPackage.eINSTANCE.getProperty_Class() == feature
+ || UMLPackage.eINSTANCE.getProperty_Datatype() == feature
+ || UMLPackage.eINSTANCE.getProperty_Opposite() == feature
+ || UMLPackage.eINSTANCE.getProperty_OwningAssociation() == feature
+ || this.isStructuralFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isValueSpecificationFeatureListened(EStructuralFeature feature){
+ if(this.isTypedElementFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isLiteralSpecificationFeatureListened(EStructuralFeature feature){
+ if(this.isValueSpecificationFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isLiteralUnlimitedNaturalFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getLiteralUnlimitedNatural_Value() == feature
+ || this.isLiteralSpecificationFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isBehavioralFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getBehavioralFeature_Concurrency() == feature
+ || UMLPackage.eINSTANCE.getBehavioralFeature_OwnedParameter() == feature
+ || UMLPackage.eINSTANCE.getBehavioralFeature_Method() == feature
+ || this.isFeatureFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isOperationFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getOperation_IsQuery() == feature
+ || UMLPackage.eINSTANCE.getOperation_RedefinedOperation() == feature
+ || UMLPackage.eINSTANCE.getOperation_Type() == feature
+ || UMLPackage.eINSTANCE.getOperation_Class() == feature
+ || this.isBehavioralFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isReceptionFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getReception_Signal() == feature
+ || this.isBehavioralFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isInstanceSpecificationFeatureListener(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getInstanceSpecification_Classifier() == feature
+ || UMLPackage.eINSTANCE.getInstanceSpecification_Slot() == feature
+ || this.isNamedElementFeatureListened(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isEnumerationLiteralFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getEnumerationLiteral_Enumeration() == feature
+ || this.isInstanceSpecificationFeatureListener(feature)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isPackageImportFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getPackageImport_Visibility() == feature
+ || UMLPackage.eINSTANCE.getPackageImport_ImportedPackage() == feature
+ || UMLPackage.eINSTANCE.getPackageImport_ImportingNamespace() == feature){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isElementImportFeatureListened(EStructuralFeature feature){
+ if(UMLPackage.eINSTANCE.getElementImport_ImportedElement() == feature
+ || UMLPackage.eINSTANCE.getElementImport_ImportingNamespace() == feature
+ || UMLPackage.eINSTANCE.getElementImport_Visibility() == feature
+ || UMLPackage.eINSTANCE.getElementImport_Alias() == feature){
+ return true;
+ }
+ return false;
+ }
}

Back to the top