blob: 7c6a66485013c02b95afdb3f04b678d989231903 [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.cpp.component
import java.util.ArrayList
import org.eclipse.core.resources.IProject
import org.eclipse.papyrus.designer.languages.common.profile.Codegen.TemplateBinding
import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Include
import org.eclipse.papyrus.designer.transformation.base.utils.TransformationException
import org.eclipse.papyrus.designer.transformation.core.transformations.ExecuteTransformationChain
import org.eclipse.papyrus.designer.transformation.core.transformations.TransformationContext
import org.eclipse.papyrus.designer.languages.common.base.file.IPFileSystemAccess
import org.eclipse.papyrus.robotics.codegen.common.utils.ApplyProfiles
import org.eclipse.papyrus.robotics.core.utils.PortUtils
import org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinition
import org.eclipse.papyrus.robotics.profile.robotics.functions.Function
import org.eclipse.papyrus.robotics.ros2.codegen.common.component.AbstractCompTransformations
import org.eclipse.papyrus.robotics.ros2.codegen.common.message.CreateMsgPackage
import org.eclipse.papyrus.robotics.ros2.codegen.cpp.utils.ProjectTools
import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil
import org.eclipse.uml2.uml.Class
import org.eclipse.uml2.uml.OpaqueBehavior
import org.eclipse.uml2.uml.Property
import org.eclipse.uml2.uml.util.UMLUtil
import static org.eclipse.papyrus.robotics.ros2.codegen.cpp.utils.RosCppTypes.*
import static extension org.eclipse.papyrus.designer.uml.tools.utils.ElementUtils.varName
import static extension org.eclipse.papyrus.robotics.codegen.common.utils.ActivityUtils.*
import static extension org.eclipse.papyrus.robotics.codegen.common.utils.ComponentUtils.isRegistered
import static extension org.eclipse.papyrus.robotics.core.utils.InteractionUtils.*
import static extension org.eclipse.papyrus.robotics.core.utils.ParameterUtils.getAllParameters
import static extension org.eclipse.papyrus.robotics.ros2.codegen.common.component.ComponentTransformationUtils.*
import static extension org.eclipse.papyrus.robotics.ros2.codegen.common.utils.MessageUtils.*
import static extension org.eclipse.papyrus.robotics.ros2.codegen.common.utils.RosHelpers.*
import static extension org.eclipse.papyrus.robotics.ros2.codegen.cpp.component.Constructor.createConstructor
import static extension org.eclipse.papyrus.robotics.ros2.codegen.cpp.component.CreateMain.createMain
import static extension org.eclipse.papyrus.robotics.ros2.codegen.cpp.component.CreateMain.registerComponent
import static extension org.eclipse.papyrus.robotics.ros2.codegen.cpp.component.ParameterTransformations.declareParameters
import static extension org.eclipse.papyrus.robotics.ros2.codegen.cpp.component.ParameterTransformations.initParameters
import static extension org.eclipse.papyrus.robotics.ros2.codegen.cpp.component.ParameterTransformations.moveParameters
class ComponentTransformations extends AbstractCompTransformations {
new(IPFileSystemAccess fileAccess, IProject genProject) {
super(fileAccess, genProject)
}
def static createPubsSubsAttrs(Class component) {
for (port : PortUtils.getAllPorts(component)) {
val cp = port.communicationPattern
if (cp.isPush || cp.isPubSub) {
var Property attribute
if (port.provideds.size() > 0) {
val rosPublisher = getType(port, "ros2Library::rclcpp_lifecycle::LifecyclePublisher")
attribute = component.createOwnedAttribute('''«port.varName»_pub_''', rosPublisher)
} else if (port.requireds.size() > 0) {
val rosSubscriber = getType(port, "ros2Library::rclcpp::Subscription")
attribute = component.createOwnedAttribute('''«port.varName»_sub_''', rosSubscriber)
}
ApplyProfiles.applyCommonProfile(attribute)
val template = StereotypeUtil.applyApp(attribute, TemplateBinding)
template.actuals.add(port.commObject)
attribute.useSharedPtr
}
}
}
def static createSendAttrs(Class component) {
for (port : PortUtils.getAllPorts(component)) {
if (port.communicationPattern.isSend) {
var Property attribute
if (port.provideds.size() > 0) {
val rosSubscriber = getType(port, "ros2Library::rclcpp::Subscription")
attribute = component.createOwnedAttribute('''«port.varName»_recv_''', rosSubscriber)
} else if (port.requireds.size() > 0) {
val rosPublisher = getType(port, "ros2Library::rclcpp_lifecycle::LifecyclePublisher")
attribute = component.createOwnedAttribute('''«port.varName»_send_''', rosPublisher)
}
ApplyProfiles.applyCommonProfile(attribute)
val template = StereotypeUtil.applyApp(attribute, TemplateBinding)
template.actuals.add(port.commObject)
attribute.useSharedPtr
}
}
}
def static createServiceAttrs(Class component) {
for (port : PortUtils.getAllPorts(component)) {
if (port.communicationPattern.isQuery) {
var Property attribute
if (port.provideds.size() > 0) {
val rosService = getType(port, "ros2Library::rclcpp::Service");
attribute = component.createOwnedAttribute('''«port.varName»_srv_''', rosService);
} else if (port.requireds.size() > 0) {
val rosClient = getType(port, "ros2Library::rclcpp::Client");
attribute = component.createOwnedAttribute('''«port.varName»_client_''', rosClient);
}
var template = StereotypeUtil.applyApp(attribute, TemplateBinding)
if (template === null) {
ApplyProfiles.applyCommonProfile(attribute)
template = StereotypeUtil.applyApp(attribute, TemplateBinding)
}
template.actuals.add(port.serviceType)
attribute.useSharedPtr
}
}
}
/**
* Add action attributes
*/
def static createActionAttrs(Class component) {
for (port : PortUtils.getAllPorts(component)) {
if (port.communicationPattern.isAction) {
var Property attribute
if (port.provideds.size() > 0) {
val rosService = getType(port, "ros2Library::rclcpp_action::Server");
attribute = component.createOwnedAttribute('''«port.varName»_actsrv_''', rosService);
} else if (port.requireds.size() > 0) {
val rosClient = getType(port, "ros2Library::rclcpp_action::Client");
attribute = component.createOwnedAttribute('''«port.varName»_actcli_''', rosClient);
}
var template = StereotypeUtil.applyApp(attribute, TemplateBinding)
if (template === null) {
ApplyProfiles.applyCommonProfile(attribute)
template = StereotypeUtil.applyApp(attribute, TemplateBinding)
}
template.actuals.add(port.serviceType)
attribute.useSharedPtr
}
}
}
/**
* 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();
}
}
}
}
override componentTrafo(Class component, CreateMsgPackage msgPkgCreator) {
msgPkgCreator.createMessagesOrServices(component)
if (genProject === null) {
throw new TransformationException(ExecuteTransformationChain.USER_CANCEL);
}
component.liftFunctions
component.createConstructor
var include = StereotypeUtil.applyApp(component, Include);
// TODO: do via external type add rclcpp via external type?
include.header = include.header + "#include <rclcpp/rclcpp.hpp>\n"
if (component.hasActions) {
include.header = include.header + "#include <rclcpp_action/rclcpp_action.hpp>\n"
}
if (component.isRegistered) {
include.body = include.body + component.registerComponent;
}
component.createMain;
if (component.hasExternalCode) {
new Ros2CodeSkeleton().createSkeleton(component);
}
// val stdString = getType(node, "ros2Library::std_msgs::String");
// node.createDependency(stdString)
component.removeActivities
component.createPubsSubsAttrs
component.createSendAttrs
component.createServiceAttrs
component.createActionAttrs
if (component.allParameters.size > 0) {
component.declareParameters
component.initParameters
}
// move parameter needs to be called even if there are not parameters
// as it also removes the nested class holding parameters
component.moveParameters
}
override componentCodegen(Class component, CreateMsgPackage msgPkgCreator) {
val codeGen = new RoboticsCppCreator(genProject, fileAccess, "src-skel/", "src/");
component.removeTemplateSig
component.removePorts
component.removeUnrefFunctions;
TransformationContext.current.project = genProject
// RoboticsTContext.current.getProjet
ProjectTools.genCode(codeGen, component)
}
}