blob: 3dee67ff76ff08f9dfc828b799a5f9eb61a312c1 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2014 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* CEA LIST - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.moka.pscs.utils.handlers;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.papyrus.uml.extensionpoints.profile.IRegisteredProfile;
import org.eclipse.papyrus.uml.extensionpoints.profile.RegisteredProfile;
import org.eclipse.papyrus.uml.extensionpoints.utils.Util;
import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.PlatformUI;
import org.eclipse.uml2.uml.Activity;
import org.eclipse.uml2.uml.ActivityParameterNode;
import org.eclipse.uml2.uml.Behavior;
import org.eclipse.uml2.uml.CallOperationAction;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.CreateObjectAction;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ForkNode;
import org.eclipse.uml2.uml.InputPin;
import org.eclipse.uml2.uml.LiteralInteger;
import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
import org.eclipse.uml2.uml.ObjectFlow;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.OutputPin;
import org.eclipse.uml2.uml.Parameter;
import org.eclipse.uml2.uml.ParameterDirectionKind;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.StartObjectBehaviorAction;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.UMLPackage;
public class Utils {
public static Profile standardProfile;
public static String STANDARD_PROFILE_NAME = "Standard";
/**
* Generates (or retrieve) a factory Activity for the given context Class.
* A factory Activity consists in a CreateObjectAction for the given context Class,
* followed by a CallOperationAction for the default constructor of this class.
*
* @param context
* The class for which a Factory is requested
* @return A factory Activity for the given context Class
*/
public static Activity getFactory(Class context) {
// First try to retrieve the factory
// Retrieval is based on name.
Activity factory = null;
String contextName = context.getName() == null ? "" : context.getName();
for (Iterator<Behavior> i = context.getOwnedBehaviors().iterator(); i.hasNext() && factory == null;) {
Behavior cddFactory = i.next();
String cddName = cddFactory.getName() == null ? "" : cddFactory.getName();
if (cddFactory instanceof Activity && cddName.equals(contextName + "_Factory")) {
factory = (Activity) cddFactory;
}
}
Parameter returnParam = null;
// if the factory does not exist, then creates it, otherwise "cleans" it
if (factory == null) {
factory = (Activity) context.createOwnedBehavior(context.getName() + "_Factory", UMLPackage.eINSTANCE.getActivity());
returnParam = factory.createOwnedParameter("result", context);
returnParam.setDirection(ParameterDirectionKind.RETURN_LITERAL);
returnParam.setLower(1);
returnParam.setUpper(1);
} else {
factory.getNodes().clear();
factory.getEdges().clear();
for (Iterator<Parameter> i = factory.getOwnedParameters().iterator(); i.hasNext() && returnParam == null;) {
Parameter cddReturn = i.next();
if (cddReturn.getDirection() == ParameterDirectionKind.RETURN_LITERAL) {
returnParam = cddReturn;
}
}
if (returnParam == null) {
returnParam = factory.createOwnedParameter("result", context);
returnParam.setDirection(ParameterDirectionKind.RETURN_LITERAL);
}
}
ActivityParameterNode returnParamNode = (ActivityParameterNode) factory.createOwnedNode("resultParameterNode", UMLPackage.eINSTANCE.getActivityParameterNode());
returnParamNode.setParameter(returnParam);
returnParamNode.setType(context);
LiteralInteger returnParamNodeUpperBound = UMLFactory.eINSTANCE.createLiteralInteger();
returnParamNodeUpperBound.setValue(1);
returnParamNode.setUpperBound(returnParamNodeUpperBound);
// Retrieves the default constructor of context
Operation defaultConstructor = getDefaultConstructor(context);
CreateObjectAction createObject = (CreateObjectAction) factory.createOwnedNode("createObject", UMLPackage.eINSTANCE.getCreateObjectAction());
OutputPin createObjectResultPin = createObject.createResult("result", context);
createObjectResultPin.setLower(1);
createObjectResultPin.setUpper(1);
LiteralUnlimitedNatural createObjectResultPinUpperBound = UMLFactory.eINSTANCE.createLiteralUnlimitedNatural();
createObjectResultPinUpperBound.setValue(1);
createObjectResultPin.setUpperBound(createObjectResultPinUpperBound);
createObject.setClassifier(context);
CallOperationAction callConstructor = (CallOperationAction) factory.createOwnedNode("callConstructor", UMLPackage.eINSTANCE.getCallOperationAction());
callConstructor.setOperation(defaultConstructor);
InputPin callConstructorTargetPin = callConstructor.createTarget("target", context);
callConstructorTargetPin.setLower(1);
callConstructorTargetPin.setUpper(1);
LiteralInteger callConstructorTargetPinUpperBound = UMLFactory.eINSTANCE.createLiteralInteger();
callConstructorTargetPinUpperBound.setValue(1);
callConstructorTargetPin.setUpperBound(callConstructorTargetPinUpperBound);
OutputPin callConstructorResultPin = callConstructor.createResult("result", context);
callConstructorResultPin.setLower(1);
callConstructorResultPin.setUpper(1);
LiteralInteger callConstructorResultPinUpperBound = UMLFactory.eINSTANCE.createLiteralInteger();
callConstructorResultPinUpperBound.setValue(1);
callConstructorResultPin.setUpperBound(callConstructorResultPinUpperBound);
ObjectFlow createObjectAction_callConstructor = (ObjectFlow) factory.createEdge("createObjectAction to callConstructor", UMLPackage.eINSTANCE.getObjectFlow());
createObjectAction_callConstructor.setSource(createObjectResultPin);
createObjectAction_callConstructor.setTarget(callConstructorTargetPin);
ObjectFlow toReturnParamNode = (ObjectFlow) factory.createEdge("callConstructor to returnParamNode", UMLPackage.eINSTANCE.getObjectFlow());
toReturnParamNode.setTarget(returnParamNode);
if (!context.isActive()) {
toReturnParamNode.setSource(callConstructorResultPin);
} else {
StartObjectBehaviorAction startBehavior = (StartObjectBehaviorAction) factory.createOwnedNode("start classifier behavior", UMLPackage.eINSTANCE.getStartObjectBehaviorAction());
startBehavior.setIsSynchronous(false);
InputPin startBehaviorInputPin = startBehavior.createObject("object", context);
startBehaviorInputPin.setLower(1);
startBehaviorInputPin.setUpper(1);
LiteralInteger startBehaviorInputPinUpperBound = UMLFactory.eINSTANCE.createLiteralInteger();
startBehaviorInputPinUpperBound.setValue(1);
startBehaviorInputPin.setUpperBound(startBehaviorInputPinUpperBound);
/*
* // 439321: [Moka] The factory generator of oepm.composite.utils is invalid in the case of an Active class
* // https://bugs.eclipse.org/bugs/show_bug.cgi?id=439321
* //OutputPin startBehaviorResultPin = startBehavior.createResult("result", context);
* //LiteralInteger startBehaviorResultPinUpperBound = UMLFactory.eINSTANCE.createLiteralInteger();
* //startBehaviorResultPinUpperBound.setValue(1) ;
* //startBehaviorResultPin.setUpperBound(startBehaviorResultPinUpperBound) ;
* //toReturnParamNode.setSource(startBehaviorResultPin);
*/
ForkNode fork = (ForkNode) factory.createOwnedNode("forkInstanciatedObject", UMLPackage.eINSTANCE.getForkNode());
toReturnParamNode.setSource(fork);
ObjectFlow forkToStartBehaviorInputPin = (ObjectFlow) factory.createEdge("fork to startbehavior input pin", UMLPackage.eINSTANCE.getObjectFlow());
forkToStartBehaviorInputPin.setSource(fork);
forkToStartBehaviorInputPin.setTarget(startBehaviorInputPin);
//
ObjectFlow callConstructor_startBehavior = (ObjectFlow) factory.createEdge("callConstructor to startBehavior", UMLPackage.eINSTANCE.getObjectFlow());
callConstructor_startBehavior.setSource(callConstructorResultPin);
callConstructor_startBehavior.setTarget(fork);
}
return factory;
}
/**
* Returns the default constructor of the given UML Class context.
* If the default constructor does not exist, it is the generated, with side effects
* on the given context Class (i.e., the generated constructor is added to the list of
* operations of the given context Class.
* A default constructor for a given context Class is a UML Operation with:
* - constructor.name == context.name
* - a single parameter p such that: p.direction == Return and p.type = context
*
* @param context
* A UML Class
* @return the default constructor Operation for the given context Class
*/
public static Operation getDefaultConstructor(Class context) {
// Returns the default constructor if it exists.
// Creates it otherwise.
Operation createdOp = null;
// Find operation with "Create" Stereotype
for (int i = 0; i < context.getOwnedOperations().size() && createdOp == null; i++) {
Operation cddOperation = context.getOwnedOperations().get(i);
for (int j = 0; j < cddOperation.getAppliedStereotypes().size(); j++) {
Stereotype createStereotype = cddOperation.getAppliedStereotypes().get(j);
if (createStereotype.getName().equals("Create")) {
if (cddOperation.getName().equals(context.getName())) {
if (cddOperation.getOwnedParameters().size() == 1) {
Parameter returnParameter = cddOperation.getOwnedParameters().get(0);
if (returnParameter.getDirection().equals(ParameterDirectionKind.RETURN_LITERAL)) {
if (returnParameter.getType().getName().equals(context.getName())) {
createdOp = cddOperation;
}
}
}
}
}
}
}
// No operation with "Create" Stereotype found : => Creation of the operation.
if (createdOp == null) {
Stereotype appliedStereotype = null;
if (!isStandardProfileApplied(context)) {
PackageUtil.applyProfile(context.getModel(), standardProfile, true);
}
createdOp = UMLFactory.eINSTANCE.createOperation();
context.getOwnedOperations().add(createdOp);
for (int j = 0; j < createdOp.getApplicableStereotypes().size() && appliedStereotype == null; j++) {
Stereotype cddStereotype = createdOp.getApplicableStereotypes().get(j);
if (cddStereotype.getName().equals("Create")) {
appliedStereotype = cddStereotype;
}
}
Parameter result = UMLFactory.eINSTANCE.createParameter();
result.setDirection(ParameterDirectionKind.RETURN_LITERAL);
result.setType(context);
result.setName("return");
result.setLower(1);
result.setUpper(1);
createdOp.setName(context.getName());
createdOp.getOwnedParameters().add(result);
createdOp.applyStereotype(appliedStereotype);
}
return createdOp;
}
/**
* Returns the method activity for the context operation.
* If the method does not exist, it is the generated, with side effects
* on the given context Class (i.e., the generated method is added to the list of
* of owned behaviors the given context Class.)
* The generated method signature matches the signature of the operation
*
* @param context
* A UML Class
* @param operation
* A UML operation
* @return the method Activity of the given Operation for the given context Class
*/
public static Activity getMethod(Class context, Operation operation) {
Activity method = null ;
if (operation.getMethods().isEmpty()) {
method = (Activity)context.createOwnedBehavior(operation.getName() + "Impl", UMLPackage.eINSTANCE.getActivity()) ;
method.setSpecification(operation);
for (Parameter p : operation.getOwnedParameters()) {
Parameter pAct = method.createOwnedParameter(p.getName(), p.getType()) ;
pAct.setDirection(p.getDirection());
pAct.setLower(p.getLower());
pAct.setUpper(p.getUpper());
}
}
else {
for(Iterator<Behavior> i = operation.getMethods().iterator() ; i.hasNext() && method==null ; ) {
Behavior b = i.next() ;
if (b instanceof Activity) {
method = (Activity)b ;
}
}
}
return method ;
}
/**
* Returns true if the Standard profile is applied on the Model containing the given element
*
* @param element
* A UML model element
* @return true if the Standard profile is applied on the Model containing the given element
*/
public static boolean isStandardProfileApplied(Element element) {
if (standardProfile == null) {
IRegisteredProfile registeredProfile = RegisteredProfile.getRegisteredProfile(STANDARD_PROFILE_NAME);
URI modelUri = registeredProfile.getUri();
Resource modelResource = Util.createTemporaryResourceSet().getResource(modelUri, true);
if (modelResource.getContents().get(0) instanceof Profile) {
standardProfile = (Profile) modelResource.getContents().get(0);
}
}
List<Profile> appliedProfiles = element.getModel().getAppliedProfiles();
return appliedProfiles.contains(standardProfile);
}
/**
* Duplicated from SequoiaAbstractHandler. @author Patrick Tessier (CEA).
* getSelected element in the diagram or in hte model explorer
*
* @return Element or null
*/
public static Element getSelection() {
Element selectedElement = null;
ISelectionService selectionService = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService();
ISelection selection = selectionService.getSelection();
if (selection instanceof IStructuredSelection) {
Object selectedobject = ((IStructuredSelection) selection).getFirstElement();
if (selectedobject instanceof GraphicalEditPart) {
Object graphicalElement = ((GraphicalEditPart) selectedobject).getModel();
if ((graphicalElement instanceof View) && ((View) graphicalElement).getElement() instanceof org.eclipse.uml2.uml.Element) {
selectedElement = (org.eclipse.uml2.uml.Element) ((View) graphicalElement).getElement();
}
} else if (selectedobject instanceof IAdaptable) {
EObject selectedEObject = (EObject) ((IAdaptable) selectedobject).getAdapter(EObject.class);
if (selectedEObject instanceof org.eclipse.uml2.uml.Element) {
selectedElement = (Element) selectedEObject;
}
}
return selectedElement;
}
return null;
}
}