Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2018-04-23 19:36:28 +0000
committerNicolas FAUVERGUE2018-05-29 13:30:23 +0000
commite65c18ff964d6407a3c750de581984eafd9044ee (patch)
tree5cf684ab932e46d69000886d5e9bf624e605f49f /plugins/uml
parentc18fa4d3b4a2c896323a3be417f13c58541b2166 (diff)
downloadorg.eclipse.papyrus-e65c18ff964d6407a3c750de581984eafd9044ee.tar.gz
org.eclipse.papyrus-e65c18ff964d6407a3c750de581984eafd9044ee.tar.xz
org.eclipse.papyrus-e65c18ff964d6407a3c750de581984eafd9044ee.zip
Bug 533676: [Sequence Diagram] Validation should be triggered after
creation of CombinedFragment or InteractionOperand Add custom well-formedness rules to check that messages and execution specifications do not cross interaction operand boundaries. Ensure that re-sizing of an interaction operand triggers validation of that operand and the interaction fragments that it contains, plus any messages originating or terminating within it. Because the default operand of a new combined fragment is now resized upon creation, a new operand is likewise validated for its contents. Fix validation hook and diagnostician extension point schema definitions to match reality of the extension point implementations. Remove UI contributions for validation, to avoid workflow interrution. Validation framework is still slow, but less intrusive for the user. A preference may control the validation activation on user actions. Update the failing compilation on gmfdiag.common.tests. Add a preference to switch on or off the validation. Change-Id: Ic7d83eb18315ce714dc7c71bff38276f330ef260 Also-by: RĂ©mi Schnekenburger <rschnekenburger@eclipsesource.com> Signed-off-by: Christian W. Damus <give.a.damus@gmail.com>
Diffstat (limited to 'plugins/uml')
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/META-INF/MANIFEST.MF18
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/Messages.java5
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/messages.properties1
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/preferences/CustomDiagramGeneralPreferencePage.java17
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/ResizeOperandEditPolicy.java18
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/AsyncValidateCommand.java157
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/OperandDiagnostician.java103
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/OperandFilter.java37
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/SequenceOCLRegistration.java46
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/seqd_constraints.ocl44
-rw-r--r--plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/plugin.xml10
11 files changed, 446 insertions, 10 deletions
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/META-INF/MANIFEST.MF b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/META-INF/MANIFEST.MF
index e960778de98..f4da8ebfc22 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/META-INF/MANIFEST.MF
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/META-INF/MANIFEST.MF
@@ -15,7 +15,7 @@ Bundle-ClassPath: .
Bundle-Name: %pluginName
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Require-Bundle: org.eclipse.ui.navigator;visibility:=reexport;bundle-version="[3.6.0,4.0.0)",
+Require-Bundle: org.eclipse.ui.navigator;bundle-version="[3.6.0,4.0.0)";visibility:=reexport,
org.eclipse.ui.navigator.resources;bundle-version="[3.5.0,4.0.0)",
org.eclipse.gmf.runtime.diagram.ui.render;bundle-version="[1.7.0,2.0.0)",
org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide;bundle-version="[1.7.0,2.0.0)",
@@ -25,10 +25,10 @@ Require-Bundle: org.eclipse.ui.navigator;visibility:=reexport;bundle-version="[3
org.eclipse.gmf.runtime.diagram.ui.providers.ide;bundle-version="[1.7.0,2.0.0)",
org.eclipse.papyrus.uml.service.types;bundle-version="[3.0.0,4.0.0)",
org.eclipse.papyrus.uml.appearance;bundle-version="[2.0.0,3.0.0)",
- org.eclipse.emf.ecore;visibility:=reexport;bundle-version="[2.12.0,3.0.0)",
- org.eclipse.emf.ecore;visibility:=reexport;bundle-version="[2.12.0,3.0.0)",
- org.eclipse.emf.ecore.edit;visibility:=reexport;bundle-version="[2.9.0,3.0.0)",
- org.eclipse.emf.validation;visibility:=reexport;bundle-version="[1.8.0,2.0.0)",
+ org.eclipse.emf.ecore;bundle-version="[2.12.0,3.0.0)";visibility:=reexport,
+ org.eclipse.emf.ecore;bundle-version="[2.12.0,3.0.0)";visibility:=reexport,
+ org.eclipse.emf.ecore.edit;bundle-version="[2.9.0,3.0.0)";visibility:=reexport,
+ org.eclipse.emf.validation;bundle-version="[1.8.0,2.0.0)";visibility:=reexport,
org.eclipse.papyrus.infra.gmfdiag.hyperlink;bundle-version="[3.0.0,4.0.0)",
org.eclipse.papyrus.uml.internationalization.utils;bundle-version="[1.0.0,2.0.0)",
org.eclipse.papyrus.infra.internationalization.utils;bundle-version="[1.0.0,2.0.0)",
@@ -53,8 +53,8 @@ Require-Bundle: org.eclipse.ui.navigator;visibility:=reexport;bundle-version="[3
org.eclipse.gmf.runtime.diagram.ui.properties,
org.eclipse.gmf.runtime.diagram.ui.providers,
org.eclipse.gmf.runtime.diagram.ui.resources.editor,
- org.eclipse.uml2.uml;visibility:=reexport;bundle-version="[5.3.0,6.0.0)",
- org.eclipse.uml2.uml.edit;visibility:=reexport;bundle-version="[5.3.0,6.0.0)",
+ org.eclipse.uml2.uml;bundle-version="[5.3.0,6.0.0)";visibility:=reexport,
+ org.eclipse.uml2.uml.edit;bundle-version="[5.3.0,6.0.0)";visibility:=reexport,
org.eclipse.gmf.runtime.draw2d.ui;visibility:=reexport,
org.eclipse.gef,
org.eclipse.papyrus.extensionpoints.editors;bundle-version="[3.0.0,4.0.0)",
@@ -65,7 +65,9 @@ Require-Bundle: org.eclipse.ui.navigator;visibility:=reexport;bundle-version="[3
org.eclipse.papyrus.uml.diagram.menu,
org.eclipse.draw2d;visibility:=reexport,
org.eclipse.gmf.runtime.notation;visibility:=reexport,
- org.eclipse.papyrus.infra.viewpoints.policy;bundle-version="[2.0.0,4.0.0)"
+ org.eclipse.papyrus.infra.viewpoints.policy;bundle-version="[2.0.0,4.0.0)",
+ org.eclipse.papyrus.uml.service.validation;bundle-version="[2.1.0,3.0.0)",
+ org.eclipse.papyrus.infra.services.validation;bundle-version="[3.0.0,4.0.0)"
Bundle-Vendor: %providerName
Bundle-Version: 5.0.0.qualifier
Bundle-ManifestVersion: 2
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/Messages.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/Messages.java
index 7fbd29d4eb7..9967bbfe3ff 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/Messages.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/Messages.java
@@ -71,6 +71,11 @@ public class Messages extends NLS {
*/
public static String DiagramsPreferencePage_createNoExecutionSpecification;
+ /**
+ * label specifying that validation should be triggered after edition
+ */
+ public static String DiagramsPreferencePage_triggerValidation_label;
+
/*************************************************************************
* Command labels
************************************************************************/
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/messages.properties b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/messages.properties
index 527a9404009..d4e3ecb55bc 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/messages.properties
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/messages/messages.properties
@@ -6,6 +6,7 @@ DiagramsPreferencePage_createBehaviorExecutionSpecification=A Behavior Execution
DiagramsPreferencePage_createActionExecutionSpecificationAndReply=An Action Execution Specification and a Reply Message
DiagramsPreferencePage_createActionExecutionSpecification=An Action Execution Specification
DiagramsPreferencePage_createNoExecutionSpecification=Nothing
+DiagramsPreferencePage_triggerValidation_label=Trigger validation when editing the diagram (This may have effect on performances)
Commands_DropDestructionOccurenceSpecification_Label=Drop Destruction Occurrence Specification
Commands_CreateExecutionSpecification_Label=Execution Specification Automatic Creation with Message
Commands_DropDestructionOccurenceSpecification_Label=Drop Destruction Occurrence Specification
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/preferences/CustomDiagramGeneralPreferencePage.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/preferences/CustomDiagramGeneralPreferencePage.java
index 4762396a4be..a72e526a228 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/preferences/CustomDiagramGeneralPreferencePage.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/preferences/CustomDiagramGeneralPreferencePage.java
@@ -39,6 +39,8 @@ public class CustomDiagramGeneralPreferencePage extends DiagramPreferencePage {
*/
private RadioGroupFieldEditor executionSpecificationWithAsyncMsg = null;
+ private BooleanFieldEditor triggerValidation;
+
/**
* preference key for asynchronous messages
*/
@@ -71,6 +73,13 @@ public class CustomDiagramGeneralPreferencePage extends DiagramPreferencePage {
public static final int PREF_MOVE_BELOW_ELEMENTS_AT_MESSAGE_CREATION_VALUE = 40;
/**
+ * preference key to trigger model validation after edition.
+ *
+ * @since 5.0
+ */
+ public static final String PREF_TRIGGER_ASYNC_VALIDATION = "PREF_TRIGGER_ASYNC_VALIDATION"; //$NON-NLS-1$
+
+ /**
* possible preference values
*/
public static final String CHOICE_BEHAVIOR_AND_REPLY = "CHOICE_BEHAVIOR_AND_REPLY"; //$NON-NLS-1$
@@ -106,6 +115,7 @@ public class CustomDiagramGeneralPreferencePage extends DiagramPreferencePage {
addField(executionSpecificationWithSyncMsg);
addField(executionSpecificationWithAsyncMsg);
+
Group otherGroup = new Group(parent, SWT.NONE);
otherGroup.setLayout(new GridLayout(2, false));
GridData otherGroupGridData = new GridData(GridData.FILL_HORIZONTAL);
@@ -115,6 +125,9 @@ public class CustomDiagramGeneralPreferencePage extends DiagramPreferencePage {
otherGroup.setText(Messages.CustomDiagramGeneralPreferencePage_othersGroupLabel);
addField(new BooleanFieldEditor(PREF_MOVE_BELOW_ELEMENTS_AT_MESSAGE_DOWN, Messages.CustomDiagramGeneralPreferencePage_MoveBelowElementsAtMessageDownDescription, otherGroup));
addField(new IntegerFieldEditor(PREF_MOVE_BELOW_ELEMENTS_AT_MESSAGE_CREATION, Messages.CustomDiagramGeneralPreferencePage_MinimumSpaceBelowMessageAtCreation, otherGroup));
+ triggerValidation = new BooleanFieldEditor(PREF_TRIGGER_ASYNC_VALIDATION,
+ Messages.DiagramsPreferencePage_triggerValidation_label, otherGroup);
+ addField(triggerValidation);
}
/**
@@ -143,6 +156,7 @@ public class CustomDiagramGeneralPreferencePage extends DiagramPreferencePage {
{ Messages.DiagramsPreferencePage_createActionExecutionSpecification, CHOICE_ACTION },
{ Messages.DiagramsPreferencePage_createNoExecutionSpecification, CHOICE_NONE }
}, composite);
+
}
/**
@@ -158,5 +172,8 @@ public class CustomDiagramGeneralPreferencePage extends DiagramPreferencePage {
preferenceStore.setDefault(PREF_MOVE_BELOW_ELEMENTS_AT_MESSAGE_DOWN, true);
preferenceStore.setDefault(PREF_MOVE_BELOW_ELEMENTS_AT_MESSAGE_CREATION, PREF_MOVE_BELOW_ELEMENTS_AT_MESSAGE_CREATION_VALUE);
+ // by default, validation is activated.
+ preferenceStore.setDefault(PREF_TRIGGER_ASYNC_VALIDATION, false);
+
}
}
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/ResizeOperandEditPolicy.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/ResizeOperandEditPolicy.java
index 9bc2572c095..b5a925b1ae0 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/ResizeOperandEditPolicy.java
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/referencialgrilling/ResizeOperandEditPolicy.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2017, 2018 CEA LIST, EclipseSource and others.
+ * Copyright (c) 2017, 2018 CEA LIST, EclipseSource, Christian W. Damus, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -9,6 +9,7 @@
* Contributors:
* CEA LIST - Initial API and implementation
* EclipseSource - Bug 533770
+ * Christian W. Damus - bug 533676
*
*****************************************************************************/
@@ -20,6 +21,7 @@ import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
+import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
@@ -29,11 +31,14 @@ import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.infra.gmfdiag.common.helper.NotationHelper;
import org.eclipse.papyrus.uml.diagram.sequence.command.SetResizeAndLocationCommand;
+import org.eclipse.papyrus.uml.diagram.sequence.validation.AsyncValidateCommand;
+import org.eclipse.uml2.uml.InteractionOperand;
/**
@@ -81,6 +86,17 @@ public class ResizeOperandEditPolicy extends GraphicalEditPolicy {
Object currentEditPart = editParts.get(0);
updateCurrentChildSize(compositeCommand, changeBoundsRequest, editingDomain, currentEditPart);
+
+ if (!compositeCommand.isEmpty() && (currentEditPart instanceof IGraphicalEditPart)
+ && compositeCommand.canExecute()) {
+
+ EObject object = ((IGraphicalEditPart) currentEditPart).resolveSemanticElement();
+ if (object instanceof InteractionOperand) {
+ InteractionOperand operand = (InteractionOperand) object;
+ // In case the containment of interaction fragments changes, validate
+ AsyncValidateCommand.get(operand).ifPresent(compositeCommand::add);
+ }
+ }
return new ICommandProxy(compositeCommand);
}
return null;
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/AsyncValidateCommand.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/AsyncValidateCommand.java
new file mode 100644
index 00000000000..4f43cc45447
--- /dev/null
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/AsyncValidateCommand.java
@@ -0,0 +1,157 @@
+/*****************************************************************************
+ * Copyright (c) 2018 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.uml.diagram.sequence.validation;
+
+import static org.eclipse.papyrus.uml.diagram.sequence.util.OccurrenceSpecificationHelper.findExecutionWith;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.transaction.util.TransactionUtil;
+import org.eclipse.gmf.runtime.common.core.command.ICommand;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.papyrus.infra.emf.gmf.command.INonDirtying;
+import org.eclipse.papyrus.infra.services.validation.ValidationTool;
+import org.eclipse.papyrus.infra.services.validation.commands.ValidateSubtreeCommand;
+import org.eclipse.papyrus.uml.diagram.sequence.command.AsynchronousCommand;
+import org.eclipse.papyrus.uml.diagram.sequence.part.UMLDiagramEditorPlugin;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.uml2.uml.ExecutionSpecification;
+import org.eclipse.uml2.uml.InteractionOperand;
+import org.eclipse.uml2.uml.Message;
+import org.eclipse.uml2.uml.MessageEnd;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.OccurrenceSpecification;
+import org.eclipse.uml2.uml.util.UMLSwitch;
+
+/**
+ * An asynchronous validation command.
+ */
+public class AsyncValidateCommand extends AsynchronousCommand implements INonDirtying {
+
+ /**
+ * Initializes me with the {@code object to validate}.
+ *
+ * @param object
+ * the object to validate later
+ */
+ public AsyncValidateCommand(EObject object) {
+ super("Validate", TransactionUtil.getEditingDomain(object), () -> validate(object));
+ }
+
+ private static ICommand validate(EObject object) {
+ ValidateSubtreeCommand cmd = new UMLSwitch<ValidateSubtreeCommand>() {
+
+ @Override
+ public ValidateSubtreeCommand caseInteractionOperand(InteractionOperand operand) {
+ return new ValidateOperandCommand(operand);
+ }
+
+ @Override
+ public ValidateSubtreeCommand defaultCase(EObject object) {
+ return new ValidateSubtreeCommand(object);
+ }
+ }.doSwitch(object);
+
+ cmd.disableUIFeedback();
+
+ return cmd;
+ }
+
+ /**
+ * Returns a new {@link AsyncValidateCommand} if preference to validate after edition is set to <code>true</code>.
+ *
+ * @return a {@link Optional} {@link AsyncValidateCommand} or an empty one if the preference is set to no validation.
+ */
+ public static Optional<AsyncValidateCommand> get(EObject object) {
+ IPreferenceStore store = UMLDiagramEditorPlugin.getInstance().getPreferenceStore();
+ Boolean triggerValidation = store.getBoolean(org.eclipse.papyrus.uml.diagram.sequence.preferences.CustomDiagramGeneralPreferencePage.PREF_TRIGGER_ASYNC_VALIDATION);
+ return Optional.ofNullable(triggerValidation ? new AsyncValidateCommand(object) : null);
+ }
+
+ static Stream<Message> messages(InteractionOperand operand) {
+ return operand.getFragments().stream()
+ .filter(MessageEnd.class::isInstance).map(MessageEnd.class::cast)
+ .map(MessageEnd::getMessage)
+ .filter(Objects::nonNull).distinct();
+ }
+
+ static Stream<ExecutionSpecification> nonOwnedExecutions(InteractionOperand operand) {
+ return operand.getFragments().stream()
+ .filter(OccurrenceSpecification.class::isInstance).map(OccurrenceSpecification.class::cast)
+ .map(AsyncValidateCommand::getExecution)
+ .filter(Objects::nonNull)
+ .filter(exec -> exec.getOwner() != operand)
+ .distinct();
+ }
+
+ static ExecutionSpecification getExecution(OccurrenceSpecification occurrence) {
+ return Optional.ofNullable(findExecutionWith(occurrence, true))
+ .orElseGet(() -> findExecutionWith(occurrence, false));
+ }
+
+ //
+ // Nested types
+ //
+
+ private static class ValidateOperandCommand extends ValidateSubtreeCommand {
+ private final InteractionOperand operand;
+
+ ValidateOperandCommand(InteractionOperand operand) {
+ super(operand, new OperandDiagnostician());
+
+ this.operand = operand;
+ }
+
+ @Override
+ protected void handleDiagnostic(IProgressMonitor monitor, Diagnostic diagnostic, EObject validateElement, Shell shell) {
+ // Do not show a dialog, as in the original version since the user sees the result directly
+ // in the model explorer
+ Resource resource = getValidationResource();
+ // final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ if (resource != null) {
+ if (validateElement != null) {
+ // In an interaction operand, we validate also the messages and execution
+ // specifications that are at least partially within it. We have to be
+ // careful about also removing existing markers for these related elements
+ // because the Diagnostician isn't responsible for that
+ List<NamedElement> others = Stream.concat(messages(operand), nonOwnedExecutions(operand))
+ .collect(Collectors.toList());
+ int markersToCreate = diagnostic.getChildren().size();
+
+ SubMonitor sub = SubMonitor.convert(monitor, 1 + others.size() + markersToCreate);
+
+ ValidationTool vt = new ValidationTool(validateElement, resource);
+
+ // Delete existing markers
+ vt.deleteSubMarkers(sub.newChild(1));
+ others.forEach(el -> new ValidationTool(el, resource).deleteSubMarkers(sub.newChild(1)));
+
+ // Create new markers
+ vt.createMarkers(diagnostic, sub.newChild(markersToCreate));
+
+ sub.done();
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/OperandDiagnostician.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/OperandDiagnostician.java
new file mode 100644
index 00000000000..959cef67e2a
--- /dev/null
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/OperandDiagnostician.java
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * Copyright (c) 2018 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.uml.diagram.sequence.validation;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.common.util.DiagnosticChain;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.uml.diagram.sequence.util.OccurrenceSpecificationHelper;
+import org.eclipse.papyrus.uml.service.validation.internal.UMLDiagnostician;
+import org.eclipse.uml2.uml.ExecutionSpecification;
+import org.eclipse.uml2.uml.InteractionOperand;
+import org.eclipse.uml2.uml.Message;
+import org.eclipse.uml2.uml.MessageEnd;
+import org.eclipse.uml2.uml.OccurrenceSpecification;
+
+/**
+ * A diagnostician for validation of an {@link InteractionOperand} sub-tree only.
+ * This includes messages that have at least one end within the operand.
+ * <b>Note</b> that this diagnostician should never be used in context of
+ * general user-driven model validation.
+ */
+@SuppressWarnings("restriction")
+public class OperandDiagnostician extends UMLDiagnostician {
+
+ /**
+ * Initializes me.
+ */
+ public OperandDiagnostician() {
+ super();
+ }
+
+ @Override
+ protected boolean doValidateContents(EObject eObject, DiagnosticChain diagnostics, Map<Object, Object> context) {
+ boolean result = true;
+
+ // Note that a message end can also be an occurrence specification, so
+ // do both of these validations (not an 'else if')
+ if (eObject instanceof MessageEnd) {
+ // Validate the message, also
+ result = validateMessage((MessageEnd) eObject, diagnostics, context);
+ }
+ if (eObject instanceof OccurrenceSpecification) {
+ // Validate the execution specification, also (if any)
+ result &= validateExecutionSpecification((OccurrenceSpecification) eObject, diagnostics, context);
+ }
+
+ if (result || diagnostics != null) {
+ result &= super.doValidateContents(eObject, diagnostics, context);
+ }
+
+ return result;
+ }
+
+ protected boolean validateMessage(MessageEnd messageEnd, DiagnosticChain diagnostics, Map<Object, Object> context) {
+ Message message = messageEnd.getMessage();
+
+ return (message == null) || validate(message, diagnostics, context);
+ }
+
+ protected boolean validateExecutionSpecification(OccurrenceSpecification occurrence, DiagnosticChain diagnostics, Map<Object, Object> context) {
+ ExecutionSpecification execution = OccurrenceSpecificationHelper.findExecutionWith(occurrence, true);
+ if (execution == null) {
+ // Maybe it's finished by this occurrence
+ execution = OccurrenceSpecificationHelper.findExecutionWith(occurrence, false);
+ }
+
+ return (execution == null) || validate(execution, diagnostics, context);
+ }
+
+ @Override
+ public boolean validate(EObject eObject, DiagnosticChain diagnostics, Map<Object, Object> context) {
+ // Avoid redundant validation of things in operands that we might also validate
+ // even when they aren't contained by those operands (per the above)
+ if (context != null && (eObject instanceof Message || eObject instanceof ExecutionSpecification)) {
+ @SuppressWarnings("unchecked")
+ Set<EObject> validated = (Set<EObject>) context.get("operand.validated");
+ if (validated == null) {
+ validated = new HashSet<>();
+ context.put("operand.validated", validated);
+ }
+ if (!validated.add(eObject)) {
+ // Already checked it
+ return true;
+ }
+ }
+
+ return super.validate(eObject, diagnostics, context);
+ }
+}
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/OperandFilter.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/OperandFilter.java
new file mode 100644
index 00000000000..9410d96a9b9
--- /dev/null
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/OperandFilter.java
@@ -0,0 +1,37 @@
+/*****************************************************************************
+ * Copyright (c) 2018 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.uml.diagram.sequence.validation;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.infra.services.validation.IValidationFilter;
+import org.eclipse.uml2.uml.InteractionOperand;
+
+/**
+ * A validation filter that matches {@link InteractionOperand}s.
+ */
+public class OperandFilter implements IValidationFilter {
+
+ /**
+ * Initializes me.
+ */
+ public OperandFilter() {
+ super();
+ }
+
+ @Override
+ public boolean isApplicable(EObject element) {
+ return element instanceof InteractionOperand;
+ }
+
+}
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/SequenceOCLRegistration.java b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/SequenceOCLRegistration.java
new file mode 100644
index 00000000000..0837f9658f1
--- /dev/null
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/custom-src/org/eclipse/papyrus/uml/diagram/sequence/validation/SequenceOCLRegistration.java
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * Copyright (c) 2018 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.uml.diagram.sequence.validation;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.papyrus.uml.diagram.sequence.part.UMLDiagramEditorPlugin;
+import org.eclipse.papyrus.uml.service.validation.AbstractOCLRegistration;
+import org.eclipse.uml2.uml.Profile;
+
+/**
+ * Validation extension for OCL constraints specific to Interactions in a sequence diagram.
+ */
+public class SequenceOCLRegistration extends AbstractOCLRegistration {
+
+ /**
+ * Initializes me.
+ */
+ public SequenceOCLRegistration() {
+ super();
+ }
+
+ @Override
+ protected URI getOCLFileURI() {
+ return URI.createPlatformPluginURI(UMLDiagramEditorPlugin.ID + "/model/seqd_constraints.ocl", true); //$NON-NLS-1$
+ }
+
+ @Override
+ protected boolean isApplicable(EObject element) {
+ EObject root = EcoreUtil.getRootContainer(element);
+ return root instanceof org.eclipse.uml2.uml.Package && !(root instanceof Profile);
+ }
+
+}
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/seqd_constraints.ocl b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/seqd_constraints.ocl
new file mode 100644
index 00000000000..debcd0d3cd6
--- /dev/null
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/model/seqd_constraints.ocl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ */
+
+import 'http://www.eclipse.org/uml2/5.0.0/UML'
+
+package UML
+
+context Element
+
+-- A helper operation that reports a problem as error severity instead of warning.
+def: asError(ok: Boolean): Boolean = if ok then ok else null endif
+
+context Message
+
+--
+-- The ends of a message that are not Gates are all owned by the same
+-- Interaction or InteractionOperand.
+--
+inv crosses_no_boundaries('Message crosses an interaction operand boundary.'):
+ let ends = Set{sendEvent, receiveEvent}->excluding(null)->reject(oclIsKindOf(Gate)) in
+ asError(ends->notEmpty() implies ends.owner->asSet()->size() = 1)
+
+
+context ExecutionSpecification
+
+--
+-- The start and finish events if an execution specification are both owned
+-- by the same Interaction or InteractionOperand.
+--
+inv crosses_no_boundaries('Execution specification crosses an interaction operand boundary.'):
+ let events = Set{start, finish}->excluding(null) in
+ asError(events->notEmpty() implies events.owner->asSet()->size() = 1)
+
+endpackage
diff --git a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/plugin.xml b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/plugin.xml
index c321e41f226..981de30f226 100644
--- a/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/plugin.xml
+++ b/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence/plugin.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<!--
- Copyright (c) 2009, 2014, 2017 CEA and others.
+ Copyright (c) 2009, 2018 CEA, Christian W. Damus, and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
@@ -11,6 +11,7 @@
Contributors:
CEA - Initial API and implementation
Christian W. Damus (CEA) - bug 323802
+ Christian W. Damus - bug 533676
-->
<plugin>
@@ -637,4 +638,11 @@
<?gmfgen generated="true"?>
</extension>
+ <extension
+ point="org.eclipse.papyrus.infra.services.validation.validationHooks">
+ <validationHook
+ id="org.eclipse.papyrus.uml.diagram.sequence.ocl"
+ filter="org.eclipse.papyrus.uml.service.validation.internal.UMLFilter"
+ hook="org.eclipse.papyrus.uml.diagram.sequence.validation.SequenceOCLRegistration"/>
+ </extension>
</plugin>

Back to the top