Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian W. Damus2018-04-20 17:14:56 -0400
committerChristian W. Damus2018-04-25 09:51:29 -0400
commit8e55acdb1ce621632d451001c9099a4784deba89 (patch)
tree2532c34255a1a3abce53f4563d46f620e993a689
parentfa3a1409f7f679d42834a4e89e1d22dd9c115ebe (diff)
downloadorg.eclipse.papyrus-8e55acdb1ce621632d451001c9099a4784deba89.tar.gz
org.eclipse.papyrus-8e55acdb1ce621632d451001c9099a4784deba89.tar.xz
org.eclipse.papyrus-8e55acdb1ce621632d451001c9099a4784deba89.zip
Bug 533682: [Sequence Diagram] Deletion of the InteractionOperand should not delete underlying elements
When deleting an interaction operand, instead of deleting contained elements, promote them to the operand or interaction containing the combined fragment. Change-Id: I677807d79ed08c6fac61069aefd37b8c4068238e Signed-off-by: Christian W. Damus <give.a.damus@gmail.com>
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.service.types/model/uml.elementtypesconfigurations2
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/CombinedFragmentEditHelper.java46
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/CombinedFragmentEditHelperAdvice.java17
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/InteractionContainerDeletionContext.java247
-rw-r--r--plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/InteractionFragmentContainerEditHelperAdvice.java92
-rw-r--r--tests/junit/framework/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java25
-rw-r--r--tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.di2
-rw-r--r--tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.notation96
-rw-r--r--tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.uml26
-rw-r--r--tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/src/org/eclipse/papyrus/uml/diagram/sequence/tests/bug/CombinedFragmentRegressionTest.java119
-rw-r--r--tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.classpath2
-rw-r--r--tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.settings/org.eclipse.jdt.core.prefs6
-rw-r--r--tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/META-INF/MANIFEST.MF2
-rw-r--r--tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/resource/interactions/bug533682.uml28
-rw-r--r--tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/src/org/eclipse/papyrus/uml/service/types/tests/deletion/InteractionDeletionTest.java257
-rw-r--r--tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/src/org/eclipse/papyrus/uml/service/types/tests/suites/AllTests.java4
16 files changed, 914 insertions, 57 deletions
diff --git a/plugins/uml/org.eclipse.papyrus.uml.service.types/model/uml.elementtypesconfigurations b/plugins/uml/org.eclipse.papyrus.uml.service.types/model/uml.elementtypesconfigurations
index 4ef481946e4..b18c277ad2c 100644
--- a/plugins/uml/org.eclipse.papyrus.uml.service.types/model/uml.elementtypesconfigurations
+++ b/plugins/uml/org.eclipse.papyrus.uml.service.types/model/uml.elementtypesconfigurations
@@ -1171,4 +1171,6 @@
<adviceBindingsConfigurations xsi:type="elementtypesconfigurations:AdviceBindingConfiguration" xmi:id="_sk_AgANEEeeK2pILzAGx9w" identifier="org.eclipse.papyrus.uml.advice.Element" target="org.eclipse.papyrus.uml.Element" inheritance="all" editHelperAdviceClassName="org.eclipse.papyrus.uml.service.types.helper.advice.ElementHelperAdvice"/>
<adviceBindingsConfigurations xsi:type="elementtypesconfigurations:AdviceBindingConfiguration" xmi:id="_pUAxYDKLEee2hdQGBOZDMQ" identifier="org.eclipse.papyrus.uml.advice.DurationConstraint" target="org.eclipse.papyrus.uml.DurationConstraint" inheritance="all" editHelperAdviceClassName="org.eclipse.papyrus.uml.service.types.helper.advice.DurationConstraintEditHelperAdvice"/>
<adviceBindingsConfigurations xsi:type="elementtypesconfigurations:AdviceBindingConfiguration" xmi:id="_RDj3kHOtEeer__BSotNaQg" identifier="org.eclipse.papyrus.uml.advice.CombinedFragment" target="org.eclipse.papyrus.uml.CombinedFragment" inheritance="all" editHelperAdviceClassName="org.eclipse.papyrus.uml.service.types.helper.advice.CombinedFragmentEditHelperAdvice"/>
+ <adviceBindingsConfigurations xsi:type="elementtypesconfigurations:AdviceBindingConfiguration" xmi:id="_U6DhsETXEeimO7ZhVBpjkg" identifier="org.eclipse.papyrus.uml.advice.InteractionOperand" target="org.eclipse.papyrus.uml.InteractionOperand" inheritance="all" editHelperAdviceClassName="org.eclipse.papyrus.uml.service.types.helper.advice.InteractionFragmentContainerEditHelperAdvice"/>
+ <adviceBindingsConfigurations xsi:type="elementtypesconfigurations:AdviceBindingConfiguration" xmi:id="_VVC0kETXEeimO7ZhVBpjkg" identifier="org.eclipse.papyrus.uml.advice.Interaction" target="org.eclipse.papyrus.uml.Interaction" inheritance="all" editHelperAdviceClassName="org.eclipse.papyrus.uml.service.types.helper.advice.InteractionFragmentContainerEditHelperAdvice"/>
</elementtypesconfigurations:ElementTypeSetConfiguration>
diff --git a/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/CombinedFragmentEditHelper.java b/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/CombinedFragmentEditHelper.java
index a94fb7d9538..5e98c116ab2 100644
--- a/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/CombinedFragmentEditHelper.java
+++ b/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/CombinedFragmentEditHelper.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2016 CEA LIST and others.
+ * Copyright (c) 2016, 2018 CEA LIST, 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
@@ -8,6 +8,7 @@
*
* Contributors:
* CEA LIST - Initial API and implementation
+ * Christian W. Damus - bug 533682
*
*****************************************************************************/
@@ -21,7 +22,6 @@ 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.commands.ConfigureElementCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest;
-import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
import org.eclipse.uml2.uml.CombinedFragment;
/**
@@ -40,6 +40,7 @@ public class CombinedFragmentEditHelper extends ElementEditHelper {
ICommand configureCommand = new ConfigureElementCommand(req) {
+ @Override
protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
CombinedFragment combinedFragment = (CombinedFragment) req.getElementToConfigure();
return CommandResult.newOKCommandResult(combinedFragment);
@@ -50,45 +51,4 @@ public class CombinedFragmentEditHelper extends ElementEditHelper {
}
- /**
- * @see org.eclipse.papyrus.infra.gmfdiag.common.helper.DefaultEditHelper#getDestroyElementCommand(org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest)
- *
- * @param req
- * @return
- */
- @Override
- protected ICommand getDestroyElementCommand(DestroyElementRequest req) {
- return super.getDestroyElementCommand(req);
- // EObject elementToDestroy = req.getElementToDestroy();
- // if (elementToDestroy instanceof CombinedFragment) {
- // CombinedFragment combinedFragment = (CombinedFragment) elementToDestroy;
- // IElementEditService provider = ElementEditServiceUtils.getCommandProvider(elementToDestroy);
- // if (provider != null) {
- // // Retrieve delete command from the Element Edit service
- // ICommand deleteCommand = super.getDestroyElementCommand(req);
- //// if (deleteCommand != null) {
- //// if (elementToDestroy instanceof CombinedFragment) {
- ////
- //// CompositeCommand deleteAll = new CompositeCommand(req.getLabel());
- //// deleteAll.add(deleteCommand);
- //// CompositeCommand deleteCfOnly = new CompositeCommand(req.getLabel());
- ////
- //// // remove children from operands and append to parent combined fragment
- //// for (InteractionOperand op : combinedFragment.getOperands()) {
- //// deleteCfOnly.add(new MoveOperandFragmentsCommand(combinedFragment, op, new MoveOperandFragmentEditRequest(req.getEditingDomain(), combinedFragment)));
- //// }
- //// deleteCfOnly.add(new CombinedFragmentDestroyCommand(req.getEditingDomain(), provider, req));
- ////
- //// return new SelectAndDeleteCommand(deleteAll, deleteCfOnly, new String[] { "Delete all", "Keep contents" });
- //// } else {
- // return deleteCommand;
- //// }
- //// }
- // }
- // }
- // return UnexecutableCommand.INSTANCE;
-
-
- }
-
}
diff --git a/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/CombinedFragmentEditHelperAdvice.java b/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/CombinedFragmentEditHelperAdvice.java
index b7eadaafdcf..e02ff6e2ca4 100644
--- a/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/CombinedFragmentEditHelperAdvice.java
+++ b/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/CombinedFragmentEditHelperAdvice.java
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (c) 2017 CEA LIST and others.
+ * Copyright (c) 2017, 2018 CEA LIST, 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
@@ -8,6 +8,7 @@
*
* Contributors:
* Nicolas FAUVERGUE (CEA LIST) nicolas.fauvergue@cea.fr - Initial API and implementation
+ * Christian W. Damus - bug 533682
*
*****************************************************************************/
@@ -21,6 +22,7 @@ import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.emf.type.core.commands.ConfigureElementCommand;
import org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice;
import org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest;
+import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
import org.eclipse.papyrus.uml.tools.utils.NamedElementUtil;
import org.eclipse.uml2.uml.CombinedFragment;
import org.eclipse.uml2.uml.InteractionOperand;
@@ -33,11 +35,6 @@ import org.eclipse.uml2.uml.UMLFactory;
*/
public class CombinedFragmentEditHelperAdvice extends AbstractEditHelperAdvice {
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice#getBeforeConfigureCommand(org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest)
- */
@Override
protected ICommand getBeforeConfigureCommand(final ConfigureRequest request) {
return new ConfigureElementCommand(request) {
@@ -66,4 +63,12 @@ public class CombinedFragmentEditHelperAdvice extends AbstractEditHelperAdvice {
return interactionOperand;
}
+ @Override
+ protected ICommand getBeforeDestroyElementCommand(DestroyElementRequest req) {
+ // If it's an operand, record that it's being deleted
+ InteractionContainerDeletionContext.deleting(req);
+
+ return super.getBeforeDestroyElementCommand(req);
+ }
+
}
diff --git a/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/InteractionContainerDeletionContext.java b/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/InteractionContainerDeletionContext.java
new file mode 100644
index 00000000000..2bf5baa1eb5
--- /dev/null
+++ b/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/InteractionContainerDeletionContext.java
@@ -0,0 +1,247 @@
+/*****************************************************************************
+ * 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.service.types.helper.advice;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.common.core.command.ICommand;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
+import org.eclipse.uml2.uml.CombinedFragment;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.GeneralOrdering;
+import org.eclipse.uml2.uml.Interaction;
+import org.eclipse.uml2.uml.InteractionFragment;
+import org.eclipse.uml2.uml.InteractionOperand;
+import org.eclipse.uml2.uml.UMLPackage;
+
+/**
+ * A {@link DestroyElementRequest} parameter tracking the deletion of {@link InteractionFragment}
+ * containers in the context of an {@link Interaction}.
+ */
+class InteractionContainerDeletionContext {
+
+ private static String PARAMETER_NAME = "papyrus.uml.InteractionContainerDeletionContext"; //$NON-NLS-1$
+
+ /**
+ * Set of {@link Interaction}s, {@link CombinedFragment}s, and
+ * {@link InteractionOperand}s being destroyed.
+ */
+ private final Set<InteractionFragment> interactionContainersBeingDestroyed = new HashSet<>();
+
+ /** Next insertion index of interaction fragments being added to a container. */
+ private final Map<InteractionFragment, Integer> insertionIndexByContainer = new HashMap<>();
+
+ private final TransactionalEditingDomain domain;
+
+ /**
+ * Initializes me with the initial destroy request.
+ */
+ private InteractionContainerDeletionContext(DestroyElementRequest request) {
+ super();
+
+ this.domain = request.getEditingDomain();
+ request.setParameter(PARAMETER_NAME, this);
+ }
+
+ static Optional<InteractionContainerDeletionContext> get(DestroyElementRequest request) {
+ Optional<InteractionContainerDeletionContext> result = Optional.ofNullable(request.getParameter(PARAMETER_NAME))
+ .filter(InteractionContainerDeletionContext.class::isInstance)
+ .map(InteractionContainerDeletionContext.class::cast);
+
+ if (isInteractionContainer(request.getElementToDestroy())) {
+ if (!result.isPresent()) {
+ result = Optional.of(new InteractionContainerDeletionContext(request));
+ }
+
+ result.get().add(request);
+ }
+
+ return result;
+ }
+
+ static void deleting(DestroyElementRequest request) {
+ if (isInteractionContainer(request.getElementToDestroy())) {
+ // Ensure that we record that this object is being destroyed
+ get(request);
+ }
+ }
+
+ private static boolean isInteractionContainer(EObject object) {
+ return object instanceof InteractionOperand
+ || object instanceof CombinedFragment
+ || object instanceof Interaction;
+ }
+
+ private void add(DestroyElementRequest request) {
+ EObject elementToDestroy = request.getElementToDestroy();
+ interactionContainersBeingDestroyed.add((InteractionFragment) elementToDestroy);
+ }
+
+ boolean isBeingDestroyed(Interaction interaction) {
+ return interactionContainersBeingDestroyed.contains(interaction);
+ }
+
+ boolean isBeingDestroyed(CombinedFragment combinedFragment) {
+ return interactionContainersBeingDestroyed.contains(combinedFragment);
+ }
+
+ boolean isBeingDestroyed(InteractionOperand operand) {
+ return interactionContainersBeingDestroyed.contains(operand);
+ }
+
+ /**
+ * Query the new container into which a {@code fragment} should be moved instead of
+ * destroyed.
+ *
+ * @param fragment
+ * a fragment for which destruction is requested
+ * @return the container, either an {@link Interaction} or an {@link InteractionOperand},
+ * into which to move the {@code fragment}, or {@code null} if it should be destroyed
+ */
+ InteractionFragment getNewContainerFor(InteractionFragment fragment) {
+ // Interaction operands are, of course, always just deleted
+ return (fragment instanceof InteractionOperand) ? null : doGetNewContainerFor(fragment);
+ }
+
+ /**
+ * Query the new container into which a {@code generalOrdering} should be moved instead of
+ * destroyed.
+ *
+ * @param generalOrdering
+ * a general ordering for which destruction is requested
+ * @return the container, either an {@link Interaction} or an {@link InteractionOperand},
+ * into which to move the {@code fragment}, or {@code null} if it should be destroyed
+ */
+ InteractionFragment getNewContainerFor(GeneralOrdering generalOrdering) {
+ return doGetNewContainerFor(generalOrdering);
+ }
+
+ /**
+ * @precondition the {@code element} is owned by an {@link InteractionFragment}
+ */
+ private InteractionFragment doGetNewContainerFor(Element element) {
+ InteractionFragment owner = (InteractionFragment) element.getOwner();
+ if (owner instanceof InteractionOperand && !isBeingDestroyed((InteractionOperand) owner)) {
+ // This element is being destroyed on its own merits
+ return null;
+ } else if (owner instanceof Interaction && !isBeingDestroyed((Interaction) owner)) {
+ // This element is being destroyed on its own merits
+ return null;
+ }
+
+ InteractionFragment result = null;
+
+ for (; result == null && owner != null; owner = (InteractionFragment) owner.getOwner()) {
+ if (owner instanceof InteractionOperand && !isBeingDestroyed((InteractionOperand) owner)) {
+ result = owner;
+ } else if (owner instanceof Interaction) {
+ if (!isBeingDestroyed((Interaction) owner)) {
+ result = owner;
+ } // else the interaction is being destroyed, so everything must be
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ ICommand getDestroyCommand(InteractionFragment fragment) {
+ InteractionFragment container = getNewContainerFor(fragment);
+ return container != null ? move(fragment, container) : null;
+ }
+
+ ICommand move(InteractionFragment fragment, InteractionFragment into) {
+ // Find the index in the new container into which add the fragment
+ Integer insertionIndex = insertionIndexByContainer.get(into);
+ if (insertionIndex == null) {
+ // Insert at the index of the nearest combined fragment that is not being deleted
+ CombinedFragment nearestCF = null;
+ for (InteractionFragment owner = (InteractionFragment) fragment.getOwner(); //
+ nearestCF == null && owner != null && !(owner instanceof Interaction); //
+ owner = (InteractionFragment) owner.getOwner()) {
+
+ if (owner instanceof CombinedFragment) {
+ CombinedFragment cf = (CombinedFragment) owner;
+ if (!isBeingDestroyed(cf)) {
+ nearestCF = cf;
+ }
+ }
+ }
+
+ if (nearestCF != null && into == nearestCF.getOwner()) {
+ // Get the list of fragments containing this CF in its enclosing operand
+ EList<InteractionFragment> fragments = nearestCF.getEnclosingOperand() != null
+ ? nearestCF.getEnclosingOperand().getFragments()
+ : nearestCF.getEnclosingInteraction().getFragments();
+ insertionIndex = fragments.indexOf(nearestCF) + 1;
+ insertionIndexByContainer.put(into, insertionIndex);
+ }
+ }
+
+ int index = -1;
+ if (insertionIndex != null) {
+ index = insertionIndex;
+ insertionIndexByContainer.put(into, index + 1); // Increment for the next fragment
+ }
+
+ EReference containment = (into instanceof InteractionOperand)
+ ? UMLPackage.Literals.INTERACTION_OPERAND__FRAGMENT
+ : UMLPackage.Literals.INTERACTION__FRAGMENT;
+ return move(fragment, into, containment, index);
+ }
+
+ ICommand getDestroyCommand(GeneralOrdering generalOrdering) {
+ InteractionFragment container = getNewContainerFor(generalOrdering);
+ return container != null ? move(generalOrdering, container) : null;
+ }
+
+ ICommand move(GeneralOrdering generalOrdering, InteractionFragment into) {
+ // Index doesn't matter because general orderings are, themselves, unordered
+ return move(generalOrdering, into, UMLPackage.Literals.INTERACTION_FRAGMENT__GENERAL_ORDERING, -1);
+ }
+
+ <E extends Element> ICommand move(E element, InteractionFragment into, EReference containment, int index) {
+ // Can't use edit-helpers for this because there is no support for insertion index in
+ // the MoveRequest
+ return new AbstractTransactionalCommand(domain, "Move Interaction Element", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
+ @SuppressWarnings("unchecked")
+ EList<E> list = (EList<E>) into.eGet(containment);
+ if (index < 0) {
+ list.add(element);
+ } else if (list.size() < index) {
+ return CommandResult.newErrorCommandResult("index out of bounds: " + index); //$NON-NLS-1$
+ } else {
+ list.add(index, element);
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ };
+ }
+}
diff --git a/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/InteractionFragmentContainerEditHelperAdvice.java b/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/InteractionFragmentContainerEditHelperAdvice.java
new file mode 100644
index 00000000000..d0edddb3758
--- /dev/null
+++ b/plugins/uml/org.eclipse.papyrus.uml.service.types/src/org/eclipse/papyrus/uml/service/types/helper/advice/InteractionFragmentContainerEditHelperAdvice.java
@@ -0,0 +1,92 @@
+/*****************************************************************************
+ * 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.service.types.helper.advice;
+
+import static org.eclipse.gmf.runtime.common.core.command.CompositeCommand.compose;
+
+import java.util.Optional;
+
+import org.eclipse.emf.ecore.EObject;
+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.IEditCommandRequest;
+import org.eclipse.uml2.uml.GeneralOrdering;
+import org.eclipse.uml2.uml.Interaction;
+import org.eclipse.uml2.uml.InteractionFragment;
+import org.eclipse.uml2.uml.InteractionOperand;
+
+/**
+ * Edit-helper advice for elements that own {@link InteractionFragment}s, being
+ * {@link Interaction}s and {@link InteractionOperand}s.
+ *
+ * @since 3.1
+ */
+public class InteractionFragmentContainerEditHelperAdvice extends AbstractEditHelperAdvice {
+
+ /**
+ * Initializes me.
+ */
+ public InteractionFragmentContainerEditHelperAdvice() {
+ super();
+ }
+
+ /**
+ * In the case of a contained {@link InteractionFragment} to be destroyed, we don't
+ * actually destroy it but just re-assign it to the containing {@link Interaction}
+ * or {@link InteractionOperand}, unless that container also is being destroyed, in
+ * which case we bump up the containment at most to the root {@link Interaction}.
+ * If that {@link Interaction} also is being destroyed, then we just destroy the
+ * fragment because the entire content of the interaction is being destroyed.
+ */
+ @Override
+ protected ICommand getBeforeDestroyElementCommand(DestroyElementRequest req) {
+ ICommand superResult = super.getBeforeDestroyElementCommand(req);
+
+ // If it's a combined fragment, record that it's being deleted
+ InteractionContainerDeletionContext.deleting(req);
+
+ EObject elementToDestroy = req.getElementToDestroy();
+
+ Optional<ICommand> result = Optional.empty();
+ if (elementToDestroy instanceof InteractionFragment) {
+ InteractionFragment fragment = (InteractionFragment) elementToDestroy;
+ Optional<InteractionContainerDeletionContext> context = InteractionContainerDeletionContext.get(req);
+ result = context.map(ctx -> ctx.getDestroyCommand(fragment));
+ } else if (elementToDestroy instanceof GeneralOrdering) {
+ GeneralOrdering generalOrdering = (GeneralOrdering) elementToDestroy;
+ Optional<InteractionContainerDeletionContext> context = InteractionContainerDeletionContext.get(req);
+ result = context.map(ctx -> ctx.getDestroyCommand(generalOrdering));
+ }
+
+ // If we have an advice command, it should replace the 'instead' command
+ result.ifPresent(advice -> instead(req, advice));
+
+ return result.map(advice -> compose(superResult, advice)).orElse(superResult);
+ }
+
+ ICommand instead(IEditCommandRequest request, ICommand instead) {
+ request.setParameter(IEditCommandRequest.REPLACE_DEFAULT_COMMAND, Boolean.TRUE);
+ return instead;
+ }
+
+ @Override
+ protected ICommand getAfterDestroyElementCommand(DestroyElementRequest request) {
+ // In case I replaced the default command, don't propagate that parameter
+ // to any destroy-dependents requests
+ request.getParameters().remove(IEditCommandRequest.REPLACE_DEFAULT_COMMAND);
+
+ return super.getAfterDestroyElementCommand(request);
+ }
+}
diff --git a/tests/junit/framework/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java b/tests/junit/framework/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java
index 4a972e13e7e..932b51085ee 100644
--- a/tests/junit/framework/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java
+++ b/tests/junit/framework/org.eclipse.papyrus.junit.utils/src/org/eclipse/papyrus/junit/utils/rules/PapyrusEditorFixture.java
@@ -8,7 +8,7 @@
*
* Contributors:
* Christian W. Damus (CEA) - Initial API and implementation
- * Christian W. Damus - bugs 433206, 465416, 434983, 483721, 469188, 485220, 491542, 497865, 533673
+ * Christian W. Damus - bugs 433206, 465416, 434983, 483721, 469188, 485220, 491542, 497865, 533673, 533682
* Thanh Liem PHAN (ALL4TEC) thanhliem.phan@all4tec.net - Bug 521550
*****************************************************************************/
package org.eclipse.papyrus.junit.utils.rules;
@@ -63,6 +63,7 @@ import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand;
@@ -76,6 +77,7 @@ import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequestFactory;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
+import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.Shape;
import org.eclipse.gmf.runtime.notation.View;
@@ -95,6 +97,8 @@ import org.eclipse.papyrus.infra.nattable.common.editor.AbstractEMFNattableEdito
import org.eclipse.papyrus.infra.nattable.common.modelresource.PapyrusNattableModel;
import org.eclipse.papyrus.infra.nattable.manager.table.INattableModelManager;
import org.eclipse.papyrus.infra.nattable.model.nattable.Table;
+import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils;
+import org.eclipse.papyrus.infra.services.edit.service.IElementEditService;
import org.eclipse.papyrus.infra.tools.util.PlatformHelper;
import org.eclipse.papyrus.infra.tools.util.TypeUtils;
import org.eclipse.papyrus.infra.ui.editor.IMultiDiagramEditor;
@@ -1532,4 +1536,23 @@ public class PapyrusEditorFixture extends AbstractModelFixture<TransactionalEdit
public static Dimension sized(int width, int height) {
return new Dimension(width, height);
}
+
+ /**
+ * Delete an edit-part from the diagram.
+ *
+ * @param editPart
+ * the edit-part to delete
+ *
+ * @since 2.2
+ */
+ public void delete(EditPart editPart) {
+ EObject toDestroy = editPart.getAdapter(EObject.class);
+ EObject container = toDestroy.eContainer();
+ DestroyElementRequest request = new DestroyElementRequest(toDestroy, false);
+ IElementEditService edit = ElementEditServiceUtils.getCommandProvider(container);
+ ICommand delete = edit.getEditCommand(request);
+
+ assertThat("No delete command obtained", delete, notNullValue());
+ execute(delete);
+ }
}
diff --git a/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.di b/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.di
new file mode 100644
index 00000000000..8c549eecdc6
--- /dev/null
+++ b/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.di
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<architecture:ArchitectureDescription xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:architecture="http://www.eclipse.org/papyrus/infra/core/architecture" contextId="org.eclipse.papyrus.infra.services.edit.TypeContext"/>
diff --git a/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.notation b/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.notation
new file mode 100644
index 00000000000..57f7bfc85a1
--- /dev/null
+++ b/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.notation
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/gmfdiag/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_QKU0YEMwEeiEZ5Jtfh6-KA" type="PapyrusUMLSequenceDiagram" name="sequence" measurementUnit="Pixel">
+ <children xmi:type="notation:Shape" xmi:id="_QKU0YUMwEeiEZ5Jtfh6-KA" type="Interaction_Shape">
+ <children xmi:type="notation:DecorationNode" xmi:id="_QKU0YkMwEeiEZ5Jtfh6-KA" type="Interaction_NameLabel">
+ <element xmi:type="uml:Interaction" href="bug533682.uml#_POkWwEMwEeiEZ5Jtfh6-KA"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_QKU0Y0MwEeiEZ5Jtfh6-KA" type="Interaction_SubfragmentCompartment">
+ <children xmi:type="notation:Shape" xmi:id="_FQ-74ESnEeilLIdbxjHAOw" type="CombinedFragment_Shape">
+ <children xmi:type="notation:BasicCompartment" xmi:id="_FRAKAESnEeilLIdbxjHAOw" type="CombinedFragment_SubfragmentCompartment">
+ <children xmi:type="notation:Shape" xmi:id="_FRAKBESnEeilLIdbxjHAOw" type="InteractionOperand_Shape">
+ <children xmi:type="notation:DecorationNode" xmi:id="_FRAKBkSnEeilLIdbxjHAOw" type="InteractionOperand_Guard">
+ <element xmi:type="uml:InteractionConstraint" href="bug533682.uml#_FQ3nIUSnEeilLIdbxjHAOw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_FRAKB0SnEeilLIdbxjHAOw" x="5" y="5"/>
+ </children>
+ <element xmi:type="uml:InteractionOperand" href="bug533682.uml#_FQ3nIESnEeilLIdbxjHAOw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_FRAKBUSnEeilLIdbxjHAOw" width="100" height="202"/>
+ </children>
+ <styles xmi:type="notation:SortingStyle" xmi:id="_FRAKAUSnEeilLIdbxjHAOw"/>
+ <styles xmi:type="notation:FilteringStyle" xmi:id="_FRAKAkSnEeilLIdbxjHAOw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_FRAKA0SnEeilLIdbxjHAOw"/>
+ </children>
+ <element xmi:type="uml:CombinedFragment" href="bug533682.uml#_FQ2ZAESnEeilLIdbxjHAOw"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_FQ-74USnEeilLIdbxjHAOw" x="14" y="40" width="381" height="222"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_RZ4XwEMwEeiEZ5Jtfh6-KA" type="Lifeline_Shape">
+ <children xmi:type="notation:DecorationNode" xmi:id="_RZ4-0EMwEeiEZ5Jtfh6-KA" type="Lifeline_NameLabel">
+ <element xmi:type="uml:Lifeline" href="bug533682.uml#_RZwb8EMwEeiEZ5Jtfh6-KA"/>
+ </children>
+ <element xmi:type="uml:Lifeline" href="bug533682.uml#_RZwb8EMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_RZ4XwUMwEeiEZ5Jtfh6-KA" x="58" y="10"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_R0X7YEMwEeiEZ5Jtfh6-KA" type="Lifeline_Shape">
+ <children xmi:type="notation:DecorationNode" xmi:id="_R0X7YkMwEeiEZ5Jtfh6-KA" type="Lifeline_NameLabel">
+ <element xmi:type="uml:Lifeline" href="bug533682.uml#_R0URAEMwEeiEZ5Jtfh6-KA"/>
+ </children>
+ <children xmi:type="notation:BasicCompartment" xmi:id="_R0cM0EMwEeiEZ5Jtfh6-KA" type="compartment_shape_display">
+ <styles xmi:type="notation:TitleStyle" xmi:id="_R0cM0UMwEeiEZ5Jtfh6-KA"/>
+ <element xmi:type="uml:Lifeline" href="bug533682.uml#_R0URAEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_R0cM0kMwEeiEZ5Jtfh6-KA"/>
+ </children>
+ <children xmi:type="notation:Shape" xmi:id="_XgABcEMwEeiEZ5Jtfh6-KA" type="BehaviorExecutionSpecification_Shape">
+ <children xmi:type="notation:DecorationNode" xmi:id="_XgABckMwEeiEZ5Jtfh6-KA" type="BehaviorExecutionSpecification_Behavior">
+ <element xmi:type="uml:BehaviorExecutionSpecification" href="bug533682.uml#_Xf7wAEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_XgAogEMwEeiEZ5Jtfh6-KA" x="18" y="18"/>
+ </children>
+ <element xmi:type="uml:BehaviorExecutionSpecification" href="bug533682.uml#_Xf7wAEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_XgABcUMwEeiEZ5Jtfh6-KA" x="40" y="90" width="20" height="100"/>
+ </children>
+ <element xmi:type="uml:Lifeline" href="bug533682.uml#_R0URAEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_R0X7YUMwEeiEZ5Jtfh6-KA" x="237" y="10"/>
+ </children>
+ <element xmi:type="uml:Interaction" href="bug533682.uml#_POkWwEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_QKU0ZEMwEeiEZ5Jtfh6-KA"/>
+ </children>
+ <element xmi:type="uml:Interaction" href="bug533682.uml#_POkWwEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_QKU0ZUMwEeiEZ5Jtfh6-KA"/>
+ </children>
+ <styles xmi:type="notation:StringValueStyle" xmi:id="_QKU0ZkMwEeiEZ5Jtfh6-KA" name="diagram_compatibility_version" stringValue="1.4.0"/>
+ <styles xmi:type="notation:DiagramStyle" xmi:id="_QKU0Z0MwEeiEZ5Jtfh6-KA"/>
+ <styles xmi:type="style:PapyrusDiagramStyle" xmi:id="_QKU0aEMwEeiEZ5Jtfh6-KA" diagramKindId="org.eclipse.papyrus.uml.diagram.sequence">
+ <owner xmi:type="uml:Class" href="bug533682.uml#_Jqu6wEMwEeiEZ5Jtfh6-KA"/>
+ </styles>
+ <element xmi:type="uml:Interaction" href="bug533682.uml#_POkWwEMwEeiEZ5Jtfh6-KA"/>
+ <edges xmi:type="notation:Connector" xmi:id="_Xfg5QEMwEeiEZ5Jtfh6-KA" type="Message_SynchEdge" source="_RZ4XwEMwEeiEZ5Jtfh6-KA" target="_R0X7YEMwEeiEZ5Jtfh6-KA">
+ <children xmi:type="notation:DecorationNode" xmi:id="_Xfg5Q0MwEeiEZ5Jtfh6-KA" type="Message_SynchNameLabel">
+ <element xmi:type="uml:Message" href="bug533682.uml#_XfUsAEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Xfg5REMwEeiEZ5Jtfh6-KA" x="1" y="-13"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_XfhgUEMwEeiEZ5Jtfh6-KA" type="Message_SynchStereotypeLabel">
+ <element xmi:type="uml:Message" href="bug533682.uml#_XfUsAEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_XfhgUUMwEeiEZ5Jtfh6-KA" x="1" y="-33"/>
+ </children>
+ <styles xmi:type="notation:FontStyle" xmi:id="_Xfg5QUMwEeiEZ5Jtfh6-KA"/>
+ <styles xmi:type="notation:LineStyle" xmi:id="_XfhgUkMwEeiEZ5Jtfh6-KA"/>
+ <element xmi:type="uml:Message" href="bug533682.uml#_XfUsAEMwEeiEZ5Jtfh6-KA"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_Xfg5QkMwEeiEZ5Jtfh6-KA" points="[0, 0, -179, 0]$[179, 0, 0, 0]"/>
+ <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_XftGgEMwEeiEZ5Jtfh6-KA" id="(0.5,0.12857142857142856)"/>
+ <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_XfttkEMwEeiEZ5Jtfh6-KA" id="(0.5,0.12857142857142856)"/>
+ </edges>
+ <edges xmi:type="notation:Connector" xmi:id="_XgIkUEMwEeiEZ5Jtfh6-KA" type="Message_ReplyEdge" source="_R0X7YEMwEeiEZ5Jtfh6-KA" target="_RZ4XwEMwEeiEZ5Jtfh6-KA">
+ <children xmi:type="notation:DecorationNode" xmi:id="_XgIkU0MwEeiEZ5Jtfh6-KA" type="Message_ReplyNameLabel">
+ <element xmi:type="uml:Message" href="bug533682.uml#_XgGvIEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_XgIkVEMwEeiEZ5Jtfh6-KA" x="1" y="-13"/>
+ </children>
+ <children xmi:type="notation:DecorationNode" xmi:id="_XgIkVUMwEeiEZ5Jtfh6-KA" type="Message_ReplyStereotypeLabel">
+ <element xmi:type="uml:Message" href="bug533682.uml#_XgGvIEMwEeiEZ5Jtfh6-KA"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_XgIkVkMwEeiEZ5Jtfh6-KA" x="1" y="-33"/>
+ </children>
+ <styles xmi:type="notation:FontStyle" xmi:id="_XgIkUUMwEeiEZ5Jtfh6-KA"/>
+ <styles xmi:type="notation:LineStyle" xmi:id="_XgIkV0MwEeiEZ5Jtfh6-KA"/>
+ <element xmi:type="uml:Message" href="bug533682.uml#_XgGvIEMwEeiEZ5Jtfh6-KA"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_XgIkUkMwEeiEZ5Jtfh6-KA" points="[0, 0, 179, 0]$[-179, 0, 0, 0]"/>
+ <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_XgJycEMwEeiEZ5Jtfh6-KA" id="(0.5,0.2714285714285714)"/>
+ <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_XgJycUMwEeiEZ5Jtfh6-KA" id="(0.5,0.2714285714285714)"/>
+ </edges>
+</notation:Diagram>
diff --git a/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.uml b/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.uml
new file mode 100644
index 00000000000..49e44708509
--- /dev/null
+++ b/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/resource/bugs/bug533682.uml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_HWN6cEMwEeiEZ5Jtfh6-KA" name="bug533673">
+ <packageImport xmi:type="uml:PackageImport" xmi:id="_HeHSMEMwEeiEZ5Jtfh6-KA">
+ <importedPackage xmi:type="uml:Model" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#_0"/>
+ </packageImport>
+ <packagedElement xmi:type="uml:Class" xmi:id="_Jqu6wEMwEeiEZ5Jtfh6-KA" name="Foo" classifierBehavior="_POkWwEMwEeiEZ5Jtfh6-KA">
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_LwEPkEMwEeiEZ5Jtfh6-KA" name="a"/>
+ <ownedAttribute xmi:type="uml:Property" xmi:id="_M6OVkEMwEeiEZ5Jtfh6-KA" name="b"/>
+ <ownedBehavior xmi:type="uml:Interaction" xmi:id="_POkWwEMwEeiEZ5Jtfh6-KA" name="DoIt">
+ <lifeline xmi:type="uml:Lifeline" xmi:id="_RZwb8EMwEeiEZ5Jtfh6-KA" name="a" represents="_LwEPkEMwEeiEZ5Jtfh6-KA" coveredBy="_FQ3nIESnEeilLIdbxjHAOw _XfZkgEMwEeiEZ5Jtfh6-KA _XgH9QEMwEeiEZ5Jtfh6-KA"/>
+ <lifeline xmi:type="uml:Lifeline" xmi:id="_R0URAEMwEeiEZ5Jtfh6-KA" name="b" represents="_M6OVkEMwEeiEZ5Jtfh6-KA" coveredBy="_FQ3nIESnEeilLIdbxjHAOw _XfaLkEMwEeiEZ5Jtfh6-KA _XgHWMEMwEeiEZ5Jtfh6-KA _Xf7wAEMwEeiEZ5Jtfh6-KA"/>
+ <fragment xmi:type="uml:CombinedFragment" xmi:id="_FQ2ZAESnEeilLIdbxjHAOw" covered="_RZwb8EMwEeiEZ5Jtfh6-KA _R0URAEMwEeiEZ5Jtfh6-KA" interactionOperator="opt" name="cfrag">
+ <operand xmi:type="uml:InteractionOperand" xmi:id="_FQ3nIESnEeilLIdbxjHAOw" name="opt" covered="_RZwb8EMwEeiEZ5Jtfh6-KA _R0URAEMwEeiEZ5Jtfh6-KA">
+ <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_XfZkgEMwEeiEZ5Jtfh6-KA" name="request-send" covered="_RZwb8EMwEeiEZ5Jtfh6-KA" message="_XfUsAEMwEeiEZ5Jtfh6-KA"/>
+ <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_XfaLkEMwEeiEZ5Jtfh6-KA" name="request-recv" covered="_R0URAEMwEeiEZ5Jtfh6-KA" message="_XfUsAEMwEeiEZ5Jtfh6-KA"/>
+ <fragment xmi:type="uml:BehaviorExecutionSpecification" xmi:id="_Xf7wAEMwEeiEZ5Jtfh6-KA" name="exec" covered="_R0URAEMwEeiEZ5Jtfh6-KA" finish="_XgHWMEMwEeiEZ5Jtfh6-KA" start="_XfaLkEMwEeiEZ5Jtfh6-KA"/>
+ <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_XgHWMEMwEeiEZ5Jtfh6-KA" name="reply-send" covered="_R0URAEMwEeiEZ5Jtfh6-KA" message="_XgGvIEMwEeiEZ5Jtfh6-KA"/>
+ <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_XgH9QEMwEeiEZ5Jtfh6-KA" name="reply-recv" covered="_RZwb8EMwEeiEZ5Jtfh6-KA" message="_XgGvIEMwEeiEZ5Jtfh6-KA"/>
+ <guard xmi:type="uml:InteractionConstraint" xmi:id="_FQ3nIUSnEeilLIdbxjHAOw" name="guard"/>
+ </operand>
+ </fragment>
+ <message xmi:type="uml:Message" xmi:id="_XfUsAEMwEeiEZ5Jtfh6-KA" name="request" receiveEvent="_XfaLkEMwEeiEZ5Jtfh6-KA" sendEvent="_XfZkgEMwEeiEZ5Jtfh6-KA"/>
+ <message xmi:type="uml:Message" xmi:id="_XgGvIEMwEeiEZ5Jtfh6-KA" messageSort="reply" receiveEvent="_XgH9QEMwEeiEZ5Jtfh6-KA" sendEvent="_XgHWMEMwEeiEZ5Jtfh6-KA"/>
+ </ownedBehavior>
+ </packagedElement>
+</uml:Model>
diff --git a/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/src/org/eclipse/papyrus/uml/diagram/sequence/tests/bug/CombinedFragmentRegressionTest.java b/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/src/org/eclipse/papyrus/uml/diagram/sequence/tests/bug/CombinedFragmentRegressionTest.java
index c5febc7935d..4a3f0f92eda 100644
--- a/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/src/org/eclipse/papyrus/uml/diagram/sequence/tests/bug/CombinedFragmentRegressionTest.java
+++ b/tests/junit/plugins/uml/diagram/org.eclipse.papyrus.uml.diagram.sequence.tests/src/org/eclipse/papyrus/uml/diagram/sequence/tests/bug/CombinedFragmentRegressionTest.java
@@ -17,10 +17,14 @@ import static org.eclipse.papyrus.junit.matchers.MoreMatchers.greaterThan;
import static org.eclipse.papyrus.junit.matchers.MoreMatchers.isEmpty;
import static org.eclipse.papyrus.junit.utils.rules.PapyrusEditorFixture.at;
import static org.eclipse.papyrus.junit.utils.rules.PapyrusEditorFixture.sized;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assume.assumeThat;
import java.util.function.Consumer;
@@ -36,7 +40,9 @@ import org.eclipse.papyrus.junit.utils.rules.PapyrusEditorFixture;
import org.eclipse.papyrus.junit.utils.rules.PluginResource;
import org.eclipse.papyrus.uml.diagram.sequence.providers.UMLElementTypes;
import org.eclipse.uml2.uml.CombinedFragment;
+import org.eclipse.uml2.uml.ExecutionSpecification;
import org.eclipse.uml2.uml.Interaction;
+import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.InteractionOperand;
import org.junit.Rule;
import org.junit.Test;
@@ -108,4 +114,117 @@ public class CombinedFragmentRegressionTest extends AbstractPapyrusTest {
verifyBounds.accept(figure.getBounds());
}
+ /**
+ * Verify that the deletion of an interaction operand does not delete the
+ * interaction fragments that it owns, but transfers them up to the next
+ * fragment container.
+ */
+ @Test
+ @PluginResource("resource/bugs/bug533682.di")
+ @ActiveDiagram("sequence")
+ public void deleteInteractionOperand() {
+ EditPart combinedFragmentEP = editor.findEditPart("cfrag", CombinedFragment.class);
+ CombinedFragment cfrag = (CombinedFragment) combinedFragmentEP.getAdapter(EObject.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ InteractionOperand operand = cfrag.getOperands().get(0);
+ EditPart operandEP = editor.requireEditPart(combinedFragmentEP, operand);
+
+ // We have at least four message ends and one execution specification
+ InteractionFragment[] fragments = operand.getFragments().toArray(new InteractionFragment[0]);
+ assumeThat("Lost fragments on opening editor", fragments.length, greaterThan(4));
+ ExecutionSpecification exec = (ExecutionSpecification) operand.getFragment("exec");
+ assumeThat("No execution specification", exec, notNullValue());
+
+ editor.delete(operandEP);
+
+ assertThat("Interaction fragments not retained", interaction.getFragments(), hasItems(fragments));
+ assertThat("Execution specification lost from diagram", editor.findEditPart(exec), notNullValue());
+
+ // Cannot test undo/redo because after Undo, the GridManagementEditPolicy
+ // erroneously adds the combined fragment to the fragments of the operand
+ // that is restored to its operands list, which is a containment cycle
+ // that breaks EMF
+ }
+
+ /**
+ * Verify that the deletion of a combined fragment does not delete the
+ * interaction fragments that its operand owns, but transfers them up to the next
+ * fragment container.
+ */
+ @Test
+ @PluginResource("resource/bugs/bug533682.di")
+ @ActiveDiagram("sequence")
+ public void deleteCombinedFragment() {
+ EditPart combinedFragmentEP = editor.findEditPart("cfrag", CombinedFragment.class);
+ CombinedFragment cfrag = (CombinedFragment) combinedFragmentEP.getAdapter(EObject.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ InteractionOperand operand = cfrag.getOperands().get(0);
+
+ // We have at least four message ends and one execution specification
+ InteractionFragment[] fragments = operand.getFragments().toArray(new InteractionFragment[0]);
+ assumeThat("Lost fragments on opening editor", fragments.length, greaterThan(4));
+ ExecutionSpecification exec = (ExecutionSpecification) operand.getFragment("exec");
+ assumeThat("No execution specification", exec, notNullValue());
+
+ editor.delete(combinedFragmentEP);
+
+ assertThat("Interaction fragments not retained", interaction.getFragments(), hasItems(fragments));
+ assertThat("Execution specification lost from diagram", editor.findEditPart(exec), notNullValue());
+ }
+
+ /**
+ * Verify that the deletion of an interaction fragment inside of an operand
+ * is not impeded.
+ */
+ @Test
+ @PluginResource("resource/bugs/bug533682.di")
+ @ActiveDiagram("sequence")
+ public void deleteInteractionFragmentInOperand() {
+ EditPart combinedFragmentEP = editor.findEditPart("cfrag", CombinedFragment.class);
+ CombinedFragment cfrag = (CombinedFragment) combinedFragmentEP.getAdapter(EObject.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ InteractionOperand operand = cfrag.getOperands().get(0);
+
+ // Find the execution specification
+ EditPart execEP = editor.findEditPart("exec", ExecutionSpecification.class);
+ ExecutionSpecification exec = (ExecutionSpecification) execEP.getAdapter(EObject.class);
+
+ editor.delete(execEP);
+
+ assertThat("Execution specification not deleted", exec.eResource(), nullValue());
+ assertThat("Operand still has the execution specification", operand.getFragments(), not(hasItem(exec)));
+ assertThat("Interaction has the execution specification", interaction.getFragments(), not(hasItem(exec)));
+
+ execEP = editor.findEditPart("exec", ExecutionSpecification.class);
+ assertThat("Execution specification still presented in diagram", execEP, nullValue());
+ }
+
+ /**
+ * Verify that the deletion of the interaction is not impeded.
+ */
+ @Test
+ @PluginResource("resource/bugs/bug533682.di")
+ @ActiveDiagram("sequence")
+ public void deleteInteraction() {
+ EditPart combinedFragmentEP = editor.findEditPart("cfrag", CombinedFragment.class);
+ CombinedFragment cfrag = (CombinedFragment) combinedFragmentEP.getAdapter(EObject.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ // Find the execution specification
+ EditPart execEP = editor.findEditPart("exec", ExecutionSpecification.class);
+ ExecutionSpecification exec = (ExecutionSpecification) execEP.getAdapter(EObject.class);
+
+ EditPart interactionEP = editor.requireEditPart(editor.getActiveDiagram(), interaction);
+ editor.delete(interactionEP);
+
+ assertThat("Execution specification not deleted", exec.eResource(), nullValue());
+ assertThat("Interaction not deleted", interaction.eResource(), nullValue());
+ }
}
diff --git a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.classpath b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.classpath
index ad32c83a788..eca7bdba8f0 100644
--- a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.classpath
+++ b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.classpath
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
diff --git a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.settings/org.eclipse.jdt.core.prefs b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.settings/org.eclipse.jdt.core.prefs
index 94d61f00da6..b3aa6d60f94 100644
--- a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/.settings/org.eclipse.jdt.core.prefs
@@ -1,10 +1,10 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/META-INF/MANIFEST.MF b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/META-INF/MANIFEST.MF
index 6bb423c4a3e..8e8bb8475b4 100644
--- a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/META-INF/MANIFEST.MF
+++ b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/META-INF/MANIFEST.MF
@@ -18,5 +18,5 @@ Bundle-Name: %pluginName
Bundle-Localization: plugin
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.papyrus.uml.service.types.tests;singleton:=true
-Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.google.common.collect;version="21.0.0"
diff --git a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/resource/interactions/bug533682.uml b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/resource/interactions/bug533682.uml
new file mode 100644
index 00000000000..67d5433ae8e
--- /dev/null
+++ b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/resource/interactions/bug533682.uml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_HWN6cEMwEeiEZ5Jtfh6-KA" name="bug533682">
+ <packageImport xmi:id="_HeHSMEMwEeiEZ5Jtfh6-KA">
+ <importedPackage xmi:type="uml:Model" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#_0"/>
+ </packageImport>
+ <packagedElement xmi:type="uml:Class" xmi:id="_Jqu6wEMwEeiEZ5Jtfh6-KA" name="Foo">
+ <ownedAttribute xmi:id="_LwEPkEMwEeiEZ5Jtfh6-KA" name="a"/>
+ <ownedAttribute xmi:id="_M6OVkEMwEeiEZ5Jtfh6-KA" name="b"/>
+ <ownedBehavior xmi:type="uml:Interaction" xmi:id="_POkWwEMwEeiEZ5Jtfh6-KA" name="DoIt">
+ <lifeline xmi:id="_RZwb8EMwEeiEZ5Jtfh6-KA" name="a" represents="_LwEPkEMwEeiEZ5Jtfh6-KA" coveredBy="_FQ3nIESnEeilLIdbxjHAOw _XfZkgEMwEeiEZ5Jtfh6-KA _XgH9QEMwEeiEZ5Jtfh6-KA _FQ2ZAESnEeilLIdbxjHAOw"/>
+ <lifeline xmi:id="_R0URAEMwEeiEZ5Jtfh6-KA" name="b" represents="_M6OVkEMwEeiEZ5Jtfh6-KA" coveredBy="_FQ3nIESnEeilLIdbxjHAOw _XfaLkEMwEeiEZ5Jtfh6-KA _XgHWMEMwEeiEZ5Jtfh6-KA _Xf7wAEMwEeiEZ5Jtfh6-KA _FQ2ZAESnEeilLIdbxjHAOw"/>
+ <fragment xmi:type="uml:CombinedFragment" xmi:id="_FQ2ZAESnEeilLIdbxjHAOw" name="cfrag" covered="_RZwb8EMwEeiEZ5Jtfh6-KA _R0URAEMwEeiEZ5Jtfh6-KA" interactionOperator="opt">
+ <operand xmi:id="_FQ3nIESnEeilLIdbxjHAOw" name="opt" covered="_RZwb8EMwEeiEZ5Jtfh6-KA _R0URAEMwEeiEZ5Jtfh6-KA">
+ <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_XfZkgEMwEeiEZ5Jtfh6-KA" name="request-send" covered="_RZwb8EMwEeiEZ5Jtfh6-KA" message="_XfUsAEMwEeiEZ5Jtfh6-KA"/>
+ <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_XfaLkEMwEeiEZ5Jtfh6-KA" name="request-recv" covered="_R0URAEMwEeiEZ5Jtfh6-KA" message="_XfUsAEMwEeiEZ5Jtfh6-KA"/>
+ <fragment xmi:type="uml:BehaviorExecutionSpecification" xmi:id="_Xf7wAEMwEeiEZ5Jtfh6-KA" name="exec" covered="_R0URAEMwEeiEZ5Jtfh6-KA" finish="_XgHWMEMwEeiEZ5Jtfh6-KA" start="_XfaLkEMwEeiEZ5Jtfh6-KA"/>
+ <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_XgHWMEMwEeiEZ5Jtfh6-KA" name="reply-send" covered="_R0URAEMwEeiEZ5Jtfh6-KA" message="_XgGvIEMwEeiEZ5Jtfh6-KA"/>
+ <fragment xmi:type="uml:MessageOccurrenceSpecification" xmi:id="_XgH9QEMwEeiEZ5Jtfh6-KA" name="reply-recv" covered="_RZwb8EMwEeiEZ5Jtfh6-KA" message="_XgGvIEMwEeiEZ5Jtfh6-KA"/>
+ <guard xmi:id="_FQ3nIUSnEeilLIdbxjHAOw" name="guard">
+ <specification xmi:type="uml:LiteralBoolean" xmi:id="_-EX0AEZCEeisIvDZ4lXvcg"/>
+ </guard>
+ </operand>
+ </fragment>
+ <message xmi:id="_XfUsAEMwEeiEZ5Jtfh6-KA" name="request" receiveEvent="_XfaLkEMwEeiEZ5Jtfh6-KA" sendEvent="_XfZkgEMwEeiEZ5Jtfh6-KA"/>
+ <message xmi:id="_XgGvIEMwEeiEZ5Jtfh6-KA" messageSort="reply" receiveEvent="_XgH9QEMwEeiEZ5Jtfh6-KA" sendEvent="_XgHWMEMwEeiEZ5Jtfh6-KA"/>
+ </ownedBehavior>
+ </packagedElement>
+</uml:Model>
diff --git a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/src/org/eclipse/papyrus/uml/service/types/tests/deletion/InteractionDeletionTest.java b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/src/org/eclipse/papyrus/uml/service/types/tests/deletion/InteractionDeletionTest.java
new file mode 100644
index 00000000000..e9e9800367d
--- /dev/null
+++ b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/src/org/eclipse/papyrus/uml/service/types/tests/deletion/InteractionDeletionTest.java
@@ -0,0 +1,257 @@
+/*****************************************************************************
+ * Copyright (c) 2018 CEA LIST 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:
+ * CEA LIST - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.uml.service.types.tests.deletion;
+
+import static org.eclipse.papyrus.junit.matchers.MoreMatchers.greaterThan;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeThat;
+
+import java.util.Iterator;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.transaction.RollbackException;
+import org.eclipse.gmf.runtime.common.core.command.ICommand;
+import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
+import org.eclipse.gmf.runtime.emf.type.core.requests.IEditCommandRequest;
+import org.eclipse.papyrus.infra.emf.gmf.util.GMFUnsafe;
+import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils;
+import org.eclipse.papyrus.infra.services.edit.service.IElementEditService;
+import org.eclipse.papyrus.junit.utils.rules.ModelSetFixture;
+import org.eclipse.papyrus.junit.utils.rules.PluginResource;
+import org.eclipse.uml2.common.util.UML2Util;
+import org.eclipse.uml2.uml.CombinedFragment;
+import org.eclipse.uml2.uml.ExecutionSpecification;
+import org.eclipse.uml2.uml.Interaction;
+import org.eclipse.uml2.uml.InteractionFragment;
+import org.eclipse.uml2.uml.InteractionOperand;
+import org.eclipse.uml2.uml.InteractionOperatorKind;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.UMLFactory;
+import org.junit.Rule;
+import org.junit.Test;
+
+import com.google.common.collect.Iterators;
+
+/**
+ * @author damus
+ *
+ */
+public class InteractionDeletionTest {
+
+ @Rule
+ public final ModelSetFixture model = new ModelSetFixture();
+
+ /**
+ * Constructor.
+ *
+ */
+ public InteractionDeletionTest() {
+ super();
+ }
+
+ /**
+ * Verify that the deletion of a combined fragment does not delete the
+ * interaction fragments that its operand owns, but transfers them up to the next
+ * fragment container.
+ */
+ @Test
+ @PluginResource("resource/interactions/bug533682.uml")
+ public void deleteCombinedFragment() {
+ CombinedFragment cfrag = findElement("cfrag", CombinedFragment.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ InteractionOperand operand = cfrag.getOperands().get(0);
+
+ // We have at least four message ends and one execution specification
+ InteractionFragment[] fragments = operand.getFragments().toArray(new InteractionFragment[0]);
+ assumeThat("Lost fragments on opening editor", fragments.length, greaterThan(4));
+ ExecutionSpecification exec = (ExecutionSpecification) operand.getFragment("exec");
+ assumeThat("No execution specification", exec, notNullValue());
+
+ delete(cfrag);
+
+ assertThat("Interaction fragments not retained", interaction.getFragments(), hasItems(fragments));
+ }
+
+ /**
+ * A variant in which the contents of a combined fragment that is deleted end up in
+ * a nesting fragment, not the interaction.
+ */
+ @Test
+ @PluginResource("resource/interactions/bug533682.uml")
+ public void deleteCombinedFragmentNested() {
+ CombinedFragment cfrag = findElement("cfrag", CombinedFragment.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ InteractionOperand operand = cfrag.getOperands().get(0);
+
+ // We have at least four message ends and one execution specification
+ InteractionFragment[] fragments = operand.getFragments().toArray(new InteractionFragment[0]);
+ assumeThat("Lost fragments on opening editor", fragments.length, greaterThan(4));
+ ExecutionSpecification exec = (ExecutionSpecification) operand.getFragment("exec");
+ assumeThat("No execution specification", exec, notNullValue());
+
+ // Insert a layer of nesting
+ CombinedFragment newCFrag = insertContainingCombinedFragment(cfrag);
+ InteractionOperand intermediate = newCFrag.getOperands().get(0);
+
+ delete(cfrag);
+
+ assertThat("Interaction fragments not retained by parent operand", intermediate.getFragments(), hasItems(fragments));
+ }
+
+ /**
+ * A variant in which the content of a combined fragment that is deleted is just another
+ * combined fragment, not more primitive fragments.
+ */
+ @Test
+ @PluginResource("resource/interactions/bug533682.uml")
+ public void deleteCombinedFragmentDeeplyNested() {
+ CombinedFragment cfrag = findElement("cfrag", CombinedFragment.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ // Insert two layers of nesting
+ CombinedFragment toDelete = insertContainingCombinedFragment(cfrag);
+ CombinedFragment newCFrag = insertContainingCombinedFragment(toDelete);
+ InteractionOperand intermediate = newCFrag.getOperands().get(0);
+
+ delete(toDelete);
+
+ assertThat("Interaction fragments not retained by grandparent operand", intermediate.getFragments(), hasItem(cfrag));
+ }
+
+ /**
+ * Verify that the deletion of an interaction fragment inside of an operand is not impeded.
+ */
+ @Test
+ @PluginResource("resource/interactions/bug533682.uml")
+ public void deleteInteractionFragmentInOperand() {
+ CombinedFragment cfrag = findElement("cfrag", CombinedFragment.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ InteractionOperand operand = cfrag.getOperands().get(0);
+
+ ExecutionSpecification exec = findElement("exec", ExecutionSpecification.class);
+
+ delete(exec);
+
+ assertThat("Execution specification not deleted", exec.eResource(), nullValue());
+ assertThat("Operand still has the execution specification", operand.getFragments(), not(hasItem(exec)));
+ assertThat("Interaction has the execution specification", interaction.getFragments(), not(hasItem(exec)));
+ }
+
+ /**
+ * Verify that the deletion of the interaction is not impeded.
+ */
+ @Test
+ @PluginResource("resource/interactions/bug533682.uml")
+ public void deleteInteraction() {
+ CombinedFragment cfrag = findElement("cfrag", CombinedFragment.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ ExecutionSpecification exec = findElement("exec", ExecutionSpecification.class);
+
+ delete(interaction);
+
+ assertThat("Execution specification not deleted", exec.eResource(), nullValue());
+ assertThat("Interaction not deleted", interaction.eResource(), nullValue());
+ }
+
+ @Test
+ @PluginResource("resource/interactions/bug533682.uml")
+ public void deleteInteractionWithNesting() {
+ CombinedFragment cfrag = findElement("cfrag", CombinedFragment.class);
+ Interaction interaction = cfrag.getEnclosingInteraction();
+ assumeThat("No interaction", interaction, notNullValue());
+
+ ExecutionSpecification exec = findElement("exec", ExecutionSpecification.class);
+
+ insertContainingCombinedFragment(cfrag);
+
+ delete(interaction);
+
+ assertThat("Execution specification not deleted", exec.eResource(), nullValue());
+ assertThat("Interaction not deleted", interaction.eResource(), nullValue());
+ }
+
+ //
+ // Test framework
+ //
+
+ <T extends NamedElement> T findElement(String name, Class<T> type) {
+ Iterator<? extends EObject> eObjects = Iterators.filter(model.getResourceSet().getAllContents(), EObject.class);
+ return type.cast(UML2Util.findEObject(eObjects, eObject -> type.isInstance(eObject) && name.equals(((NamedElement) eObject).getName())));
+ }
+
+ void delete(EObject object) {
+ DestroyElementRequest request = new DestroyElementRequest(model.getEditingDomain(), object, false);
+ model.execute(command(object.eContainer(), request));
+ }
+
+ ICommand command(EObject object, IEditCommandRequest request) {
+ IElementEditService edit = ElementEditServiceUtils.getCommandProvider(object);
+ assertThat("No edit command provider", edit, notNullValue());
+ ICommand result = edit.getEditCommand(request);
+ assertThat("No command provided for " + request.getClass().getSimpleName(), result, notNullValue());
+ return result;
+ }
+
+ /**
+ * Sneak a combined fragment into the model as parent of the given combined fragment,
+ * to add a level of nesting.
+ *
+ * @param cfrag
+ * the combined fragment to nested into another new one
+ * @return the new nesting combined fragment
+ */
+ CombinedFragment insertContainingCombinedFragment(CombinedFragment cfrag) {
+ CombinedFragment[] result = { null };
+
+ try {
+ GMFUnsafe.write(model.getEditingDomain(), () -> {
+ EList<InteractionFragment> fragments = (cfrag.getEnclosingInteraction() == null)
+ ? cfrag.getEnclosingOperand().getFragments()
+ : cfrag.getEnclosingInteraction().getFragments();
+
+ int index = fragments.indexOf(cfrag);
+ CombinedFragment newCFrag = UMLFactory.eINSTANCE.createCombinedFragment();
+ newCFrag.setInteractionOperator(InteractionOperatorKind.OPT_LITERAL);
+ InteractionOperand newOperand = newCFrag.createOperand(null);
+ fragments.add(index, newCFrag);
+ newOperand.getFragments().add(cfrag);
+
+ result[0] = newCFrag;
+ });
+ } catch (InterruptedException e) {
+ fail("Combined fragment insertion transaction interrupted");
+ } catch (RollbackException e) {
+ e.printStackTrace();
+ fail("Combined fragment insertion transaction rolled back");
+ }
+
+ return result[0];
+ }
+}
diff --git a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/src/org/eclipse/papyrus/uml/service/types/tests/suites/AllTests.java b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/src/org/eclipse/papyrus/uml/service/types/tests/suites/AllTests.java
index b42b80c9211..d64e181f978 100644
--- a/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/src/org/eclipse/papyrus/uml/service/types/tests/suites/AllTests.java
+++ b/tests/junit/plugins/uml/org.eclipse.papyrus.uml.service.types.tests/src/org/eclipse/papyrus/uml/service/types/tests/suites/AllTests.java
@@ -17,7 +17,6 @@
package org.eclipse.papyrus.uml.service.types.tests.suites;
import org.eclipse.papyrus.junit.framework.classification.ClassificationSuite;
-import org.eclipse.papyrus.junit.framework.runner.Headless;
import org.eclipse.papyrus.uml.service.types.tests.creation.ConnectorReadOnlyTestBug465899;
import org.eclipse.papyrus.uml.service.types.tests.creation.CreateAssociationCompositeDirectedTest;
import org.eclipse.papyrus.uml.service.types.tests.creation.CreateAssociationCompositeTest;
@@ -32,13 +31,13 @@ import org.eclipse.papyrus.uml.service.types.tests.deletion.DeleteContainmentSub
import org.eclipse.papyrus.uml.service.types.tests.deletion.DeleteDependentWithStereotypeApplications458685;
import org.eclipse.papyrus.uml.service.types.tests.deletion.DeletePureUMLElementTest;
import org.eclipse.papyrus.uml.service.types.tests.deletion.DeleteTransitionsWithVertexTest;
+import org.eclipse.papyrus.uml.service.types.tests.deletion.InteractionDeletionTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite.SuiteClasses;
/**
* Main Test suite.
*/
-@Headless
@RunWith(ClassificationSuite.class)
@SuiteClasses({
// TestElementTypeRegistryContent.class,
@@ -56,6 +55,7 @@ import org.junit.runners.Suite.SuiteClasses;
CreateAssociationCompositeDirectedTest.class,
CreateAssociationSharedTest.class,
CreateAssociationSharedDirectedTest.class,
+ InteractionDeletionTest.class,
})
public class AllTests {
// JUnit 4 Test Suite

Back to the top