Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreperico2010-03-12 15:11:10 +0000
committereperico2010-03-12 15:11:10 +0000
commit5fd6e643d6f0c9cc1dde4162799c290d1031ceba (patch)
treeef87aa4851a9b49dfbe52154b7dd35ccd61f7e13
parenta34c43a979d9c643ea284797d4797d5b9cff9ef3 (diff)
downloadorg.eclipse.papyrus-5fd6e643d6f0c9cc1dde4162799c290d1031ceba.tar.gz
org.eclipse.papyrus-5fd6e643d6f0c9cc1dde4162799c290d1031ceba.tar.xz
org.eclipse.papyrus-5fd6e643d6f0c9cc1dde4162799c290d1031ceba.zip
NEW - bug 305128: [All Diagram] Provide a feature to transform a model element to another
https://bugs.eclipse.org/bugs/show_bug.cgi?id=305128
-rw-r--r--plugins/uml/org.eclipse.papyrus.navigator/META-INF/MANIFEST.MF3
-rw-r--r--plugins/uml/org.eclipse.papyrus.navigator/plugin.xml11
-rw-r--r--plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformAction.java83
-rw-r--r--plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformActionProvider.java187
-rw-r--r--plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformer.java436
-rw-r--r--plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/commands/EObjectInheritanceCopyCommand.java411
6 files changed, 1130 insertions, 1 deletions
diff --git a/plugins/uml/org.eclipse.papyrus.navigator/META-INF/MANIFEST.MF b/plugins/uml/org.eclipse.papyrus.navigator/META-INF/MANIFEST.MF
index 4a82b59384f..0a59a51ad8d 100644
--- a/plugins/uml/org.eclipse.papyrus.navigator/META-INF/MANIFEST.MF
+++ b/plugins/uml/org.eclipse.papyrus.navigator/META-INF/MANIFEST.MF
@@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.ui.navigator;bundle-version="3.3.101",
org.eclipse.uml2.uml.editor;bundle-version="2.2.0",
org.eclipse.papyrus.core;bundle-version="0.7.0";visibility:=reexport,
org.eclipse.papyrus.sasheditor.di;bundle-version="0.7.0";visibility:=reexport,
- org.eclipse.ltk.core.refactoring;bundle-version="3.5.0"
+ org.eclipse.ltk.core.refactoring;bundle-version="3.5.0",
+ org.eclipse.emf.converter;bundle-version="2.5.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Vendor: %providerName
diff --git a/plugins/uml/org.eclipse.papyrus.navigator/plugin.xml b/plugins/uml/org.eclipse.papyrus.navigator/plugin.xml
index 744f53b039d..7144710e737 100644
--- a/plugins/uml/org.eclipse.papyrus.navigator/plugin.xml
+++ b/plugins/uml/org.eclipse.papyrus.navigator/plugin.xml
@@ -119,6 +119,17 @@
</enablement>
</actionProvider>
<actionProvider
+ class="org.eclipse.papyrus.navigator.actions.GenericTransformActionProvider"
+ id="org.eclipse.papyrus.navigator.actions.GenericTransformActionProvider">
+ <enablement>
+ <or>
+ <adapt
+ type="org.eclipse.uml2.uml.Element">
+ </adapt>
+ </or>
+ </enablement>
+ </actionProvider>
+ <actionProvider
class="org.eclipse.papyrus.navigator.actions.CreateDiagramActionProvider"
id="org.eclipse.papyrus.navigator.actions.CreateDiagramActionProvider">
<enablement>
diff --git a/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformAction.java b/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformAction.java
new file mode 100644
index 00000000000..bb60922198b
--- /dev/null
+++ b/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformAction.java
@@ -0,0 +1,83 @@
+/***************************************************
+* Copyright (c) 2010 Atos Origin.
+
+*
+* 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:
+* Atos Origin - Initial API and implementation
+*
+****************************************************/
+package org.eclipse.papyrus.navigator.actions;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * GenericTransformAction is an action which transforms and EObject by changing its eclass.
+ */
+public class GenericTransformAction extends Action {
+
+ /** title of error dialog */
+ private static final String ERROR_TITLE = "Impossible to continue transformation.";
+
+ /** message in error dialog */
+ private static final String ERROR_MESSAGE = "The transformation can not continue.\n" + "Some objects referencing your selection could not be able to reference the result of the transformation.\n" + "For UML and SysML, applied stereotypes could not be applicable on the result of the transformation.\n" + "Before performing the transformation please delete or unapply the elements listed bellow.";
+
+ /** The EClass to transform into. */
+ private EClass targetEClass = null;
+
+ /** The element to transform. */
+ private EObject element;
+
+ /**
+ * Constructor for a new action.
+ *
+ * @param transformationEClass
+ * the eclass element must be transformed into
+ * @param adapterFactory
+ * the adapter factory for providing label image
+ * @param elementToTransform
+ * the element to transform
+ */
+ public GenericTransformAction(EClass transformationEClass, AdapterFactory adapterFactory, EObject elementToTransform) {
+ super(transformationEClass.getName());
+ targetEClass = transformationEClass;
+ element = elementToTransform;
+
+ if(adapterFactory != null) {
+ EObject tmpEobject = transformationEClass.getEPackage().getEFactoryInstance().create(transformationEClass);
+ IItemLabelProvider provider = (IItemLabelProvider)adapterFactory.adapt(tmpEobject, IItemLabelProvider.class);
+ setImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(provider.getImage(tmpEobject)));
+ }
+ }
+
+ /**
+ * Transform the element and update referencing diagrams.
+ *
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ @Override
+ public void run() {
+ GenericTransformer transformer = new GenericTransformer(element);
+ MultiStatus messages = transformer.isTransformationPossible(targetEClass);
+ if(messages != null && messages.getChildren().length == 0) {
+ transformer.transform(targetEClass);
+ } else {
+ ErrorDialog errorDialog = new ErrorDialog(Display.getDefault().getActiveShell(), ERROR_TITLE, ERROR_MESSAGE, messages, IStatus.WARNING);
+ errorDialog.open();
+ }
+ }
+
+}
diff --git a/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformActionProvider.java b/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformActionProvider.java
new file mode 100644
index 00000000000..45c339351f2
--- /dev/null
+++ b/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformActionProvider.java
@@ -0,0 +1,187 @@
+/***************************************************
+* Copyright (c) 2010 Atos Origin.
+
+*
+* 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:
+* Atos Origin - Initial API and implementation
+*
+****************************************************/
+package org.eclipse.papyrus.navigator.actions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.converter.util.ConverterUtil;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+/**
+ * GenericTransformActionProvider class provides GenericTransformAction actions available for a given element.
+ */
+public class GenericTransformActionProvider extends AbstractSubmenuActionProvider {
+
+ /** Group label */
+ private static final String TRANSFORM_INTO_LABEL = "Transform into";
+
+ /** The factories of appropriate EClass */
+ private Map<String, AdapterFactory> factories = new HashMap<String, AdapterFactory>();
+
+ /** The appropriate EClass for element's transformation */
+ private Set<EClassifier> eClassifiers = new HashSet<EClassifier>();
+
+ /**
+ * Adds all actions to transform an EObject
+ */
+ @Override
+ public void fillContextMenu(IMenuManager menu) {
+ super.fillContextMenu(menu);
+ ISelection selection = getContext().getSelection();
+ if(selection instanceof IStructuredSelection && ((IStructuredSelection)selection).size() == 1) {
+ Object selectedElement = ((IStructuredSelection)selection).getFirstElement();
+ if(selectedElement instanceof EObject) {
+ fillEClassifiers((EObject)selectedElement);
+ }
+ }
+
+ Collection<IAction> genericTransformActions = generateTransformActions(selection);
+ MenuManager submenuManager = new MenuManager(TRANSFORM_INTO_LABEL);
+ populateManager(submenuManager, genericTransformActions, null);
+ menu.add(submenuManager);
+ }
+
+ /**
+ * From an EObject we get the epackage corresponding to the resource extension of the file
+ * and get the imported epackage correspondant
+ *
+ * @param selectionEObject
+ */
+ private void fillEClassifiers(EObject selectionEObject) {
+ Resource r = selectionEObject.eResource();
+ URI uri = r.getURI();
+ String extension = uri.fileExtension();
+ for(Object p : EPackage.Registry.INSTANCE.values()) {
+ if(p instanceof EPackage) {
+ EPackage pack = (EPackage)p;
+ if(pack.getNsPrefix() != null && extension.toLowerCase().equals(pack.getNsPrefix().toLowerCase())) {
+ addClassifiers(pack, eClassifiers);
+ factories.put(pack.getNsURI(), GenericTransformer.getFactory(pack.getNsURI()));
+ List<EPackage> packages = ConverterUtil.computeRequiredPackages(pack);
+ for(EPackage pTmp : packages) {
+ addClassifiers(pTmp, eClassifiers);
+ factories.put(pTmp.getNsURI(), GenericTransformer.getFactory(pTmp.getNsURI()));
+ }
+ break;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Register all classifiers contained in the package
+ *
+ * @param pack
+ * the package
+ * @param result
+ * results at which classifiers must be added
+ */
+ private void addClassifiers(EPackage pack, Set<EClassifier> result) {
+ for(EClassifier c : pack.getEClassifiers()) {
+ result.add(c);
+ }
+ }
+
+ /**
+ * Generate the sorted list of transformation actions.
+ *
+ * @param descriptors
+ * the descriptors
+ * @param selection
+ * the selection
+ *
+ * @return the collection< i action>
+ */
+ protected Collection<IAction> generateTransformActions(ISelection selection) {
+ List<IAction> transformActions = (List<IAction>)generateTransformActionsCore(selection);
+
+ Collections.<IAction> sort(transformActions, new Comparator<IAction>() {
+
+ public int compare(IAction a1, IAction a2) {
+ return a1.getText().compareTo(a2.getText());
+ }
+ });
+
+ return transformActions;
+ }
+
+ /**
+ * Generate transformation actions.
+ *
+ * @param descriptors
+ * the descriptors
+ * @param selection
+ * the selection
+ *
+ * @return the collection< i action>
+ */
+ protected Collection<IAction> generateTransformActionsCore(ISelection selection) {
+ Collection<IAction> actions = new ArrayList<IAction>();
+ if(eClassifiers != null) {
+ for(EClassifier descriptor : eClassifiers) {
+ Object selected = ((IStructuredSelection)selection).getFirstElement();
+ if(selected instanceof EObject) {
+ final EObject selectedElement = (EObject)selected;
+ if(descriptor instanceof EClass && selectedElement.eContainingFeature() != null) {
+ final EClass eclass = (EClass)descriptor;
+ EStructuralFeature containingFeature = selectedElement.eContainingFeature();
+ // to be candidate an eclass has to have a common parent, to not be the selection
+ // and to not be abstract
+ EClass containgType = (EClass)containingFeature.getEType();
+ if((GenericTransformer.getAllSuperTypes(eclass).contains(containgType) || EcoreUtil.equals(eclass, containgType)) && !eclass.equals(selectedElement.eClass()) && !eclass.isAbstract()) {
+ if(selection instanceof IStructuredSelection && ((IStructuredSelection)selection).size() == 1) {
+
+ AdapterFactory adapterFactory = factories.get(eclass.getEPackage().getNsURI());
+ Action transformAction = new GenericTransformAction(eclass, adapterFactory, selectedElement);
+ actions.add(transformAction);
+ if(adapterFactory != null) {
+ EObject tmpEobject = eclass.getEPackage().getEFactoryInstance().create(eclass);
+ IItemLabelProvider provider = (IItemLabelProvider)adapterFactory.adapt(tmpEobject, IItemLabelProvider.class);
+ transformAction.setImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(provider.getImage(tmpEobject)));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return actions;
+ }
+
+}
diff --git a/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformer.java b/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformer.java
new file mode 100644
index 00000000000..617eabe605c
--- /dev/null
+++ b/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/actions/GenericTransformer.java
@@ -0,0 +1,436 @@
+/***************************************************
+* Copyright (c) 2010 Atos Origin.
+
+*
+* 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:
+* Atos Origin - Initial API and implementation
+*
+****************************************************/
+package org.eclipse.papyrus.navigator.actions;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EStructuralFeature.Setting;
+import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.commands.CommandStack;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.gef.requests.GroupRequest;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
+import org.eclipse.gmf.runtime.common.ui.services.editor.EditorService;
+import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
+import org.eclipse.gmf.runtime.diagram.core.util.ViewRefactorHelper;
+import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
+import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramEditDomain;
+import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
+import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest;
+import org.eclipse.gmf.runtime.diagram.ui.requests.RequestConstants;
+import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil;
+import org.eclipse.gmf.runtime.notation.Diagram;
+import org.eclipse.gmf.runtime.notation.Edge;
+import org.eclipse.gmf.runtime.notation.LayoutConstraint;
+import org.eclipse.gmf.runtime.notation.Location;
+import org.eclipse.gmf.runtime.notation.Node;
+import org.eclipse.gmf.runtime.notation.NotationPackage;
+import org.eclipse.gmf.runtime.notation.View;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.papyrus.core.utils.EditorUtils;
+import org.eclipse.papyrus.navigator.commands.EObjectInheritanceCopyCommand;
+import org.eclipse.papyrus.navigator.internal.Activator;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * The Class GenericTransformer. Permits to transform an eobject of eclass to another eclass
+ */
+public class GenericTransformer {
+
+ /** The factories to create eObjects */
+ private static HashMap<String, AdapterFactory> factories = new HashMap<String, AdapterFactory>();
+
+ /** extension to recover factories */
+ private static final String EXT_FACTORIES = "org.eclipse.emf.edit.itemProviderAdapterFactories";
+
+ /** title of the warning dialog */
+ private static final String WARNING_TITLE = "Problems during transformation";
+
+ /** message of the warning dialog */
+ private static final String WARNING_MSG = "It seems the transformation you want to perform can't be executed";
+
+ /** command to execute the whole transformation */
+ private CompositeCommand globalCommand;
+
+ /** element to transform */
+ private EObject element;
+
+ /** views referencing the element */
+ private Set<View> referencingViews = new HashSet<View>();
+
+ /** command to execute the model transformation */
+ private EObjectInheritanceCopyCommand commandModel;
+
+ /** whether the graphical edit parts must also be transformed */
+ private boolean graphCopy = true;
+
+ /** the command to import new graphical edit parts */
+ private ImporterCommand importerCommand;
+
+ /**
+ * Instantiates a new generic transformer.
+ *
+ * @param currentNode
+ * the current node
+ */
+ public GenericTransformer(AbstractGraphicalEditPart currentNode) {
+ this(currentNode, true);
+ }
+
+ /**
+ * Instantiates a new generic transformer. and specify if we have to perform graphical copy
+ *
+ * @param currentNode
+ * the current node
+ * @param graphCopy
+ * the graph copy
+ */
+ public GenericTransformer(AbstractGraphicalEditPart currentNode, boolean graphCopy) {
+ this.graphCopy = graphCopy;
+ if(currentNode != null) {
+ Object model = currentNode.getModel();
+ if(model instanceof View) {
+ this.element = ((View)model).getElement();
+ }
+ }
+ }
+
+ /**
+ * Instantiates a new generic transformer.
+ *
+ * @param currentEobject
+ * the current eobject
+ */
+ public GenericTransformer(EObject currentEobject) {
+ this.element = currentEobject;
+ }
+
+ /**
+ * Transform the element to the given eclass.
+ *
+ * @param eclass
+ * the targeted eclass
+ */
+ public void transform(EClass eclass) {
+
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ IEditorPart editor = page.getActiveEditor();
+ CommandStack stack = (CommandStack)editor.getAdapter(CommandStack.class);
+ globalCommand = new CompositeCommand("Generic Transformation");
+
+ if(graphCopy) {
+ if(element != null) {
+ EReference[] features = { NotationPackage.eINSTANCE.getView_Element() };
+ Collection<?> views = EMFCoreUtil.getReferencers(element, features);
+ for(Object view : views) {
+ if(view instanceof View) {
+ referencingViews.add((View)view);
+ }
+ }
+ }
+ }
+ if(stack != null) {
+ // maybe extension point for stereotypes
+ EObject model = (EObject)AdapterFactoryEditingDomain.unwrap(element);
+ // get mixed editing domain to do transaction
+ TransactionalEditingDomain domain = EditorUtils.getTransactionalEditingDomain();
+ commandModel = new EObjectInheritanceCopyCommand(model, eclass, domain);
+ globalCommand.add(commandModel);
+ if(graphCopy) {
+ importerCommand = new ImporterCommand(domain);
+ if(importerCommand.canExecute()) {
+ globalCommand.add(importerCommand);
+ }
+
+ }
+ if(globalCommand.canExecute()) {
+ try {
+ // drop caches about input element
+ ECrossReferenceAdapter cross = ECrossReferenceAdapter.getCrossReferenceAdapter(element);
+ if(cross != null) {
+ cross.unsetTarget(element);
+ }
+ stack.execute(new ICommandProxy(globalCommand));
+ } catch (Exception e) {
+ MessageDialog.openWarning(Display.getDefault().getActiveShell(), WARNING_TITLE, WARNING_MSG);
+ e.printStackTrace();
+ }
+ } else {
+ MessageDialog.openWarning(Display.getDefault().getActiveShell(), WARNING_TITLE, WARNING_MSG);
+ }
+ }
+ }
+
+ /**
+ * The Class ImporterCommand. permits to add the importer in the compound command
+ */
+ private class ImporterCommand extends AbstractTransactionalCommand {
+
+ /**
+ * Constructor.
+ *
+ * @param domain
+ * transactional editing domain
+ */
+ public ImporterCommand(TransactionalEditingDomain domain) {
+ super(domain, "Import graphical nodes", null);
+ }
+
+ /**
+ * Execute the command
+ *
+ * @param monitor
+ * progress monitor
+ * @param info
+ * the info
+ * @return the command result
+ * @throws ExecutionException
+ */
+ protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
+ graphCopy(null, commandModel.getResultEobject());
+ return CommandResult.newOKCommandResult();
+ }
+
+ /**
+ * Graph copy, make a drag and drop of the new object on all diagrams
+ *
+ * @param diagramDomain
+ * the mixed domain
+ * @param target
+ * the target
+ * @param globalCommand2
+ * @param graphElement
+ * the graph element
+ * @param oldLocation
+ * the old location
+ * @param editpart
+ * the editpart
+ */
+ private void graphCopy(IDiagramEditDomain domain, EObject target) {
+ for(View graphElement : referencingViews) {
+ View parent = ViewUtil.getContainerView(graphElement);
+ if(parent == null || graphElement.getDiagram() == null) {
+ // this is an orphaned view. Skip it
+ continue;
+ }
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ // Get the edit part of the diagram containing the view.
+ DiagramEditPart diagramEditPart = null;
+ IEditorPart activeEditorPart = page.getActiveEditor();
+ if(activeEditorPart instanceof IDiagramWorkbenchPart) {
+ if(graphElement.getDiagram().equals(((IDiagramWorkbenchPart)activeEditorPart).getDiagram())) {
+ diagramEditPart = ((IDiagramWorkbenchPart)activeEditorPart).getDiagramEditPart();
+ }
+ }
+ if(diagramEditPart == null) {
+ // search in other editor parts than the active one
+ List<?> editorParts = EditorService.getInstance().getRegisteredEditorParts();
+ for(Object editorPart : editorParts) {
+ if(editorPart instanceof IDiagramWorkbenchPart) {
+ if(graphElement.getDiagram().equals(((IDiagramWorkbenchPart)editorPart).getDiagram())) {
+ diagramEditPart = ((IDiagramWorkbenchPart)editorPart).getDiagramEditPart();
+ }
+ }
+ }
+ }
+
+ if(diagramEditPart != null) {
+ EditPart containerPart = (EditPart)diagramEditPart.getViewer().getEditPartRegistry().get(parent);
+ // create the new transformed view
+ DropObjectsRequest req = new DropObjectsRequest();
+ req.setObjects(Collections.singletonList(target));
+ if(graphElement instanceof Node) {
+ LayoutConstraint constraint = ((Node)graphElement).getLayoutConstraint();
+ if(constraint instanceof Location) {
+ Location location = (Location)constraint;
+ req.setLocation(new Point(location.getX(), location.getY()));
+ }
+ }
+ if(req.getLocation() == null) {
+ req.setLocation(new Point());
+ }
+ Command partCreationCmd = containerPart.getCommand(req);
+ partCreationCmd.execute();
+ View newView = null;
+ if(partCreationCmd instanceof ICommandProxy) {
+ CommandResult res = ((ICommandProxy)partCreationCmd).getICommand().getCommandResult();
+ Object newValue = res.getReturnValue();
+ if(newValue instanceof Collection<?>) {
+ for(Object value : (Collection<?>)newValue) {
+ if(value instanceof ViewDescriptor) {
+ newView = (View)((ViewDescriptor)value).getAdapter(View.class);
+ }
+ }
+ } else if(newValue instanceof ViewDescriptor) {
+ newView = (View)((ViewDescriptor)newValue).getAdapter(View.class);
+ }
+ }
+ //with ViewRefactorHelper, copy view properties on the old one
+ if(newView != null) {
+ ViewTransformerHelper helper = new ViewTransformerHelper(diagramEditPart.getDiagramPreferencesHint());
+ helper.copyMixedViewFeatures(graphElement, newView);
+ }
+ // delete the old view
+ GroupRequest deleteReq = new GroupRequest(RequestConstants.REQ_DELETE);
+ EditPart oldPart = (EditPart)diagramEditPart.getViewer().getEditPartRegistry().get(graphElement);
+ Command partDeletionCmd = oldPart.getCommand(deleteReq);
+ partDeletionCmd.execute();
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * ViewTransformerHelper allow to refactor a view to copy properties from another view
+ */
+ private static class ViewTransformerHelper extends ViewRefactorHelper {
+
+ /**
+ * Constructor.
+ *
+ * @param preferencesHint
+ * the diagram preferences hint
+ */
+ public ViewTransformerHelper(PreferencesHint preferencesHint) {
+ super(preferencesHint);
+ }
+
+ /**
+ * Copy common features from a view to another
+ *
+ * @param oldView
+ * the old view to copy from
+ * @param newView
+ * the new view to copy to
+ */
+ public void copyMixedViewFeatures(View oldView, View newView) {
+ if(oldView instanceof Diagram && newView instanceof Diagram) {
+ copyDiagramFeatures((Diagram)oldView, (Diagram)newView);
+ } else if(oldView instanceof Node && newView instanceof Node) {
+ copyNodeFeatures((Node)oldView, (Node)newView);
+ } else if(oldView instanceof Edge && newView instanceof Edge) {
+ copyEdgeFeatures((Edge)oldView, (Edge)newView);
+ } else {
+ copyViewFeatures(oldView, newView);
+ }
+ }
+
+ }
+
+ /**
+ * Gets all the super types.
+ *
+ * @param class1
+ * the class
+ *
+ * @return super types
+ */
+ public static HashSet<EClass> getAllSuperTypes(EClass class1) {
+ HashSet<EClass> results = new HashSet<EClass>();
+ results.addAll(class1.getEAllSuperTypes());
+ return results;
+ }
+
+ /**
+ * Gets the factory from uri.
+ *
+ * @param uri
+ * the uri
+ *
+ * @return the factory
+ */
+ public static AdapterFactory getFactory(String uri) {
+ AdapterFactory factory = factories.get(uri);
+ if(factory == null) {
+ IConfigurationElement[] extensions = Platform.getExtensionRegistry().getConfigurationElementsFor(EXT_FACTORIES);
+ for(IConfigurationElement e : extensions) {
+ if(uri.equals(e.getAttribute("uri"))) {
+ try {
+ factory = (AdapterFactory)e.createExecutableExtension("class");
+ if(factory != null) {
+ factories.put(uri, factory);
+ }
+ } catch (CoreException e1) {
+ // do nothing
+ }
+ }
+ }
+ }
+ return factory;
+ }
+
+ /**
+ * Checks if a transformation is possible.
+ *
+ * @param eclass
+ * the eclass
+ *
+ * @return the multi status
+ */
+ public MultiStatus isTransformationPossible(EClass eclass) {
+ MultiStatus result = new MultiStatus(Activator.PLUGIN_ID, 0, "Type incompatibility", null);
+ if(element != null) {
+ Collection<Setting> usages = EObjectInheritanceCopyCommand.getUsages(element);
+ if(usages != null) {
+ for(EStructuralFeature.Setting nonNavigableInverseReference : usages) {
+ EStructuralFeature structuralFeature = nonNavigableInverseReference.getEStructuralFeature();
+ if(!(nonNavigableInverseReference.getEObject() instanceof View)) {
+ boolean compatible = EObjectInheritanceCopyCommand.isCompatible(structuralFeature.getEType(), eclass);
+ if(!compatible) {
+ String econtainer = structuralFeature.eContainer() instanceof EClassifier ? ((EClassifier)structuralFeature.eContainer()).getName() + " ( " + nonNavigableInverseReference.getEObject().toString() + " )" : structuralFeature.eContainer().toString();
+ Status s = new Status(Status.WARNING, Activator.PLUGIN_ID, String.format("an element typed %s references your selection, we can not assign instead of your selection an object typed %s", econtainer, eclass.getName()));
+ result.add(s);
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/commands/EObjectInheritanceCopyCommand.java b/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/commands/EObjectInheritanceCopyCommand.java
new file mode 100644
index 00000000000..35d7ec8d720
--- /dev/null
+++ b/plugins/uml/org.eclipse.papyrus.navigator/src/org/eclipse/papyrus/navigator/commands/EObjectInheritanceCopyCommand.java
@@ -0,0 +1,411 @@
+/***************************************************
+* Copyright (c) 2010 Atos Origin.
+
+*
+* 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:
+* Atos Origin - Initial API and implementation
+*
+****************************************************/
+package org.eclipse.papyrus.navigator.commands;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
+import org.eclipse.gmf.runtime.emf.type.core.commands.DestroyElementCommand;
+import org.eclipse.gmf.runtime.emf.type.core.commands.SetValueCommand;
+import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
+import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
+import org.eclipse.gmf.runtime.notation.Diagram;
+import org.eclipse.gmf.runtime.notation.View;
+
+/**
+ * The Class EObjectInheritanceCopyCommand. it takes an eobject in parameter and copy all the elements contained in the
+ * source to the target and adds the target to the container of the source
+ */
+public class EObjectInheritanceCopyCommand extends CompositeCommand {
+
+ private final EObject sourceEObject;
+
+ private final EObject targetEObject;
+
+ private final TransactionalEditingDomain editingDomain;
+
+ private Collection<Object> alreadyManaged = new LinkedList<Object>();
+
+ public EObjectInheritanceCopyCommand(EObject source, EClass target, TransactionalEditingDomain adapterFactoryEditingDomain) {
+ super("Inheritance copy");
+ this.sourceEObject = source;
+ this.targetEObject = target.getEPackage().getEFactoryInstance().create(target);
+ this.editingDomain = adapterFactoryEditingDomain;
+ if(sourceEObject == null || targetEObject == null || editingDomain == null) {
+ throw new IllegalArgumentException("Please provide non null arguments");
+ }
+ init();
+ if(sourceEObject.eContainingFeature().isMany()) {
+ replace(sourceEObject.eContainer(), sourceEObject, targetEObject, sourceEObject.eContainingFeature());
+ } else {
+ add(new CustomSetCommand(editingDomain, sourceEObject.eContainer(), sourceEObject.eContainingFeature(), targetEObject, sourceEObject, sourceEObject.eContainingFeature()));
+ add(new DestroyElementCommand(new DestroyElementRequest(editingDomain, sourceEObject, false)));
+ }
+ }
+
+ private void init() {
+ modelCopy(sourceEObject, targetEObject);
+ crossReference(sourceEObject, targetEObject);
+ }
+
+ /**
+ * Model copy, copy the eobject source attributes to target's
+ *
+ * @param mixedDomain
+ * the mixed domain
+ * @param source
+ * the source
+ * @param target
+ * the target
+ */
+ private void modelCopy(EObject source, EObject target) {
+ EClass eclass = source.eClass();
+ if(eclass != null) {
+ EList<EStructuralFeature> eAllStructuralFeatures = eclass.getEAllStructuralFeatures();
+ for(EStructuralFeature e : eAllStructuralFeatures) {
+ if(contains(target.eClass(), e) && isCompatible(e.getEType(), target.eClass().getEStructuralFeature(e.getName()).getEType())) {
+ manageFeature(source, target, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Contains. check if the target eclass contains a estructuralfeature with the same name less rigorous can work for
+ * many cases
+ *
+ * @param target
+ * the target
+ * @param e
+ * the e
+ *
+ * @return true, if successful
+ */
+ private boolean contains(EClass target, EStructuralFeature e) {
+ EList<EStructuralFeature> features = target.getEAllStructuralFeatures();
+ for(EStructuralFeature f : features) {
+ if(f.getName().equals(e.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Manage feature for cross.
+ *
+ * @param mixedDomain
+ * the mixed domain
+ * @param theObjectWithCross
+ * the the object with cross
+ * @param source
+ * the source
+ * @param target
+ * the target
+ * @param structuralFeature
+ * the structural feature
+ */
+ private void manageFeatureForCross(EObject theObjectWithCross, EObject source, EObject target, EStructuralFeature structuralFeature) {
+ boolean compatible = isCompatible(structuralFeature.getEType(), target.eClass());
+
+ if(compatible && structuralFeature.isChangeable() && !structuralFeature.isDerived()) {
+ if(structuralFeature.isMany()) {
+ replace(theObjectWithCross, source, target, structuralFeature);
+ } else {
+ add(new SetValueCommand(new SetRequest(editingDomain, theObjectWithCross, structuralFeature, target)));
+ }
+ } else if(!compatible) {
+ if(structuralFeature.isMany()) {
+ remove(theObjectWithCross, source, structuralFeature);
+ } else {
+ add(new SetValueCommand(new SetRequest(editingDomain, theObjectWithCross, structuralFeature, null)));
+ }
+ }
+
+ }
+
+ private void remove(EObject owner, Object source, EStructuralFeature structuralFeature) {
+ if(!alreadyManaged.contains(source)) {
+
+ if(owner == null && structuralFeature == null) {
+ if(source instanceof EObject) {
+ add(new DestroyElementCommand(new DestroyElementRequest(editingDomain, (EObject)source, false)));
+ }
+ } else {
+ Object value = owner.eGet(structuralFeature);
+ if(value instanceof Collection<?>) {
+ List<Object> newList = new ArrayList<Object>((Collection<?>)value);
+ newList.remove(source);
+ add(new SetValueCommand(new SetRequest(editingDomain, owner, structuralFeature, newList)));
+ } else if(source.equals(value)) {
+ add(new SetValueCommand(new SetRequest(editingDomain, owner, structuralFeature, null)));
+ } else {
+ add(new SetValueCommand(new SetRequest(editingDomain, owner, structuralFeature, null)));
+ }
+ }
+ alreadyManaged.add(source);
+ }
+ }
+
+ private void replace(EObject owner, Object source, Object target, EStructuralFeature structuralFeature) {
+ if(!alreadyManaged.contains(source)) {
+
+ if(owner == null && structuralFeature == null) {
+ if(source instanceof EObject) {
+ add(new DestroyElementCommand(new DestroyElementRequest(editingDomain, (EObject)source, false)));
+ }
+ } else {
+ Object value = owner.eGet(structuralFeature);
+ if(value instanceof Collection<?>) {
+ List<Object> newList = new ArrayList<Object>((Collection<?>)value);
+ int index = newList.indexOf(source);
+ if(index >= 0) {
+ newList.remove(index);
+ newList.add(index, target);
+ add(new SetValueCommand(new SetRequest(editingDomain, owner, structuralFeature, newList)));
+ }
+ } else if(source.equals(value)) {
+ add(new SetValueCommand(new SetRequest(editingDomain, owner, structuralFeature, target)));
+ } else {
+ add(new SetValueCommand(new SetRequest(editingDomain, owner, structuralFeature, target)));
+ }
+ }
+ alreadyManaged.add(source);
+ }
+ }
+
+ @Override
+ public IStatus undo(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
+ return super.undo(progressMonitor, info);
+ }
+
+ /**
+ * Cross reference. Manage eobjects referencing the source eobject
+ *
+ * @param mixedDomain
+ * the mixed domain
+ * @param source
+ * the source eobject
+ * @param target
+ * the target eobject
+ */
+ private void crossReference(EObject source, EObject target) {
+ Collection<EStructuralFeature.Setting> collection = getUsages(source);
+ if(collection != null) {
+ for(EStructuralFeature.Setting nonNavigableInverseReference : collection) {
+ EStructuralFeature structuralFeature = nonNavigableInverseReference.getEStructuralFeature();
+ if(!(nonNavigableInverseReference.getEObject() instanceof View)) {
+ manageFeatureForCross(nonNavigableInverseReference.getEObject(), source, target, structuralFeature);
+ } else if(nonNavigableInverseReference.getEObject() instanceof Diagram) {
+ Diagram di = (Diagram)nonNavigableInverseReference.getEObject();
+ remove(null, di, null);
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the usages.
+ *
+ * @param source
+ * the source
+ *
+ * @return the usages or null if there is no usages
+ */
+ public static Collection<EStructuralFeature.Setting> getUsages(EObject source) {
+ Collection<EStructuralFeature.Setting> collection = null;
+ ECrossReferenceAdapter crossReferenceAdapter = ECrossReferenceAdapter.getCrossReferenceAdapter(source);
+ if(crossReferenceAdapter != null) {
+ collection = crossReferenceAdapter.getNonNavigableInverseReferences(source);
+ } else {
+ collection = EcoreUtil.UsageCrossReferencer.find(source, source.eResource().getResourceSet());
+ }
+ return collection;
+ }
+
+ /**
+ * Checks if a type is compatible to another.
+ *
+ * @param type
+ * the type
+ * @param target
+ * the target
+ *
+ * @return true, if is compatible
+ */
+ public static boolean isCompatible(EClassifier type, EClassifier target) {
+ Collection<EClassifier> types = new LinkedList<EClassifier>();
+ if(target instanceof EClass) {
+ EClass eclass = (EClass)target;
+ types.addAll(eclass.getEAllSuperTypes());
+ }
+ if(!types.contains(target)) {
+ types.add(target);
+ }
+ return types.contains(type);
+ }
+
+ /**
+ * Manage a feature for the attribute's copy.
+ *
+ * @param mixedDomain
+ * the mixed domain
+ * @param source
+ * the source
+ * @param target
+ * the target
+ * @param feature
+ * the e
+ */
+ @SuppressWarnings("unchecked")
+ private void manageFeature(EObject source, EObject target, EStructuralFeature feature) {
+ EStructuralFeature targetFeature = getFeature(target, feature.getName());
+
+ if(feature.getUpperBound() <= targetFeature.getUpperBound() && feature.getLowerBound() >= targetFeature.getLowerBound()) {
+ if(feature.isChangeable() && !feature.isDerived()) {
+ Object value = source.eGet(feature);
+ if(feature.isMany() && targetFeature.isMany()) {
+ Collection<EObject> list = (Collection<EObject>)value;
+ if(list != null && !list.isEmpty()) {
+ Collection<EObject> newList = new LinkedList<EObject>();
+ newList.addAll(list);
+ if(feature instanceof EReference && !((EReference)feature).isContainment()) {
+ add(new SetValueCommand(new SetRequest(editingDomain, target, targetFeature, newList)));
+ } else if(feature instanceof EReference && ((EReference)feature).isContainment()) {
+ Collection<Object> toTreat = new LinkedList<Object>();
+ for(Object o : newList) {
+ if(!alreadyManaged.contains(o)) {
+ toTreat.add(o);
+ alreadyManaged.add(o);
+ }
+ }
+ add(new CustomAddCommand(editingDomain, target, targetFeature, newList, source, feature));
+ }
+ }
+ } else if(!feature.isMany() && !targetFeature.isMany()) {
+ if(value != null) {
+ if(!alreadyManaged.contains(value)) {
+ alreadyManaged.add(value);
+ add(new CustomSetCommand(editingDomain, target, targetFeature, value, source, feature));
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Gets a feature from a name
+ *
+ * @param eobject
+ * the eobject
+ * @param name
+ * the name
+ *
+ * @return the feature
+ */
+ private EStructuralFeature getFeature(EObject eobject, String name) {
+ return eobject.eClass().getEStructuralFeature(name);
+ }
+
+ /**
+ * Gets the result eobject.
+ *
+ * @return the result eobject
+ */
+ public EObject getResultEobject() {
+ return targetEObject;
+ }
+
+ /**
+ * The Class CustomSetCommand. permits to change a value from an eobject to eanother
+ */
+ private class CustomSetCommand extends SetValueCommand {
+
+ private EObject oldObject = null;
+
+ private EStructuralFeature oldFeature = null;
+
+ private Object oldValue = null;
+
+ public CustomSetCommand(TransactionalEditingDomain domain, EObject owner, EStructuralFeature feature, Object value, EObject old, EStructuralFeature structuralFeature) {
+ super(new SetRequest(domain, owner, feature, value));
+ oldObject = old;
+ oldFeature = structuralFeature;
+ oldValue = value;
+ }
+
+ @Override
+ protected IStatus doUndo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
+ IStatus result = super.doUndo(monitor, info);
+ oldObject.eSet(oldFeature, oldValue);
+ return result;
+ }
+
+ }
+
+ /**
+ * The Class CustomSetCommand. permits to change a value from an eobject to eanother
+ */
+ private class CustomAddCommand extends SetValueCommand {
+
+ private EObject oldObject = null;
+
+ private EStructuralFeature oldFeature;
+
+ private EStructuralFeature newFeature;
+
+ public CustomAddCommand(TransactionalEditingDomain editingDomain, EObject target, EStructuralFeature targetFeature, Collection<EObject> newList, EObject source, EStructuralFeature e) {
+ super(new SetRequest(editingDomain, target, targetFeature, newList));
+ oldObject = source;
+ oldFeature = e;
+ newFeature = targetFeature;
+ }
+
+ @Override
+ protected IStatus doUndo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
+ Object values = getElementToEdit().eGet(newFeature);
+ IStatus result = super.doUndo(monitor, info);
+ // this test permit to avoid modification from other command
+ // if getOwner list is empty it will perform error we avoid it
+ if(values instanceof Collection<?> && !((Collection<?>)values).isEmpty()) {
+ Collection<?> collection = (Collection<?>)values;
+ Collection<Object> collecOldObject = (Collection)oldObject.eGet(oldFeature);
+ for(Object o : collection) {
+ if(!collecOldObject.contains(o)) {
+ collecOldObject.add(o);
+ }
+ }
+ }
+ return result;
+ }
+ }
+}

Back to the top