diff options
Diffstat (limited to 'extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src')
8 files changed, 1253 insertions, 0 deletions
diff --git a/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/Activator.java b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/Activator.java new file mode 100755 index 00000000000..906b423896a --- /dev/null +++ b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/Activator.java @@ -0,0 +1,82 @@ +/***************************************************************************** + * Copyright (c) 2016 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.propertylifecycle; + +import org.eclipse.papyrus.infra.core.log.LogHelper; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.infra.papyrus.propertylifecycle"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + // The Log service + public static LogHelper log; + + public static String PLCSTRATEGY_TRACE = "PLCStrategy"; + + public static String PLCSTRATEGY_TYPES_TRACE = "PLCStrategy_Types"; + + public static String PLCSTRATEGY_SUPERTYPES_TRACE = "PLCStrategy_Supertypes"; + + public static String PLCSTRATEGY_REORIENT_TRACE = "PLCStrategy_Reorient"; + + public static String PLCSTRATEGY_CONFIGURE_TRACE = "PLCStrategy_Configure"; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + log = new LogHelper(plugin); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/commands/LifeCycleEditElementCommand.java b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/commands/LifeCycleEditElementCommand.java new file mode 100755 index 00000000000..04f976f876e --- /dev/null +++ b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/commands/LifeCycleEditElementCommand.java @@ -0,0 +1,155 @@ +/***************************************************************************** + * Copyright (c) 2016 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.propertylifecycle.commands; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.emf.ecore.EObject; +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.UnexecutableCommand; +import org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand; +import org.eclipse.gmf.runtime.emf.type.core.requests.AbstractEditCommandRequest; +import org.eclipse.papyrus.infra.tools.util.ClassLoaderHelper; +import org.eclipse.papyrus.propertylifecycle.AbstractValueProcessor; +import org.eclipse.papyrus.propertylifecycle.ElementProperty; +import org.eclipse.papyrus.propertylifecycle.JavaProcessor; +import org.eclipse.papyrus.propertylifecycle.utils.CommandValueProcessor; + +/** + * The command retrieved from the applicable strategies + */ +public class LifeCycleEditElementCommand extends EditElementCommand { + + private String featureLabel; + private ElementProperty featureStrategy; + // private Map<String, Object> accessedProcessors; + private AbstractEditCommandRequest request; + // private EObject elementToEdit; + + /** + * Constructor. + * + * @param commandLabel + * The label of the command + * @param elementToEdit + * The element to edit + * @param request + * The request to edit the element + * @param featureLabel + * The key used to sort through the possible strategies (the feature to edit) + * @param featureStrategy + * The {@link org.eclipse.papyrus.propertylifecycle.ElementProperty informations} used to calculate the new value + * @param accessedProcessors + * The accessed processors + */ + public LifeCycleEditElementCommand(String commandLabel, EObject elementToEdit, AbstractEditCommandRequest request, + String featureLabel, ElementProperty featureStrategy, Map<String, Object> accessedProcessors) { + super(commandLabel, elementToEdit, request); + // this.elementToEdit = elementToEdit; + this.request = request; + this.featureLabel = featureLabel; + this.featureStrategy = featureStrategy; + // this.accessedProcessors = accessedProcessors == null ? new HashMap<String, Object>() : accessedProcessors; + } + + /** + * Constructor. + * + * @param commandLabel + * The label of the command + * @param elementToEdit + * The element to edit + * @param request + * The request to edit the element + * @param featureLabel + * The key used to sort through the possible strategies (the feature to edit) + * @param featureStrategy + * The {@link org.eclipse.papyrus.propertylifecycle.ElementProperty informations} used to calculate the new value + */ + public LifeCycleEditElementCommand(String commandLabel, EObject elementToEdit, AbstractEditCommandRequest request, + String featureLabel, ElementProperty featureStrategy) { + this(commandLabel, elementToEdit, request, featureLabel, featureStrategy, null); + } + + /** + * Constructor. + * + * @param commandLabel + * The label of the command + * @param request + * The request to edit the element + * @param featureLabel + * The key used to sort through the possible strategies (the feature to edit) + * @param featureStrategy + * The {@link org.eclipse.papyrus.propertylifecycle.ElementProperty informations} used to calculate the new value + */ + public LifeCycleEditElementCommand(String commandLabel, AbstractEditCommandRequest request, + String featureLabel, ElementProperty featureStrategy) { + this(commandLabel, (EObject) request.getElementsToEdit().get(0), request, featureLabel, featureStrategy, null); + } + + @Override + protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { + + // Get the ICommand built in the processor and execute them in order to build the CommandResult + ICommand cmd = setProcessorValue(featureLabel, featureStrategy); + if (cmd == null || cmd instanceof UnexecutableCommand) { + throw new OperationCanceledException(); + } + + cmd.execute(monitor, info); + + return cmd.getCommandResult(); + } + + /** + * Filter the processors to return the correct {@link org.eclipse.gmf.runtime.common.core.command.Commandresult} + * + * @param property + * The {@link org.eclipse.papyrus.propertylifecycle.ElementProperty property} of the strategy + * @param elementType + * The element type of the element + * @return + * The {@link org.eclipse.gmf.runtime.common.core.command.Commandresult} of the element's edition + */ + private ICommand setProcessorValue(String featureLabel, ElementProperty property) { + AbstractValueProcessor propertyProcessor = property.getValueProcessor(); + + if (propertyProcessor instanceof JavaProcessor) { + // Cache the processor in order to limit the number of calls to the loader + Object processor; + String className = ((JavaProcessor) (property.getValueProcessor())).getClassName(); + // if (!accessedProcessors.containsKey(className)) { + processor = ClassLoaderHelper.newInstance(className); + // accessedProcessors.put(className, processor); + // } else { + // processor = accessedProcessors.get(className); + // } + + if (processor instanceof CommandValueProcessor) { + boolean isImmutable = property.getPriority() < 0 ? true : false; + return ((CommandValueProcessor) processor).setValueFromRequest(featureLabel, isImmutable, request); + } + } + + return null; + } + +} diff --git a/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/commands/LifecycleSetCommand.java b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/commands/LifecycleSetCommand.java new file mode 100755 index 00000000000..2b9ca0bd6be --- /dev/null +++ b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/commands/LifecycleSetCommand.java @@ -0,0 +1,130 @@ +/*****************************************************************************
+ * Copyright (c) 2016 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.propertylifecycle.commands;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.AbstractCommand;
+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.UnexecutableCommand;
+import org.eclipse.gmf.runtime.emf.type.core.commands.SetValueCommand;
+import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
+import org.eclipse.papyrus.infra.emf.gmf.command.GMFtoEMFCommandWrapper;
+
+/**
+ * End command used to set the value of the edited element through the propertylifecycle strategies
+ */
+public class LifecycleSetCommand extends AbstractCommand {
+
+ private TransactionalEditingDomain editingDomain;
+ private EObject eObject;
+ private EStructuralFeature feature;
+ private Object value;
+
+ private SetRequest setRequest;
+ private GMFtoEMFCommandWrapper emfCommand;
+
+ /**
+ * Constructor.
+ *
+ * @param editingDomain
+ * The editing domain
+ * @param label
+ * The label of the command
+ * @param eObject
+ * The object to edit
+ * @param feature
+ * The feature to edit
+ * @param value
+ * The new value to set
+ */
+ public LifecycleSetCommand(TransactionalEditingDomain editingDomain, String label,
+ EObject eObject, EStructuralFeature feature, Object value) {
+ super(label);
+ this.editingDomain = editingDomain;
+ this.eObject = eObject;
+ this.feature = feature;
+ this.value = value;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param label
+ * The label of the command
+ * @param eObject
+ * The object to edit
+ * @param feature
+ * The feature to edit
+ * @param value
+ * The new value to set
+ */
+ public LifecycleSetCommand(String label, EObject eObject, EStructuralFeature feature, Object value) {
+ this(null, label, eObject, feature, value);
+ }
+
+
+ @Override
+ protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
+ if (editingDomain != null) {
+ setRequest = new SetRequest(editingDomain, eObject, feature, value);
+ } else {
+ setRequest = new SetRequest(eObject, feature, value);
+ }
+
+ /** Final ! Should never call the service edit again or else risk a StackOverflow because of it will loop on itself */
+ // IElementEditService provider = ElementEditServiceUtils.getCommandProvider(eObject);
+ // ICommand createGMFCommand = provider.getEditCommand(setRequest);
+
+ ICommand gmfCommand = new SetValueCommand(setRequest);
+ if (gmfCommand == null || gmfCommand instanceof UnexecutableCommand) {
+ throw new OperationCanceledException();
+ }
+
+ emfCommand = new GMFtoEMFCommandWrapper(gmfCommand);
+ emfCommand.execute();
+
+ return gmfCommand.getCommandResult();
+ }
+
+
+ @Override
+ protected CommandResult doRedoWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
+ emfCommand.redo();
+ return null;
+ }
+
+ @Override
+ protected CommandResult doUndoWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
+ emfCommand.undo();
+ return null;
+ }
+
+ @Override
+ public boolean canRedo() {
+ return emfCommand != null;
+ }
+
+ @Override
+ public boolean canUndo() {
+ return emfCommand != null;
+ }
+
+}
diff --git a/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/helper/advice/PropertyLifecycleHelperAdvice.java b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/helper/advice/PropertyLifecycleHelperAdvice.java new file mode 100755 index 00000000000..c45342b696c --- /dev/null +++ b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/helper/advice/PropertyLifecycleHelperAdvice.java @@ -0,0 +1,249 @@ +/***************************************************************************** + * Copyright (c) 2016 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.propertylifecycle.helper.advice; + +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.gmf.runtime.common.core.command.CommandResult; +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.commands.CreateElementCommand; +import org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand; +import org.eclipse.gmf.runtime.emf.type.core.commands.SetValueCommand; +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.CreateElementRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.MoveRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.ReorientRelationshipRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; +import org.eclipse.papyrus.propertylifecycle.Activator; +import org.eclipse.papyrus.propertylifecycle.utils.PropertyLifecycleManager; + +/** + * Advice used to handle the calls for the applications of the {@link org.eclipse.papyrus.propertylifecycle.StrategyElement strategies} + * + */ +public class PropertyLifecycleHelperAdvice extends AbstractEditHelperAdvice { + + // private HashMap nameMap; + + /** + * Access used to edit the contained elements in case of a new container + * + * @see org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice#getAfterMoveCommand(org.eclipse.gmf.runtime.emf.type.core.requests.MoveRequest) + * + * @param request + * The move request + * @return + * new IStatus.OK command result. + */ + @Override + protected ICommand getAfterMoveCommand(final MoveRequest request) { + return super.getAfterMoveCommand(request); + // return new MoveElementsCommand(request) { + // + // @Override + // protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { + // Activator.log.trace(Activator.PLCSTRATEGY_TRACE, "moveElements: " + request.getElementsToMove().keySet() + // + ", in: " + request.getElementsToEdit()); + // + // for (Object object : request.getElementsToMove().keySet()) { + // if (!(object instanceof EObject)) { + // return CommandResult.newOKCommandResult(); + // } + // EObject element = (EObject) object; + // + // if (!(element instanceof NamedElement)) { + // return CommandResult.newOKCommandResult(); + // } + // Activator.log.trace(Activator.PLCSTRATEGY_TRACE, "ElementPreviousName: " + // + element.eGet(element.eClass().getEStructuralFeature("name"), true).toString()); + // + // NamedElement namedElement = (NamedElement) element; + // String name = PropertyLifecycleHelper.getAssociatedCreationName(request, element, null); + // + // if (name != null) { + // String initializedName = NamedElementUtil.getDefaultNameWithIncrementFromBase(name, element.eContainer().eContents(), element, ""); + // namedElement.setName(initializedName); + // Activator.log.trace(Activator.PLCSTRATEGY_TRACE, "ElementNewName: " + // + element.eGet(element.eClass().getEStructuralFeature("name"), true).toString()); + // } else { + // Retrieves the default name in case there are no strategy for this (element, container) couple + // String initializedName = NamedElementUtil.getDefaultNameWithIncrementFromBase(element.eClass().getName(), element.eContainer().eContents()); + // namedElement.setName(initializedName); + // IElementType umlET = ElementTypeRegistry.getInstance().getType("org.eclipse.papyrus.uml." + element.eClass().getName()); + // } + // + // } + // + // return super.doExecuteWithResult(progressMonitor, info); + //// return CommandResult.newOKCommandResult(); + // } + // }; + } + + + /** + * Access used to edit the values of a reoriented association + * + * @see org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice#getAfterReorientRelationshipCommand(org.eclipse.gmf.runtime.emf.type.core.requests.ReorientRelationshipRequest) + * + * @param request + * The reorient request + * @return + * new IStatus.OK command result. + */ + @Override + protected ICommand getAfterReorientRelationshipCommand(ReorientRelationshipRequest request) { + + return new EditElementCommand("Lifecycle Reorient Relashionship", request.getRelationship(), request) { + + @Override + protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { + PropertyLifecycleManager lifecycleManager = new PropertyLifecycleManager(request, 0); + ICommand lifecycleStrategyCommand = lifecycleManager.setAssociatedPropertyValues(); + if (lifecycleStrategyCommand != null) { + if (lifecycleStrategyCommand.canExecute()) { + lifecycleStrategyCommand.execute(monitor, info); + } + } + return CommandResult.newOKCommandResult(request.getRelationship()); + } + }; + + // ICommand compositeCommand = super.getAfterReorientRelationshipCommand(request); + // PropertyLifecycleManager lifecycleManager = new PropertyLifecycleManager(request, 0); + // ICommand lifecycleStrategyCommand = lifecycleManager.setAssociatedPropertyValues(); + // if (lifecycleStrategyCommand != null) { + // compositeCommand = CompositeCommand.compose(compositeCommand, lifecycleStrategyCommand); + // } + // + // return compositeCommand; + } + + + /** + * Access used to edit the values of the currently edited/created element + * + * @see org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice#getAfterConfigureCommand(org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest) + * + * @param request + * The configure request + * @return + * new IStatus.OK command result. + */ + @Override + protected ICommand getAfterConfigureCommand(final ConfigureRequest request) { + // // TEST1 - BEGIN + // if (element.eResource() instanceof XMIResource) { + // String xmiID = ((XMIResource) element.eResource()).getID(element); + // System.err.println(xmiID); + // } + // // TEST1 - END + + // The stereotypes are not yet applied at this stage, i.e. wait until execution to filter based on the matchers + return new ConfigureElementCommand(request) { + + @Override + protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { + PropertyLifecycleManager lifecycleManager = new PropertyLifecycleManager(request, 0); + ICommand lifecycleStrategyCommand = lifecycleManager.setAssociatedPropertyValues(); + if (lifecycleStrategyCommand != null) { + if (lifecycleStrategyCommand.canExecute()) { + lifecycleStrategyCommand.execute(monitor, info); + } + } + return CommandResult.newOKCommandResult(request.getElementToConfigure()); + } + }; + } + + + /** + * Access used to edit the values of the currently edited/created element + * + * @see org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice#getAfterCreateCommand(org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest) + * + * @param request + * The creation request + * @return + * new IStatus.OK command result. + */ + @Override + protected ICommand getAfterCreateCommand(final CreateElementRequest request) { + + // The stereotypes are not yet applied at this stage, i.e. wait until execution to filter based on the matchers + return new CreateElementCommand(request) { + + @Override + protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { + PropertyLifecycleManager lifecycleManager = new PropertyLifecycleManager(request, 0); + ICommand lifecycleStrategyCommand = lifecycleManager.setAssociatedPropertyValues(); + if (lifecycleStrategyCommand != null) { + if (lifecycleStrategyCommand.canExecute()) { + lifecycleStrategyCommand.execute(monitor, info); + } + } + return CommandResult.newOKCommandResult(request.getNewElement()); + } + }; + } + + + /** + * Access used to edit the contained elements in case of a modified value of the container + * + * @see org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice#getAfterSetCommand(org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest) + * + * @param request + * The editing request + * @return + * The Command wrapping the strategy commands + */ + @Override + protected ICommand getAfterSetCommand(SetRequest request) { + // EObject element = request.getElementToEdit(); + // if (element instanceof NamedElement) { + // Activator.log.trace(Activator.PLCSTRATEGY_TRACE, ", name: " + ((NamedElement) element).getName()); + // }; + + return new SetValueCommand(request) { + + @Override + protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { + PropertyLifecycleManager lifecycleManager = new PropertyLifecycleManager(request, 0); + ICommand lifecycleStrategyCommand = lifecycleManager.setAssociatedPropertyValues(); + if (lifecycleStrategyCommand != null) { + if (lifecycleStrategyCommand.canExecute()) { + lifecycleStrategyCommand.execute(monitor, info); + } + } + return CommandResult.newOKCommandResult(request.getElementToEdit()); + }; + }; + + // ICommand compositeCommand = super.getAfterSetCommand(request); + // PropertyLifecycleManager lifecycleManager = new PropertyLifecycleManager(request, 0); + // ICommand lifecycleStrategyCommand = lifecycleManager.setAssociatedPropertyValues(); + // compositeCommand = CompositeCommand.compose(compositeCommand, lifecycleStrategyCommand); + // if (lifecycleStrategyCommand != null) { + // compositeCommand = CompositeCommand.compose(compositeCommand, lifecycleStrategyCommand); + // } + // + // return compositeCommand; + } + +} diff --git a/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/messages/Messages.java b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/messages/Messages.java new file mode 100755 index 00000000000..bf9c7a351e6 --- /dev/null +++ b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/messages/Messages.java @@ -0,0 +1,35 @@ +/***************************************************************************** + * Copyright (c) 2016 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.propertylifecycle.messages; + +import org.eclipse.osgi.util.NLS; + +/** + * + */ +public class Messages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.papyrus.infra.propertylifecycle.messages.messages"; //$NON-NLS-1$ + + public static String FEATURELABEL_NAME; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } + +} diff --git a/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/messages/messages.properties b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/messages/messages.properties new file mode 100755 index 00000000000..974799064a2 --- /dev/null +++ b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/messages/messages.properties @@ -0,0 +1 @@ +FEATURELABEL_NAME=name
\ No newline at end of file diff --git a/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/utils/CommandValueProcessor.java b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/utils/CommandValueProcessor.java new file mode 100755 index 00000000000..de14bfc7c6e --- /dev/null +++ b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/utils/CommandValueProcessor.java @@ -0,0 +1,26 @@ +/***************************************************************************** + * Copyright (c) 2016 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.propertylifecycle.utils; + +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.emf.type.core.requests.AbstractEditCommandRequest; + +/** + * + */ +public interface CommandValueProcessor { + + public ICommand setValueFromRequest(String featureLabel, boolean isImmutable, AbstractEditCommandRequest request); + +} diff --git a/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/utils/PropertyLifecycleManager.java b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/utils/PropertyLifecycleManager.java new file mode 100755 index 00000000000..9a71489714b --- /dev/null +++ b/extraplugins/propertylifecycle/org.eclipse.papyrus.propertylifecycle/src/org/eclipse/papyrus/propertylifecycle/utils/PropertyLifecycleManager.java @@ -0,0 +1,575 @@ +/***************************************************************************** + * Copyright (c) 2015 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.propertylifecycle.utils; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +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.ElementTypeRegistry; +import org.eclipse.gmf.runtime.emf.type.core.IElementType; +import org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand; +import org.eclipse.gmf.runtime.emf.type.core.requests.AbstractEditCommandRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.ReorientRelationshipRequest; +import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; +import org.eclipse.papyrus.infra.types.core.impl.ConfiguredHintedMetamodelElementType; +import org.eclipse.papyrus.infra.types.core.impl.ConfiguredHintedSpecializationElementType; +import org.eclipse.papyrus.propertylifecycle.Activator; +import org.eclipse.papyrus.propertylifecycle.ElementContainer; +import org.eclipse.papyrus.propertylifecycle.ElementProperty; +import org.eclipse.papyrus.propertylifecycle.StrategyElement; +import org.eclipse.papyrus.propertylifecycle.commands.LifeCycleEditElementCommand; +import org.eclipse.papyrus.propertylifecycle.preferences.utils.PropertyLifecyclePreferencesManager; + + +/** + * Used to match the handled element against the selected strategies + * + */ +public class PropertyLifecycleManager { + + /** The manager containing all the strategies informations */ + private PropertyLifecyclePreferencesManager preferencesManager = new PropertyLifecyclePreferencesManager(); + + /** The element's type */ + private IElementType elementType; + + /** The handled element */ + private EObject element; + + /** The list of all loaded processors (reflexively accessed) */ + private Map<String, Object> accessedProcessors = new HashMap<String, Object>(); + + /** The command encompassing the changes to the handled element */ + private ICommand command; + + /** The request used to extract the element's contextual informations */ + private AbstractEditCommandRequest request; + + /** The depth to which the strategies will be matched against the handled element's contents */ + private int depth; + + + /** + * + * Constructor. Default depth set to -1 + * + * @param request + * The {@link org.eclipse.gmf.runtime.emf.type.core.requests.AbstractEditCommandRequest} of the edited element + */ + public PropertyLifecycleManager(AbstractEditCommandRequest request) { + this(request, -1); + } + + /** + * + * Constructor. + * + * @param request + * The {@link org.eclipse.gmf.runtime.emf.type.core.requests.AbstractEditCommandRequest} of the edited element + * @param depth + * The depth to which the strategies will be matched against the handled element's contents. Negative numbers for infinite depth. + */ + public PropertyLifecycleManager(AbstractEditCommandRequest request, int depth) { + this.request = request; + setElementsVariables(this.request); + this.depth = depth; + } + + /** + * Set the variables {@link #element} and {@link #elementType} used to filter the strategies + * + * @param request + * The manipulated {@link org.eclipse.gmf.runtime.emf.type.core.requests.AbstractEditCommandRequest} + */ + private void setElementsVariables(AbstractEditCommandRequest request) { + if (request instanceof CreateElementRequest) { + CreateElementRequest createRequest = (CreateElementRequest) request; + elementType = createRequest.getElementType(); + // TODO do a better job at fishing out the created element + // Object object = createRequest.getElementsToEdit().get(0); + // element = object instanceof EObject ? (EObject) object : null; + element = ((CreateElementRequest) request).getNewElement(); + } + + if (request instanceof ConfigureRequest) { + ConfigureRequest confRequest = ((ConfigureRequest) request); + elementType = confRequest.getTypeToConfigure(); + element = confRequest.getElementToConfigure(); + } + + if (request instanceof ReorientRelationshipRequest) { + ReorientRelationshipRequest reorientRequest = (ReorientRelationshipRequest) request; + element = reorientRequest.getRelationship(); + String testString = element.eClass().getInstanceClassName(); + // TODO find an alternative to this placeholder element type + IElementType papyrusType = ElementTypeRegistry.getInstance().getType(testString.replace("org.eclipse.uml2", "org.eclipse.papyrus")); + elementType = papyrusType != null ? papyrusType : ElementTypeRegistry.getInstance().getElementType(element.eClass()); + } + + if (request instanceof SetRequest) { + SetRequest setRequest = (SetRequest) request; + element = setRequest.getElementToEdit(); + String testString = element.eClass().getInstanceClassName(); + // TODO find an alternative to this placeholder element type + IElementType papyrusType = ElementTypeRegistry.getInstance().getType(testString.replace("org.eclipse.uml2", "org.eclipse.papyrus")); + elementType = papyrusType != null ? papyrusType : ElementTypeRegistry.getInstance().getElementType(element.eClass()); + } + + } + + + /** + * Construct the {@link org.eclipse.gmf.runtime.common.core.command.ICommand} of the edition + * + * @return + * The {@link org.eclipse.gmf.runtime.common.core.command.CompositeCommand} from the different changes brought by the current strategies + */ + public ICommand setAssociatedPropertyValues() { + + // This will avoid an NPE later and indicates that there is not yet a way to deal with the given request + if (elementType == null || element == null) { + return command; + } + + Collection<StrategyElement> matchingStrategies = new LinkedList<StrategyElement>(); + matchingStrategies.addAll(preferencesManager.retrieveAllStrategies()); + + matchingStrategies = filterOnContext(matchingStrategies, elementType, element); + Activator.log.trace(Activator.PLCSTRATEGY_TRACE, matchingStrategies.size() + ": " + matchingStrategies); + + if (matchingStrategies.size() > 0) { + Set<String> modifiableFeatures = getAllModifiableFeatures(matchingStrategies); + + if (modifiableFeatures.size() > 0) { + HashMap<String, ElementProperty> newFeatureValues = getNewFeatureValues(matchingStrategies, modifiableFeatures); + + for (EStructuralFeature elementFeature : element.eClass().getEAllStructuralFeatures()) { + String featureLabel = elementFeature.getName(); + if (newFeatureValues.keySet().contains(featureLabel)) { + ElementProperty featureStrategy = newFeatureValues.get(featureLabel); + if (command == null) { + command = getAssociatedCommand(featureLabel, featureStrategy, request); + } else { + command = CompositeCommand.compose(command, getAssociatedCommand(featureLabel, featureStrategy, request)); + } + } + } + } + } + + // Iterate on all the nested elements, if any, to match them against the current strategies + applyStrategiesToContents(element); + + return command; + } + + + /** + * Filter regrouping all the contextual information in which the element is created + * + * @param strategies + * The possible strategies + * @param elementType + * The element type of the element + * @param element + * The element + * @return + * The list of Strategies matching the element + */ + private Collection<StrategyElement> filterOnContext(Collection<StrategyElement> strategies, IElementType elementType, EObject element) { + Map<String, StrategyElement> matchingStrategies = new HashMap<String, StrategyElement>(); + // LinkedList<IElementType> elementSuperTypes = new LinkedList<IElementType>(Arrays.asList(elementType.getAllSuperTypes())); + String trimmedID = getTrimmedID(elementType); + if (elementType != null) { + Activator.log.trace(Activator.PLCSTRATEGY_TRACE, "IElementType_ID: " + elementType.getId()); + Activator.log.trace(Activator.PLCSTRATEGY_TRACE, "IElementType_trimmedID: " + trimmedID); + } + + for (StrategyElement strategy : strategies) { + + if (trimmedID == null) { + continue; + } + + // Filter on the specified element specializedType + if (!filterOnElement(elementType, element, strategy)) { + continue; + } + + // Verify that the user specified a container to the strategy element + if (!filterOnContainer(element, strategy)) { + continue; + } + + // Filtered list + matchingStrategies.put(strategy.getId(), strategy); + } + + return matchingStrategies.values(); + + } + + + /** + * Filter based on the element's {@link org.eclipse.gmf.runtime.emf.type.core.ElementType} + * and its possible {@link org.eclipse.gmf.runtime.emf.type.core.SpecializationType} + * + * @param elementType + * The element type of the element + * @param element + * The element's EObject + * @param strategy + * The strategy the element is being matched against + * @return + * If the element is a match to the strategy or not + */ + private boolean filterOnElement(IElementType elementType, EObject element, StrategyElement strategy) { + IElementType strategyBaseType = ElementTypeRegistry.getInstance().getType(strategy.getBaseType()); + IElementType strategySpeType = ElementTypeRegistry.getInstance().getType(strategy.getSpecializedType()); + + // 1- Filter on the element baseType + if (strategyBaseType == null) { + return false; + } + // TEST1 - BEGIN + if (strategyBaseType instanceof ConfiguredHintedMetamodelElementType) { + ConfiguredHintedMetamodelElementType metatype = (ConfiguredHintedMetamodelElementType) strategyBaseType; + Activator.log.trace(Activator.PLCSTRATEGY_TYPES_TRACE, "ConfiguredHintedMetamodelElementType: " + metatype); + } + if (strategyBaseType instanceof ConfiguredHintedSpecializationElementType) { + ConfiguredHintedSpecializationElementType spetype = (ConfiguredHintedSpecializationElementType) strategyBaseType; + Activator.log.trace(Activator.PLCSTRATEGY_TYPES_TRACE, "ConfiguredHintedSpecializationElementType: " + spetype); + } + // TEST1 - END + + if (strategyBaseType.equals(ElementTypeRegistry.getInstance().getType("org.eclipse.papyrus.uml.Element"))) { + return true; + } + // If the base type is a metamodel type, there are no matchers to use + if (strategyBaseType instanceof ConfiguredHintedMetamodelElementType) { + ConfiguredHintedMetamodelElementType metaType = (ConfiguredHintedMetamodelElementType) strategyBaseType; + Activator.log.trace(Activator.PLCSTRATEGY_TYPES_TRACE, "element: " + metaType.getEClass()); + Activator.log.trace(Activator.PLCSTRATEGY_TYPES_TRACE, "element: " + element.eClass()); + + if (!metaType.getEClass().equals(element.eClass())) { + return false; + } + } + // If the base type is a specialization type as the base type, there is a matcher available + if (strategyBaseType instanceof ConfiguredHintedSpecializationElementType) { + ConfiguredHintedSpecializationElementType speType = (ConfiguredHintedSpecializationElementType) strategyBaseType; + + if (speType.getMatcher() == null) { + // FIXME there are no matchers for: Extend(UseCase), + Activator.log.trace(Activator.PLCSTRATEGY_TRACE, speType.getId() + ", hasNoMatcher"); + return false; + } else { + Activator.log.trace(Activator.PLCSTRATEGY_TRACE, speType.getId()); + if (!speType.getMatcher().matches(element)) { + return false; + } + } + } + + // 2- Filter on the element specializedType + if (strategySpeType != null && elementType != null && !Arrays.asList(elementType.getAllSuperTypes()).contains(strategySpeType)) { + return false; + } + + + // All the previous conditions are met + return true; + } + + + /** + * Go through all the specified strategy's containers + * + * @param element + * The element + * @param strategy + * The strategy + * @return + * If the element's container is a match or not + */ + private boolean filterOnContainer(EObject element, StrategyElement strategy) { + Collection<ElementContainer> strategyContainers = strategy.getElementContainers(); + Boolean skip = true; + + // There were no specified containers hence the condition is always verified + if (strategyContainers == null || strategyContainers.size() < 1) { + return true; + } + + for (ElementContainer container : strategyContainers) { + // Filter on the possible element's container + skip = matchContainers(element.eContainer(), container); + if (skip) { + return true; + } + } + + // All the previous conditions are met + return false; + } + + + /** + * Go through all the specified strategy's container and its containers + * + * @param element + * The element + * @param container + * The {@link org.eclipse.papyrus.propertylifecycle.ElementContainer container} specified in the strategy + * @return + * If the element's container is a match or not + */ + private boolean matchContainers(EObject element, ElementContainer container) { + IElementType containerBaseType = ElementTypeRegistry.getInstance().getType(container.getBaseType()); + IElementType containerSpeType = ElementTypeRegistry.getInstance().getType(container.getSpecializedType()); + + // 1- Filter on the element baseType + if (containerBaseType == null) { + return false; + } + + // If the base type is a metamodel type, there are no matchers to use + if (containerBaseType instanceof ConfiguredHintedMetamodelElementType) { + ConfiguredHintedMetamodelElementType metaType = (ConfiguredHintedMetamodelElementType) containerBaseType; + Activator.log.trace(Activator.PLCSTRATEGY_TYPES_TRACE, "container: " + metaType.getEClass()); + Activator.log.trace(Activator.PLCSTRATEGY_TYPES_TRACE, "container: " + element.eClass()); + + if (!metaType.getEClass().equals(element.eClass())) { + return false; + } + } + // If the base type is a specialization type as the base type, there is a matcher available + if (containerBaseType instanceof ConfiguredHintedSpecializationElementType) { + ConfiguredHintedSpecializationElementType speType = (ConfiguredHintedSpecializationElementType) containerBaseType; + + if (!speType.getMatcher().matches(element)) { + return false; + } + } + + // 2- Filter on the element specializedType + // As there are no way to link an eObject to a specific elementType we only verify that the specialized type is contained by the baseType + if (containerSpeType != null && !Arrays.asList(containerBaseType.getAllSuperTypes()).contains(containerSpeType)) { + return false; + } + + // 3- Filter on the possible element's container + if (container.getContainersContainer() != null) { + if (!matchContainers(element.eContainer(), container.getContainersContainer())) { + return false; + } + } + + + // All the previous conditions are met + return true; + } + + + /** + * The possible changes brought by the current strategies + * + * @param strategies + * The strategies applicable to the element + * @return + * The list containing all the features affected by the applicable strategies + */ + private Set<String> getAllModifiableFeatures(Collection<StrategyElement> strategies) { + Set<String> modifiableFeatures = new HashSet<String>(); + + for (StrategyElement strategy : strategies) { + for (ElementProperty property : strategy.getElementProperties()) { + // The user did not set a label + if (property.getFeatureLabel() == null) { + continue; + } + modifiableFeatures.add(property.getFeatureLabel()); + } + } + + return modifiableFeatures; + } + + + /** + * filter the possible strategies applicable to the features of the element and selecting them by their associated priorities + * + * @param strategies + * The strategies applicable to the element + * @param modifiableFeatures + * The features that can be modified by them + * @return + * The map detailing which changes will be applied to the modifiable features of the element + */ + private HashMap<String, ElementProperty> getNewFeatureValues(Collection<StrategyElement> strategies, Set<String> modifiableFeatures) { + HashMap<String, ElementProperty> newFeatureValues = new HashMap<String, ElementProperty>(); + + for (String featureLabel : modifiableFeatures) { + ElementProperty priorityProperty = filterOnPriority(featureLabel, strategies); + newFeatureValues.put(featureLabel, priorityProperty); + } + + return newFeatureValues; + } + + + /** + * Filter the possible changes based on their priority + * + * @param featureLabel + * The label of the element's feature to change + * @param strategies + * The strategies applicable to the element + * @return + * The selected behavior + */ + private ElementProperty filterOnPriority(String featureLabel, Collection<StrategyElement> strategies) { + HashMap<Integer, ElementProperty> weightedStrategies = new HashMap<Integer, ElementProperty>(); + int priority = 0; + + for (StrategyElement strategy : strategies) { + for (ElementProperty property : strategy.getElementProperties()) { + if (featureLabel.equals(property.getFeatureLabel())) { + // The user did not set a priority + if (property.getPriority() == null) { + weightedStrategies.put(0, property); + continue; + } + + // The user defined this property value to be immutable + if (property.getPriority() < 0) { + Activator.log.trace(Activator.PLCSTRATEGY_TRACE, "Immutable priority: " + property.getPriority()); + return property; + } + + weightedStrategies.put(property.getPriority(), property); + priority = priority < property.getPriority() ? property.getPriority() : priority; + } + } + } + + Activator.log.trace(Activator.PLCSTRATEGY_TRACE, "Highest priority: " + priority); + return weightedStrategies.get(priority); + } + + + /** + * Get the associated {@link org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand} corresponding to the modifications on the element + * + * @param featureLabel + * The label of the feature to edit + * @param featureStrategy + * The strategy applied to this feature + * @return + * The {@link org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand} + * with its associated {@link org.eclipse.gmf.runtime.common.core.command.CommandResult} + */ + private EditElementCommand getAssociatedCommand(String featureLabel, ElementProperty featureStrategy, AbstractEditCommandRequest request) { + return new LifeCycleEditElementCommand("LifecycleEditCommand", element, request, featureLabel, featureStrategy, accessedProcessors); + } + + + /** + * This method calls on the {@link #setAssociatedPropertyValues()} for the contents of the edited element + * It will do so until the maximum depth has been reached (set in the constructor) + * + * @param element + * The edited element + */ + private void applyStrategiesToContents(EObject element) { + // The max depth has been reached + if (depth == 0) { + return; + } + + if (element.eContents().size() > 0) { + // Increase the depth of the matching + depth -= 1; + for (EObject eObject : element.eContents()) { + // Reinitialize the element to test against the current strategies + this.element = eObject; + // TODO find an alternative (more precise) to this default value + this.elementType = ElementTypeRegistry.getInstance().getElementType(eObject.eClass()); + setAssociatedPropertyValues(); + } + } + } + + + /** + * @param elementType + * The element's type + * @return + * The element type ID trimmed of any graphical extension + */ + private String getTrimmedID(IElementType elementType) { + if (elementType == null) { + return null; + } + + if (!graphicalIDMatcher(elementType.getId())) { + // The ID is already not a graphical one + return elementType.getId(); + } + + IElementType[] elementSuperTypes = elementType.getAllSuperTypes(); + LinkedList<IElementType> superTypes = new LinkedList<IElementType>(Arrays.asList(elementSuperTypes)); + for (int i = elementSuperTypes.length - 1; i > 0; i--) { + String typeID = superTypes.get(i).getId(); + Activator.log.trace(Activator.PLCSTRATEGY_TRACE, "typeID: " + typeID); + + if (!graphicalIDMatcher(typeID)) { + return typeID; + } + } + + // A chain of graphical IDs, albeit nigh impossible, could lead to this case + return null; + } + + + /** + * Detect the presence of a graphical extension in the element type ID + * + * @param typeID + * The element type ID + * @return + * isGraphical or not + */ + private boolean graphicalIDMatcher(String typeID) { + if (typeID.matches("[A-Za-z].+_[0-9]+")) { // $NON-NLS-1$ + // The type ID is graphical + return true; + } + + return false; + } + +} |