diff options
| author | Christian W. Damus | 2017-01-18 21:46:57 +0000 |
|---|---|---|
| committer | Christian W. Damus | 2017-01-19 19:23:57 +0000 |
| commit | 0664de23dafbf3ed7072fcff6497c035674c1811 (patch) | |
| tree | 902cf63befde2f38c4289e4e75598c6240aff651 | |
| parent | 73c0376aedf98ed71aa67248d2f37532775e8843 (diff) | |
| download | org.eclipse.papyrus-rt-0664de23dafbf3ed7072fcff6497c035674c1811.tar.gz org.eclipse.papyrus-rt-0664de23dafbf3ed7072fcff6497c035674c1811.tar.xz org.eclipse.papyrus-rt-0664de23dafbf3ed7072fcff6497c035674c1811.zip | |
Bug 467545: [UML-RT] PapyrusRT shall provide a UML specific implementation to support redefinition
Fix some problems in editing and display of replication:
* CreateEditBasedElementCommand refuses to execute if it would replace an element
in a single-valued containment reference, so when replacing a multiplicity bound
ValueSpecification, first destroy an existing element and then create the new one.
This requires deferring creation of the creation command until after the destroy
command has actually run, because there is no way to tell the
CreateEditBasedElementCommand that it will be okay to execute because a previous
command in the composite will have deleted the existing element
* fix the MultiplicityElementAdapter to also handle changes to the body of an
OpaqueExpression, which being list-valued does support other kinds of notifications
* fix the RTMaskedLabelEditPolicy to properly track comings and goings of bounds
and types and also to refresh itself when the body of an opaque-expression bound
changes
https://bugs.eclipse.org/bugs/show_bug.cgi?id=467545
Change-Id: I40406104225dbc1367ef2721169d97c2229741d3
4 files changed, 161 insertions, 63 deletions
diff --git a/plugins/umlrt/core/org.eclipse.papyrusrt.umlrt.core/src/org/eclipse/papyrusrt/umlrt/core/utils/MultiplicityElementAdapter.java b/plugins/umlrt/core/org.eclipse.papyrusrt.umlrt.core/src/org/eclipse/papyrusrt/umlrt/core/utils/MultiplicityElementAdapter.java index f22fdb6b7..036446380 100644 --- a/plugins/umlrt/core/org.eclipse.papyrusrt.umlrt.core/src/org/eclipse/papyrusrt/umlrt/core/utils/MultiplicityElementAdapter.java +++ b/plugins/umlrt/core/org.eclipse.papyrusrt.umlrt.core/src/org/eclipse/papyrusrt/umlrt/core/utils/MultiplicityElementAdapter.java @@ -99,9 +99,18 @@ public class MultiplicityElementAdapter extends AdapterImpl { @Override public void notifyChanged(Notification notification) { - // We are only interested in changes to scalar features, and these - // are the only kinds of changes that they support + // We are only interested in changes to scalar features, and they + // only support SET, UNSET, and RESOLVE notifications switch (notification.getEventType()) { + case Notification.ADD: + case Notification.ADD_MANY: + case Notification.REMOVE: + case Notification.REMOVE_MANY: + // Except for OpaqueExpression bodies, which are lists + if (notification.getFeature() != UMLPackage.Literals.OPAQUE_EXPRESSION__BODY) { + break; + } + // Fall through case Notification.SET: case Notification.UNSET: if (notification.isTouch()) { @@ -139,6 +148,7 @@ public class MultiplicityElementAdapter extends AdapterImpl { break; } + } final void adaptChange(Notifier oldNotifier, Notifier newNotifier) { diff --git a/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.diagram.common/src/org/eclipse/papyrusrt/umlrt/tooling/diagram/common/internal/editpolicies/RTMaskLabelEditPolicy.java b/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.diagram.common/src/org/eclipse/papyrusrt/umlrt/tooling/diagram/common/internal/editpolicies/RTMaskLabelEditPolicy.java index 6f4908333..d75b39708 100644 --- a/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.diagram.common/src/org/eclipse/papyrusrt/umlrt/tooling/diagram/common/internal/editpolicies/RTMaskLabelEditPolicy.java +++ b/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.diagram.common/src/org/eclipse/papyrusrt/umlrt/tooling/diagram/common/internal/editpolicies/RTMaskLabelEditPolicy.java @@ -13,11 +13,16 @@ package org.eclipse.papyrusrt.umlrt.tooling.diagram.common.internal.editpolicies; +import org.eclipse.emf.common.notify.Notification; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; +import org.eclipse.papyrus.uml.diagram.common.Activator; import org.eclipse.papyrus.uml.diagram.common.editpolicies.IndirectPropertyLabelEditPolicy; +import org.eclipse.papyrusrt.umlrt.core.utils.MultiplicityElementAdapter; import org.eclipse.papyrusrt.umlrt.tooling.diagram.common.internal.utils.RTPropertyLabelHelper; import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.Property; +import org.eclipse.uml2.uml.UMLPackage; /** * Custom mask-label edit policy for UML-RT diagrams that delegates @@ -27,6 +32,13 @@ import org.eclipse.uml2.uml.Element; */ public class RTMaskLabelEditPolicy extends IndirectPropertyLabelEditPolicy { + private MultiplicityElementAdapter adapter = new MultiplicityElementAdapter.ForProperty() { + @Override + protected void handleMultiplicityChanged(Notification notification) { + RTMaskLabelEditPolicy.this.notifyChanged(notification); + } + }; + @Override protected Element initSemanticElement() { return (Element) ((IGraphicalEditPart) getHost()).resolveSemanticElement(); @@ -38,4 +50,37 @@ public class RTMaskLabelEditPolicy extends IndirectPropertyLabelEditPolicy { RTPropertyLabelHelper.getInstance().refreshEditPartDisplay((GraphicalEditPart) getHost()); } + @Override + public void addAdditionalListeners() { + Property property = getUMLElement(); + + // check host semantic element is not null + if (property == null) { + Activator.log.error("No property in RTMaskLabelEditPolicy", null); + return; + } + + adapter.adapt(property); + } + + @Override + protected void removeAdditionalListeners() { + if (adapter.getTarget() != null) { + adapter.unadapt(adapter.getTarget()); + } + } + + @Override + public void notifyChanged(Notification notification) { + super.notifyChanged(notification); + + Object object = notification.getNotifier(); + Property property = getUMLElement(); + if ((object != null) && (property != null)) { + // Handle also the case of opaque expression bodies changing + if (notification.getFeature() == UMLPackage.Literals.OPAQUE_EXPRESSION__BODY) { + refreshDisplay(); + } + } + } } diff --git a/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.diagram.common/src/org/eclipse/papyrusrt/umlrt/tooling/diagram/common/internal/utils/RTPropertyLabelHelper.java b/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.diagram.common/src/org/eclipse/papyrusrt/umlrt/tooling/diagram/common/internal/utils/RTPropertyLabelHelper.java index 4b63c6afb..caed2164e 100644 --- a/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.diagram.common/src/org/eclipse/papyrusrt/umlrt/tooling/diagram/common/internal/utils/RTPropertyLabelHelper.java +++ b/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.diagram.common/src/org/eclipse/papyrusrt/umlrt/tooling/diagram/common/internal/utils/RTPropertyLabelHelper.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2016 Christian W. Damus and others. + * Copyright (c) 2016, 2017 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 @@ -21,6 +21,7 @@ import java.util.Collection; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; +import org.eclipse.papyrus.infra.tools.util.TypeUtils; import org.eclipse.papyrus.uml.diagram.common.helper.PropertyLabelHelper; import org.eclipse.papyrus.uml.tools.utils.ICustomAppearance; import org.eclipse.papyrusrt.umlrt.tooling.diagram.common.editparts.IRTNameEditPart; @@ -44,7 +45,7 @@ public class RTPropertyLabelHelper extends PropertyLabelHelper { @Override public Property getUMLElement(GraphicalEditPart editPart) { - return (Property) ((IGraphicalEditPart) editPart).resolveSemanticElement(); + return TypeUtils.as(((IGraphicalEditPart) editPart).resolveSemanticElement(), Property.class); } @Override diff --git a/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.ui/src/org/eclipse/papyrusrt/umlrt/tooling/ui/widgets/PropertyReplicationObservableValue.java b/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.ui/src/org/eclipse/papyrusrt/umlrt/tooling/ui/widgets/PropertyReplicationObservableValue.java index ac6d0dd5c..9fda02491 100644 --- a/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.ui/src/org/eclipse/papyrusrt/umlrt/tooling/ui/widgets/PropertyReplicationObservableValue.java +++ b/plugins/umlrt/tooling/org.eclipse.papyrusrt.umlrt.tooling.ui/src/org/eclipse/papyrusrt/umlrt/tooling/ui/widgets/PropertyReplicationObservableValue.java @@ -14,35 +14,36 @@ package org.eclipse.papyrusrt.umlrt.tooling.ui.widgets; import java.util.Collections; -import java.util.Map; import java.util.Objects; +import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.databinding.observable.Diffs; import org.eclipse.core.databinding.observable.IObserving; import org.eclipse.core.databinding.observable.value.ValueDiff; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.UnexecutableCommand; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; 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.common.core.command.ICompositeCommand; +import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; -import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest; import org.eclipse.gmf.runtime.emf.type.core.requests.IEditCommandRequest; import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; import org.eclipse.papyrus.infra.core.services.ServiceException; import org.eclipse.papyrus.infra.emf.gmf.command.GMFtoEMFCommandWrapper; -import org.eclipse.papyrus.infra.emf.requests.UnsetRequest; import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForEObject; -import org.eclipse.papyrus.infra.services.edit.commands.ConfigureFeatureListCommandFactory; -import org.eclipse.papyrus.infra.services.edit.commands.IConfigureCommandFactory; import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils; import org.eclipse.papyrus.infra.services.edit.service.IElementEditService; -import org.eclipse.papyrus.uml.service.types.element.UMLElementTypes; import org.eclipse.papyrus.uml.tools.Activator; import org.eclipse.papyrus.uml.tools.databinding.PapyrusObservableValue; import org.eclipse.papyrusrt.umlrt.core.defaultlanguage.IDefaultLanguage; @@ -50,13 +51,13 @@ import org.eclipse.papyrusrt.umlrt.core.defaultlanguage.IDefaultLanguageService; import org.eclipse.papyrusrt.umlrt.core.utils.CapsulePartUtils; import org.eclipse.papyrusrt.umlrt.core.utils.MultiplicityElementAdapter; import org.eclipse.papyrusrt.umlrt.core.utils.RTPortUtils; +import org.eclipse.uml2.uml.LiteralInteger; import org.eclipse.uml2.uml.LiteralUnlimitedNatural; import org.eclipse.uml2.uml.MultiplicityElement; import org.eclipse.uml2.uml.OpaqueExpression; import org.eclipse.uml2.uml.Property; import org.eclipse.uml2.uml.UMLPackage; - -import com.google.common.collect.ImmutableMap; +import org.eclipse.uml2.uml.ValueSpecification; /** @@ -87,14 +88,7 @@ public class PropertyReplicationObservableValue extends PapyrusObservableValue i propertyElement = (Property) property; // add listeners - propertyElement.eAdapters().add(getPartAdapter()); - if (propertyElement.getLowerValue() != null) { - propertyElement.getLowerValue().eAdapters().add(getPartAdapter()); - } - if (propertyElement.getUpperValue() != null) { - propertyElement.getUpperValue().eAdapters().add(getPartAdapter()); - } - + ((PartAdapter) getPartAdapter()).adapt(propertyElement); } } @@ -200,7 +194,7 @@ public class PropertyReplicationObservableValue extends PapyrusObservableValue i return defaultLanguage; } - protected Command getSetMultiplicityCommand(MultiplicityElement element, int lower, int upper) { + protected Command getSetMultiplicityCommand(MultiplicityElement element, Object lower, Object upper) { ICommand result = null; try { @@ -208,10 +202,58 @@ public class PropertyReplicationObservableValue extends PapyrusObservableValue i if (provider != null) { TransactionalEditingDomain ted = (TransactionalEditingDomain) domain; CompositeTransactionalCommand cc = new CompositeTransactionalCommand(ted, "Set Replication"); - IEditCommandRequest setLowerRequest = createSetRequest(ted, eObject, UMLPackage.Literals.MULTIPLICITY_ELEMENT__LOWER, lower); - IEditCommandRequest setUpperRequest = createSetRequest(ted, eObject, UMLPackage.Literals.MULTIPLICITY_ELEMENT__UPPER, upper); - cc.add(provider.getEditCommand(setLowerRequest)); - cc.add(provider.getEditCommand(setUpperRequest)); + + // Handle the lower value + ValueSpecification lowerValue = element.getLowerValue(); + if ((lower instanceof Integer) && (lowerValue instanceof LiteralInteger)) { + // Set its value + IElementEditService edit = ElementEditServiceUtils.getCommandProvider(lowerValue); + if (edit == null) { + cc.add(org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand.INSTANCE); + } else { + cc.add(edit.getEditCommand(createSetRequest(ted, lowerValue, UMLPackage.Literals.LITERAL_INTEGER__VALUE, lower))); + } + } else if ((lower instanceof String) && (lowerValue instanceof OpaqueExpression)) { + // Set its body + appendSetCommands(cc, (OpaqueExpression) lowerValue, (String) lower, getDefaultLanguage()); + } else { + if (lowerValue != null) { + // Destroy and replace + cc.add(provider.getEditCommand(new DestroyElementRequest(ted, lowerValue, false))); + } // else nothing to replace. Just create + + if (lower instanceof Integer) { + appendCreateLiteralIntegerCommand(cc, element, UMLPackage.Literals.MULTIPLICITY_ELEMENT__LOWER_VALUE, lower); + } else if (lower instanceof String) { + appendCreateExpressionCommand(cc, element, (String) lower, getDefaultLanguage(), UMLPackage.Literals.MULTIPLICITY_ELEMENT__LOWER_VALUE); + } + } + + // Handle the upper value + ValueSpecification upperValue = element.getUpperValue(); + if ((upper instanceof Integer) && (upperValue instanceof LiteralUnlimitedNatural)) { + // Set its value + IElementEditService edit = ElementEditServiceUtils.getCommandProvider(upperValue); + if (edit == null) { + cc.add(org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand.INSTANCE); + } else { + cc.add(edit.getEditCommand(createSetRequest(ted, upperValue, UMLPackage.Literals.LITERAL_UNLIMITED_NATURAL__VALUE, upper))); + } + } else if ((upper instanceof String) && (upperValue instanceof OpaqueExpression)) { + // Set its body + appendSetCommands(cc, (OpaqueExpression) upperValue, (String) upper, getDefaultLanguage()); + } else { + if (upperValue != null) { + // Destroy and replace + cc.add(provider.getEditCommand(new DestroyElementRequest(ted, upperValue, false))); + } // else nothing to replace. Just create + + if (upper instanceof Integer) { + appendCreateLiteralUnlimitedNaturalCommand(cc, element, UMLPackage.Literals.MULTIPLICITY_ELEMENT__UPPER_VALUE, upper); + } else if (upper instanceof String) { + appendCreateExpressionCommand(cc, element, (String) upper, getDefaultLanguage(), UMLPackage.Literals.MULTIPLICITY_ELEMENT__UPPER_VALUE); + } + } result = cc.canExecute() ? cc.reduce() : null; } @@ -222,38 +264,39 @@ public class PropertyReplicationObservableValue extends PapyrusObservableValue i return (result == null) ? UnexecutableCommand.INSTANCE : GMFtoEMFCommandWrapper.wrap(result); } - protected Command getSetMultiplicityCommand(MultiplicityElement element, Object lower, String upper) { - ICommand result = null; + private ICommand create(TransactionalEditingDomain domain, MultiplicityElement element, EReference containment, EClass typeToCreate, + EStructuralFeature feature, Object initialValue, Object... more) { - if (lower != null) { - try { - String lang = getDefaultLanguage(); + return new AbstractTransactionalCommand(domain, "Create Multiplicity Bound", null) { - TransactionalEditingDomain ted = (TransactionalEditingDomain) domain; - CompositeTransactionalCommand cc = new CompositeTransactionalCommand(ted, "Set Replication"); + @Override + protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { + ValueSpecification result = (containment == UMLPackage.Literals.MULTIPLICITY_ELEMENT__LOWER_VALUE) + ? element.createLowerValue(null, null, typeToCreate) + : element.createUpperValue(null, null, typeToCreate); - if (element.getUpperValue() instanceof OpaqueExpression) { - appendSetCommands(cc, (OpaqueExpression) element.getUpperValue(), upper, lang); - } else { - appendCreateExpressionCommand(cc, element, upper, lang, UMLPackage.Literals.MULTIPLICITY_ELEMENT__UPPER_VALUE); - } - - if (lower instanceof Integer) { - IElementEditService provider = ElementEditServiceUtils.getCommandProvider(element); - cc.add(provider.getEditCommand(createSetRequest(ted, element, UMLPackage.Literals.MULTIPLICITY_ELEMENT__LOWER, lower))); - } else if (element.getLowerValue() instanceof OpaqueExpression) { - appendSetCommands(cc, (OpaqueExpression) element.getLowerValue(), (String) lower, lang); - } else { - appendCreateExpressionCommand(cc, element, (String) lower, lang, UMLPackage.Literals.MULTIPLICITY_ELEMENT__LOWER_VALUE); + if (feature != null) { + result.eSet(feature, initialValue); + if (more.length > 0) { + for (int i = 0; i < more.length; i += 2) { + result.eSet((EStructuralFeature) more[i], more[i + 1]); + } + } } - result = cc.canExecute() ? cc.reduce() : null; - } catch (Exception ex) { - Activator.log.error(ex); + return CommandResult.newOKCommandResult(result); } - } + }; + } - return (result == null) ? UnexecutableCommand.INSTANCE : GMFtoEMFCommandWrapper.wrap(result); + private void appendCreateLiteralIntegerCommand(ICompositeCommand cc, MultiplicityElement element, EReference containment, Object value) { + cc.add(create((TransactionalEditingDomain) domain, element, containment, UMLPackage.Literals.LITERAL_INTEGER, + UMLPackage.Literals.LITERAL_INTEGER__VALUE, value)); + } + + private void appendCreateLiteralUnlimitedNaturalCommand(ICompositeCommand cc, MultiplicityElement element, EReference containment, Object value) { + cc.add(create((TransactionalEditingDomain) domain, element, containment, UMLPackage.Literals.LITERAL_UNLIMITED_NATURAL, + UMLPackage.Literals.LITERAL_UNLIMITED_NATURAL__VALUE, value)); } private void appendSetCommands(ICompositeCommand cc, OpaqueExpression expr, String body, String language) { @@ -268,16 +311,9 @@ public class PropertyReplicationObservableValue extends PapyrusObservableValue i } private void appendCreateExpressionCommand(ICompositeCommand cc, MultiplicityElement element, String body, String language, EReference bound) { - IElementEditService provider = ElementEditServiceUtils.getCommandProvider(element); - TransactionalEditingDomain ted = (TransactionalEditingDomain) domain; - - CreateElementRequest create = new CreateElementRequest(ted, element, UMLElementTypes.OPAQUE_EXPRESSION, bound); - Map<EStructuralFeature, Object> configuration = ImmutableMap.of( + cc.add(create((TransactionalEditingDomain) domain, element, bound, UMLPackage.Literals.OPAQUE_EXPRESSION, UMLPackage.Literals.OPAQUE_EXPRESSION__BODY, Collections.singletonList(body), - UMLPackage.Literals.OPAQUE_EXPRESSION__LANGUAGE, Collections.singletonList(language)); - create.setParameter(IConfigureCommandFactory.CONFIGURE_COMMAND_FACTORY_ID, new ConfigureFeatureListCommandFactory(configuration)); - - cc.add(provider.getEditCommand(create)); + UMLPackage.Literals.OPAQUE_EXPRESSION__LANGUAGE, Collections.singletonList(language))); } protected Command getUnsetMultiplicityCommand(MultiplicityElement element) { @@ -288,10 +324,16 @@ public class PropertyReplicationObservableValue extends PapyrusObservableValue i if (provider != null) { TransactionalEditingDomain ted = (TransactionalEditingDomain) domain; CompositeTransactionalCommand cc = new CompositeTransactionalCommand(ted, "Set Replication"); - IEditCommandRequest setLowerRequest = new UnsetRequest(ted, eObject, UMLPackage.Literals.MULTIPLICITY_ELEMENT__LOWER_VALUE); - IEditCommandRequest setUpperRequest = new UnsetRequest(ted, eObject, UMLPackage.Literals.MULTIPLICITY_ELEMENT__UPPER_VALUE); - cc.add(provider.getEditCommand(setLowerRequest)); - cc.add(provider.getEditCommand(setUpperRequest)); + + ValueSpecification lowerValue = element.getLowerValue(); + if (lowerValue != null) { + cc.add(provider.getEditCommand(new DestroyElementRequest(ted, lowerValue, false))); + } + + ValueSpecification upperValue = element.getUpperValue(); + if (upperValue != null) { + cc.add(provider.getEditCommand(new DestroyElementRequest(ted, upperValue, false))); + } result = cc.canExecute() ? cc.reduce() : null; } |
