diff options
author | Christian W. Damus | 2016-11-16 15:37:19 +0000 |
---|---|---|
committer | Christian W. Damus | 2016-11-16 15:38:35 +0000 |
commit | cf3a9c9d3b1d9d2f73ec8fbd4762b804e5848ab3 (patch) | |
tree | 463fa1d6b5f095c2f7bc6b5fbedb78bf0228509a | |
parent | fbf626fbcfb5495e08e98eb867c25c3d83c11210 (diff) | |
download | org.eclipse.papyrus-cf3a9c9d3b1d9d2f73ec8fbd4762b804e5848ab3.tar.gz org.eclipse.papyrus-cf3a9c9d3b1d9d2f73ec8fbd4762b804e5848ab3.tar.xz org.eclipse.papyrus-cf3a9c9d3b1d9d2f73ec8fbd4762b804e5848ab3.zip |
Bug 507618: CreateEditBasedElementCommand does not use the factory registered in the resource set
Use the factory registered in the resource set to create
UML elements.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=507618
Change-Id: If7a137b79ecd28379e8de23d29b989b08f2ec3ee
5 files changed, 177 insertions, 13 deletions
diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/CreateEditBasedElementCommand.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/CreateEditBasedElementCommand.java index 853ada99096..12b9091ca5e 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/CreateEditBasedElementCommand.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/CreateEditBasedElementCommand.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013, 2014 CEA LIST and others.
+ * Copyright (c) 2013, 2016 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
@@ -9,6 +9,7 @@ * Contributors:
* Remi Schnekenburger (CEA LIST) - Initial API and implementation
* Christian W. Damus (CEA) - bug 431109
+ * Christian W. Damus - bug 507618
*
*****************************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.common.commands;
@@ -27,8 +28,10 @@ import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.UnexecutableCommand;
import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.edit.command.CommandParameter;
import org.eclipse.emf.edit.command.CreateChildCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
@@ -120,9 +123,10 @@ public class CreateEditBasedElementCommand extends CreateElementCommand { EReference containment = getContainmentFeature();
if (containment != null) {
IEditingDomainItemProvider editingDomainItemProvider = AdapterFactoryEditingDomain.getEditingDomainItemProviderFor(element);
+ ResourceSet resourceSet = EMFHelper.getResourceSet(element);
for (EClass eClassToCreateCommandsFor : eClassesToCreateCommandsFor) {
-
- EObject newElement = eClassToCreateCommandsFor.getEPackage().getEFactoryInstance().create(eClassToCreateCommandsFor);
+ // Use the resource set's registered factory, if possible (UML-RT)
+ EObject newElement = getFactory(eClassToCreateCommandsFor, resourceSet).create(eClassToCreateCommandsFor);
Command possibleCommand = editingDomainItemProvider.createCommand(element, getEditingDomain(), CreateChildCommand.class, new CommandParameter(element, containment, new CommandParameter(null, containment, newElement)));
if (possibleCommand == null) {
possibleCommands.add(UnexecutableCommand.INSTANCE);
@@ -139,6 +143,39 @@ public class CreateEditBasedElementCommand extends CreateElementCommand { }
/**
+ * Obtain the best factory for instantiation of the given {@code eClass}.
+ * This is either
+ * <ul>
+ * <li>the factory registered locally in the {@code resourceSet} for the
+ * {@code eClass}'s package, or</li>
+ * <li>in the very unusual case that the package is not registered, or
+ * if the {@code resourceSet} is {@code null}, the static factory
+ * of the {@code eClass}'s static package</li>
+ * </ul>
+ *
+ * @param eClass
+ * an Ecore class to instantiate
+ * @param resourceSet
+ * the resource set in which context the model is being edited.
+ * May be {@code null}
+ *
+ * @return the factory to use for instantiation of the {@code eClass}
+ */
+ EFactory getFactory(EClass eClass, ResourceSet resourceSet) {
+ EFactory result = null;
+
+ if (resourceSet != null) {
+ result = resourceSet.getPackageRegistry().getEFactory(eClass.getEPackage().getNsURI());
+ }
+
+ if (result == null) {
+ result = eClass.getEPackage().getEFactoryInstance();
+ }
+
+ return result;
+ }
+
+ /**
* Prepares the EMF command to which we delegate execution, if
* it has not already been created. This is not safe to do in a
* read-only context if our request does not {@link CreateEditBasedElementCommand#hasElementToEdit() have
@@ -194,7 +231,9 @@ public class CreateEditBasedElementCommand extends CreateElementCommand { if (containment != null) {
EObject element = getElementToEdit();
if (element != null) {
- newElement = eClass.getEPackage().getEFactoryInstance().create(eClass);
+ ResourceSet resourceSet = EMFHelper.getResourceSet(element);
+ // Use the resource set's registered factory, if possible (UML-RT)
+ newElement = getFactory(eClass, resourceSet).create(eClass);
IEditingDomainItemProvider editingDomainItemProvider = AdapterFactoryEditingDomain.getEditingDomainItemProviderFor(element);
commandDone = editingDomainItemProvider.createCommand(element, getEditingDomain(), CreateChildCommand.class, new CommandParameter(element, containment, new CommandParameter(null, containment, newElement)));
}
@@ -336,10 +375,7 @@ public class CreateEditBasedElementCommand extends CreateElementCommand { return (configureStatus == null) ? CommandResult.newOKCommandResult(newElement) : new CommandResult(configureStatus, newElement);
}
};
- // executes the command and then adds it to the list
- compositeEMFOperation.add(configureTransactionalCommand); // add
- // before
- // execution
+ compositeEMFOperation.add(configureTransactionalCommand);
}
return compositeEMFOperation;
}
diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/META-INF/MANIFEST.MF b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/META-INF/MANIFEST.MF index 71563f3dd83..84cb68492dd 100644 --- a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/META-INF/MANIFEST.MF +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/META-INF/MANIFEST.MF @@ -7,12 +7,13 @@ Require-Bundle: org.junit;bundle-version="4.10.0", org.eclipse.papyrus.infra.gmfdiag.canonical;bundle-version="1.2.0", org.eclipse.uml2.uml;bundle-version="5.1.0", org.eclipse.papyrus.infra.types.core;bundle-version="1.2.0", - org.eclipse.papyrus.infra.gmfdiag.common;bundle-version="1.2.0", - org.eclipse.papyrus.uml.diagram.clazz;bundle-version="2.0.0" + org.eclipse.papyrus.infra.gmfdiag.common;bundle-version="2.0.2", + org.eclipse.papyrus.uml.diagram.clazz;bundle-version="2.0.0", + org.eclipse.papyrus.uml.service.types;bundle-version="2.0.0" Export-Package: org.eclipse.papyrus.infra.gmfdiag.common.tests, org.eclipse.papyrus.infra.gmfdiag.common.utils Bundle-Vendor: %providerName -Bundle-Version: 1.2.0.qualifier +Bundle-Version: 2.0.2.qualifier Bundle-Name: %pluginName Bundle-Localization: plugin Bundle-ManifestVersion: 2 diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/pom.xml b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/pom.xml index 204b9103979..22650e86bb5 100644 --- a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/pom.xml +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/pom.xml @@ -10,6 +10,6 @@ </parent> <groupId>org.eclipse.papyrus</groupId> <artifactId>org.eclipse.papyrus.infra.gmfdiag.common.tests</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>2.0.2-SNAPSHOT</version> <packaging>eclipse-test-plugin</packaging> </project> diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/tests/CreateEditBasedElementCommandTest.java b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/tests/CreateEditBasedElementCommandTest.java new file mode 100644 index 00000000000..a4d2d200e2b --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/commands/tests/CreateEditBasedElementCommandTest.java @@ -0,0 +1,125 @@ +/***************************************************************************** + * Copyright (c) 2016 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.infra.gmfdiag.common.commands.tests; + +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EFactory; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.InternalEObject; +import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; +import org.eclipse.papyrus.infra.gmfdiag.common.commands.CreateEditBasedElementCommand; +import org.eclipse.papyrus.junit.utils.rules.ModelSetFixture; +import org.eclipse.papyrus.junit.utils.rules.PluginResource; +import org.eclipse.papyrus.junit.utils.rules.ServiceRegistryModelSetFixture; +import org.eclipse.papyrus.uml.service.types.element.UMLElementTypes; +import org.eclipse.uml2.uml.UMLFactory; +import org.eclipse.uml2.uml.UMLPackage; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +/** + * Tests for the {@link CreateEditBasedElementCommand} class. + */ +@PluginResource("models/ExpansionModelTest.di") +public class CreateEditBasedElementCommandTest { + + @Rule + public final ModelSetFixture fixture = new ServiceRegistryModelSetFixture(); + + private List<String> invocations = new ArrayList<>(); + + @Test + public void createElement() { + CreateElementRequest request = new CreateElementRequest(fixture.getModel(), UMLElementTypes.CLASS); + CreateEditBasedElementCommand command = new CreateEditBasedElementCommand(request); + assertThat(command.canExecute(), is(true)); + + fixture.execute(command); + + // A new class is always given a default name by edit advice + assertThat(invocations, hasItem("setName")); + } + + // + // Test framework + // + + @Before + public void installUMLFactory() { + // Install reflective proxies for the standard package and factory that + // create reflective proxies for model elements + ClassLoader cl = getClass().getClassLoader(); + + EFactory[] eFactory = { null }; + EPackage[] ePackage = { null }; + + ePackage[0] = (EPackage) Proxy.newProxyInstance(cl, new Class[] { UMLPackage.class }, + (__, method, args) -> { + switch (method.getName()) { + case "getEFactoryInstance": + case "getUMLFactory": + return eFactory[0]; + default: + return method.invoke(UMLPackage.eINSTANCE, args); + } + }); + eFactory[0] = (EFactory) Proxy.newProxyInstance(cl, new Class[] { UMLFactory.class }, + (__, method, args) -> { + switch (method.getName()) { + case "getEPackage": + case "getUMLPackage": + return ePackage[0]; + case "create": + EClass eClass = (EClass) args[0]; + EObject realObject = (EObject) method.invoke(UMLFactory.eINSTANCE, args); + return Proxy.newProxyInstance(cl, new Class[] { + eClass.getInstanceClass(), + InternalEObject.class, + }, (___, method1, args1) -> { + recordInvocation(method1.getName()); + return method1.invoke(realObject, args1); + }); + default: + return method.invoke(UMLFactory.eINSTANCE, args); + } + }); + + EPackage.Registry registry = fixture.getResourceSet().getPackageRegistry(); + + // Replace all registrations of the UML package + for (Map.Entry<String, Object> next : registry.entrySet()) { + if (next.getValue() instanceof UMLPackage) { + next.setValue(ePackage[0]); + } + } + + // Just to make sure + registry.put(ePackage[0].getNsURI(), ePackage[0]); + } + + void recordInvocation(String methodName) { + invocations.add(methodName); + } +} diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/tests/AllTests.java b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/tests/AllTests.java index 19729d7cdc0..e5a16370b03 100644 --- a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/tests/AllTests.java +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/tests/AllTests.java @@ -8,10 +8,11 @@ * * Contributors: * Christian W. Damus (CEA) - initial API and implementation - * Christian W. Damus - bugs 465416, 474467 + * Christian W. Damus - bugs 465416, 474467, 507618 */ package org.eclipse.papyrus.infra.gmfdiag.common.tests; +import org.eclipse.papyrus.infra.gmfdiag.common.commands.tests.CreateEditBasedElementCommandTest; import org.eclipse.papyrus.infra.gmfdiag.common.providers.tests.NotationLabelProviderTest; import org.eclipse.papyrus.infra.gmfdiag.common.sync.tests.SyncTests; import org.eclipse.papyrus.infra.gmfdiag.common.utils.GMFUnsafeTest; @@ -37,6 +38,7 @@ import org.junit.runners.Suite.SuiteClasses; GMFUnsafeTest.class, SyncTests.class, NotationLabelProviderTest.class, + CreateEditBasedElementCommandTest.class, }) public class AllTests { |