blob: 66372b5d628c55db4e033c89ad78e8dfdf893435 [file] [log] [blame]
/*****************************************************************************
* 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();
}
}
}