| /***************************************************************************** |
| * Copyright (c) 2020 CEA LIST. |
| * |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * Contributors: |
| * Ansgar Radermacher ansgar.radermacher@cea.fr |
| * |
| *****************************************************************************/ |
| |
| package org.eclipse.papyrus.robotics.ros2.codegen.common.component |
| |
| import java.util.ArrayList |
| import org.eclipse.emf.ecore.util.EcoreUtil |
| import org.eclipse.papyrus.robotics.core.utils.PortUtils |
| import org.eclipse.papyrus.robotics.profile.robotics.components.Activity |
| import org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinition |
| import org.eclipse.papyrus.robotics.profile.robotics.functions.Function |
| import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil |
| import org.eclipse.uml2.uml.Behavior |
| import org.eclipse.uml2.uml.Class |
| import org.eclipse.uml2.uml.OpaqueBehavior |
| import org.eclipse.uml2.uml.util.UMLUtil |
| |
| import static extension org.eclipse.papyrus.robotics.core.utils.InteractionUtils.* |
| |
| class ComponentTransformationUtils { |
| |
| /** |
| * Move functions in passed activity to component (node) level |
| */ |
| def static liftFunctions(Class component) { |
| val cd = UMLUtil.getStereotypeApplication(component, ComponentDefinition) |
| for (activity : cd.activities) { |
| activity.liftFunctions(component) |
| } |
| } |
| |
| /** |
| * Remove activities from node |
| */ |
| def static removeActivities(Class component) { |
| val cd = UMLUtil.getStereotypeApplication(component, ComponentDefinition) |
| for (activity : cd.activities.clone) { |
| // remove activity and associated attribute |
| component.getAttribute(null, activity.base_Class).destroy |
| activity.base_Class.destroy |
| } |
| } |
| |
| /** |
| * The service definition is used as parameter type for the callback parameters with a suitable ptr |
| * declaration that sub-selects one of the contained types. In case of a service definition of query |
| * for instance, ROS uses <service def name>::Request::SharedPtr |
| * The C++ code generator follows the template binding of the service definition and includes the |
| * referenced types. Therefore, we need to remove this binding to avoid this code is generated. Adding |
| * a no-code-gen tag to these would not a solution, as the referenced type could actually be used in |
| * another message definition. |
| */ |
| def static removeTemplateSig(Class component) { |
| for(port : PortUtils.getAllPorts(component)) { |
| if (port.serviceDefinition !== null && port.serviceDefinition.templateBinding !== null) { |
| port.serviceDefinition.templateBinding.destroy(); |
| } |
| } |
| } |
| |
| /** |
| * Move functions in passed activity to component level |
| */ |
| def static liftFunctions(Activity activity, Class component) { |
| for (fct : activity.base_Class.attributes) { |
| if (fct.type instanceof Behavior) { |
| val fctType = fct.type as Behavior |
| // moving the component implies losing the stereotype |
| // application, save information before move |
| var fctSt = UMLUtil.getStereotypeApplication(fctType, Function); |
| if (fctSt !== null) { |
| // Use generic code, avoid that it would break if additional properties are added to functions |
| val copy = EcoreUtil.copy(fctSt) as Function |
| component.ownedBehaviors.add(fctType) |
| fctSt = StereotypeUtil.applyApp(fctType, Function); |
| for (feature : fctSt.eClass.EStructuralFeatures) { |
| if (feature.changeable) { |
| fctSt.eSet(feature, copy.eGet(feature)) |
| } |
| } |
| } |
| else { |
| // should not happen, i.e. all activity attributes should be functions |
| component.ownedBehaviors.add(fctType) |
| } |
| val specification = component.createOwnedOperation(fctType.name, null, null) |
| fctType.specification = specification |
| } |
| } |
| } |
| |
| /** |
| * Remove functions that are not referenced by activities (this can happen after |
| * deletion of a function from an activity) |
| */ |
| def static removeUnrefFunctions(Class component) { |
| val cd = UMLUtil.getStereotypeApplication(component, ComponentDefinition) |
| val fctList = new ArrayList<Function>(); |
| |
| for (activity : cd.activities) { |
| fctList.addAll(activity.functions) |
| } |
| for (pe : component.nearestPackage.packagedElements.clone) { |
| if (pe instanceof OpaqueBehavior) { |
| val fct = UMLUtil.getStereotypeApplication(pe, Function) |
| if (fct !== null && !fctList.contains(fct)) { |
| pe.destroy(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Remove the port, as well as its type (component service, |
| * normally a nested classifier) |
| */ |
| def static removePorts(Class component) { |
| for (port : PortUtils.getAllPorts(component)) { |
| port.type.destroy(); |
| port.destroy(); |
| } |
| } |
| } |