From e5ef3c3723a42d3837760a21c433bd97a8cce24d Mon Sep 17 00:00:00 2001 From: Camille Letavernier Date: Mon, 30 Jul 2018 16:44:55 +0200 Subject: Bug 536640: [Sequence Diagram] Ensure that graphics & semantics remain consistent for Durations https://bugs.eclipse.org/bugs/show_bug.cgi?id=536640 Change-Id: I7458b84062b529a98780a729d8f27bfcab50814c Signed-off-by: Camille Letavernier --- .../helpers/advice/AbstractDurationLinkAdvice.java | 87 ++++++++++++++++ .../advice/DurationConstraintLinkAdvice.java | 31 ++++++ .../advice/DurationObservationLinkAdvice.java | 31 ++++++ .../diagram/sequence/util/DurationLinkUtil.java | 112 +++++++++++++++++++++ .../SequenceDiagram.elementtypesconfigurations | 18 ++-- 5 files changed, 273 insertions(+), 6 deletions(-) create mode 100644 plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/AbstractDurationLinkAdvice.java create mode 100644 plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/DurationConstraintLinkAdvice.java create mode 100644 plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/DurationObservationLinkAdvice.java diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/AbstractDurationLinkAdvice.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/AbstractDurationLinkAdvice.java new file mode 100644 index 00000000000..4d70849c3a2 --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/AbstractDurationLinkAdvice.java @@ -0,0 +1,87 @@ +/***************************************************************************** + * Copyright (c) 2018 CEA LIST, EclipseSource and others. + * + * 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: + * EclipseSource - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.sequence.edit.helpers.advice; + +import java.util.Collection; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature.Setting; +import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice; +import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; +import org.eclipse.gmf.runtime.notation.Connector; +import org.eclipse.gmf.runtime.notation.NotationPackage; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils; +import org.eclipse.papyrus.infra.services.edit.service.IElementEditService; +import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.SequenceDiagramEditPart; +import org.eclipse.papyrus.uml.diagram.sequence.util.DurationLinkUtil; + +/** + *

+ * Abstract sequence diagram advice to clear DurationLinks when the corresponding + * semantic Duration element becomes inconsistent (typically, the source/target changes + * or is removed). + *

+ */ +public abstract class AbstractDurationLinkAdvice extends AbstractEditHelperAdvice { + + private EClass durationElementType; + private EReference eventsReference; + private String durationLinkType; + + protected AbstractDurationLinkAdvice(EClass durationElementType, EReference eventsReference, String durationLinkType) { + this.durationElementType = durationElementType; + this.eventsReference = eventsReference; + this.durationLinkType = durationLinkType; + } + + @Override + protected ICommand getAfterSetCommand(SetRequest request) { + if (request.getFeature() == eventsReference && durationElementType.isInstance(request.getElementToEdit())) { + Collection usages = EMFHelper.getUsages(request.getElementToEdit()); + + // We need to delegate to the command provider; otherwise the view is not correctly destroyed, + // and the diagram may still display a ghost connection (referencing a view that is no longer + // attached to the notation model) + IElementEditService provider = ElementEditServiceUtils.getCommandProvider(request.getElementToEdit()); + if (provider == null) { + return null; + } + + CompositeCommand deletions = new CompositeCommand("Delete inconsistent DurationLink views"); + for (Setting usage : usages) { + if (usage.getEObject() instanceof Connector && usage.getEStructuralFeature() == NotationPackage.Literals.VIEW__ELEMENT) { + Connector connector = (Connector) usage.getEObject(); + if (durationLinkType.equals(connector.getType()) // + && connector.getDiagram() != null // + && SequenceDiagramEditPart.MODEL_ID.equals(connector.getDiagram().getType())) { + if (!DurationLinkUtil.isConsistent(connector, request)) { + // Retrieve delete command from the Element Edit service + DestroyElementRequest destroyRequest = new DestroyElementRequest(request.getEditingDomain(), connector, false); + ICommand deleteCommand = provider.getEditCommand(destroyRequest); + deletions.add(deleteCommand); + } + } + } + } + return deletions.isEmpty() ? null : deletions.reduce(); + } + return super.getAfterSetCommand(request); + } + +} diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/DurationConstraintLinkAdvice.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/DurationConstraintLinkAdvice.java new file mode 100644 index 00000000000..7bd4d30d6b9 --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/DurationConstraintLinkAdvice.java @@ -0,0 +1,31 @@ +/***************************************************************************** + * Copyright (c) 2018 CEA LIST, EclipseSource and others. + * + * 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: + * EclipseSource - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.sequence.edit.helpers.advice; + +import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.DurationConstraintLinkEditPart; +import org.eclipse.uml2.uml.UMLPackage; + +/** + *

+ * A sequence diagram advice to clear {@link DurationConstraintLinkEditPart DurationConstraint links} when the + * constraint's constrained elements are changed. + *

+ */ +public class DurationConstraintLinkAdvice extends AbstractDurationLinkAdvice { + + public DurationConstraintLinkAdvice() { + super(UMLPackage.Literals.DURATION_CONSTRAINT, UMLPackage.Literals.CONSTRAINT__CONSTRAINED_ELEMENT, DurationConstraintLinkEditPart.VISUAL_ID); + } + +} diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/DurationObservationLinkAdvice.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/DurationObservationLinkAdvice.java new file mode 100644 index 00000000000..6a3c92258c8 --- /dev/null +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/edit/helpers/advice/DurationObservationLinkAdvice.java @@ -0,0 +1,31 @@ +/***************************************************************************** + * Copyright (c) 2018 CEA LIST, EclipseSource and others. + * + * 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: + * EclipseSource - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.diagram.sequence.edit.helpers.advice; + +import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.DurationObservationLinkEditPart; +import org.eclipse.uml2.uml.UMLPackage; + +/** + *

+ * A sequence diagram advice to clear {@link DurationObservationLinkEditPart DurationObservation links} when the + * observation's events are changed. + *

+ */ +public class DurationObservationLinkAdvice extends AbstractDurationLinkAdvice { + + public DurationObservationLinkAdvice() { + super(UMLPackage.Literals.DURATION_OBSERVATION, UMLPackage.Literals.DURATION_OBSERVATION__EVENT, DurationObservationLinkEditPart.VISUAL_ID); + } + +} diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/DurationLinkUtil.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/DurationLinkUtil.java index 09e3876e2f5..600773dab24 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/DurationLinkUtil.java +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/util/DurationLinkUtil.java @@ -20,6 +20,7 @@ import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PointList; import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.emf.ecore.EObject; import org.eclipse.gef.EditPart; import org.eclipse.gef.requests.CreateConnectionRequest; import org.eclipse.gef.requests.CreateRequest; @@ -30,10 +31,21 @@ import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElemen import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest; import org.eclipse.gmf.runtime.emf.type.core.IElementType; import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; +import org.eclipse.gmf.runtime.notation.Connector; +import org.eclipse.gmf.runtime.notation.IdentityAnchor; +import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.infra.gmfdiag.common.service.palette.AspectUnspecifiedTypeConnectionTool.CreateAspectUnspecifiedTypeConnectionRequest; +import org.eclipse.papyrus.uml.diagram.sequence.anchors.AnchorConstants; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.DurationConstraintLinkEditPart; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.DurationObservationLinkEditPart; import org.eclipse.papyrus.uml.diagram.sequence.providers.UMLElementTypes; +import org.eclipse.uml2.uml.DurationConstraint; +import org.eclipse.uml2.uml.DurationObservation; +import org.eclipse.uml2.uml.ExecutionSpecification; +import org.eclipse.uml2.uml.Message; +import org.eclipse.uml2.uml.MessageEnd; +import org.eclipse.uml2.uml.OccurrenceSpecification; /** *

@@ -168,4 +180,104 @@ public class DurationLinkUtil { request.getConnectionEditPart() instanceof DurationObservationLinkEditPart; } + /** + *

+ * Test if the connector view is consistent with a new value. If the new value is not a List, + * this method always returns true. Otherwise, the list items will be compared with the + * semantic source/target of the given connector. + *

+ * + * @param connector + * A connector representing a DurationLink (Constraint or Observation) in the Sequence Diagram + * @param setRequest + * A {@link SetRequest} modifying a duration link source/target (for {@link DurationConstraint#getConstrainedElements()} + * or {@link DurationObservation#getEvents()}, + * @return + * true if the Connector is consistent with the new proposed value, false if the connector + * is no longer consistent. If the result is false, actions should be taken to preserve the diagram + * consistency. + */ + public static boolean isConsistent(Connector connector, SetRequest setRequest) { + Object newValue = setRequest.getValue(); + if (false == newValue instanceof List) { + // Not supported; do nothing. Probably shouldn't happen anyway. + return true; + } + + List values = (List) newValue; + if (values.isEmpty()) { + // FIXME Workaround for the Properties View. When using the multi-reference editor's dialog, + // the editor will first send a clear() request, then a addAll() request; so we'd always + // destroy the connector, even if it's actually still valid. To be safe, we ignore this case + // Keeping an invalid connector in the diagram is better than destroying a valid one. + return true; + } + + View sourceView = connector.getSource(); + String sourceAnchor = connector.getSourceAnchor() instanceof IdentityAnchor ? ((IdentityAnchor) connector.getSourceAnchor()).getId() : ""; + + View targetView = connector.getTarget(); + String targetAnchor = connector.getSourceAnchor() instanceof IdentityAnchor ? ((IdentityAnchor) connector.getTargetAnchor()).getId() : ""; + + if (sourceView == null || targetView == null) { + return false; + } + + if (values.isEmpty()) { + return false; + } + + Object sourceEvent = values.get(0); + if (sourceEvent != DurationLinkUtil.findSemanticOccurrence(sourceView, sourceAnchor)) { + return false; + } + + if (values.size() > 1) { // source != target + Object targetEvent = values.get(1); + return targetEvent == DurationLinkUtil.findSemanticOccurrence(targetView, targetAnchor); + } else { // source == target + return sourceEvent == DurationLinkUtil.findSemanticOccurrence(targetView, targetAnchor); + } + } + + /** + * Find the semantic {@link OccurrenceSpecification} represented by the given connectorEnd. + * The connector should be the source or target of a DurationLink connector. + * + * @param connectorEnd + * the source or target of a DurationLink connector + * @param anchorTerminal + * The connection anchor corresponding to the given connector end. + * @return + * The semantic occurrence specification represented by the given connector end (View), or null + * if the view doesn't represent a valid {@link OccurrenceSpecification}. + */ + public static OccurrenceSpecification findSemanticOccurrence(View connectorEnd, String anchorTerminal) { + EObject semantic = connectorEnd.getElement(); + if (semantic instanceof OccurrenceSpecification) { + return (OccurrenceSpecification) semantic; + } else if (semantic instanceof ExecutionSpecification) { + switch (anchorTerminal) { + case AnchorConstants.START_TERMINAL: + return ((ExecutionSpecification) semantic).getStart(); + case AnchorConstants.END_TERMINAL: + return ((ExecutionSpecification) semantic).getFinish(); + default: + return null; + } + } else if (semantic instanceof Message) { + switch (anchorTerminal) { + case AnchorConstants.START_TERMINAL: + MessageEnd sendEvent = ((Message) semantic).getSendEvent(); + return sendEvent instanceof OccurrenceSpecification ? (OccurrenceSpecification) sendEvent : null; + case AnchorConstants.END_TERMINAL: + MessageEnd receiveEvent = ((Message) semantic).getReceiveEvent(); + return receiveEvent instanceof OccurrenceSpecification ? (OccurrenceSpecification) receiveEvent : null; + default: + return null; + } + } + return null; + } + } diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/SequenceDiagram.elementtypesconfigurations b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/SequenceDiagram.elementtypesconfigurations index bb84ce2dda9..8fb60f354be 100644 --- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/SequenceDiagram.elementtypesconfigurations +++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/SequenceDiagram.elementtypesconfigurations @@ -1,10 +1,16 @@ - - - + + + - - - + + + + + + + + + -- cgit v1.2.3