blob: 3ec6ceb878013df40802ebe5a24f65d86b700207 [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.codegen.common.utils
import java.util.ArrayList
import org.eclipse.core.resources.IProject
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.papyrus.designer.transformation.base.utils.TransformationException
import org.eclipse.papyrus.designer.transformation.core.transformations.TransformationContext
import org.eclipse.papyrus.robotics.core.utils.FileExtensions
import org.eclipse.papyrus.robotics.core.utils.ScanUtils
import org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel
import org.eclipse.papyrus.robotics.profile.robotics.components.SystemComponentArchitectureModel
import org.eclipse.papyrus.robotics.profile.robotics.services.ServiceDefinitionModel
import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil
import org.eclipse.uml2.uml.Class
import org.eclipse.uml2.uml.Package
import org.eclipse.uml2.uml.util.UMLUtil
import org.eclipse.papyrus.uml.tools.utils.PackageUtil
class PackageTools {
/**
* Return the ROS package name. Instead of the UML model name, the name of the project
* hosting the model (lowerCase) is used.
* @param model
* @return The ROS2 package name
*/
def static String pkgName(Package model) {
if (model === null) {
System.err.println("Haeh");
}
if (StereotypeUtil.isApplied(model, ServiceDefinitionModel)) {
return model.name.toLowerCase
}
else {
// in case of an external components, use model name in order to enable multiple
// packages in a single Eclipse project
val compDefModel = UMLUtil.getStereotypeApplication(model, ComponentDefinitionModel)
if (compDefModel !== null && compDefModel.isExternal) {
return model.name.toLowerCase
}
return model.projectName.toLowerCase
}
}
/**
* Check whether a given srcCompRes has already been copied into the target
* model. If yes, it returns the component found in there.
* Otherwise, it returns a copy of the component found in the src-model
* resource (the resource is not transformed)
*/
def static findOrCopyCompDef(Resource srcCompRes) {
var compDef = ScanUtils.getCompFromResource(srcCompRes)
if (compDef !== null) {
val mmList = new ArrayList(TransformationContext.current.copier.additionalRootPkgs)
mmList.add(TransformationContext.current.mm)
for (pkg : mmList) {
if (StereotypeUtil.isApplied(pkg.model, ComponentDefinitionModel)) {
val compDefCandidate = ScanUtils.getCompFromResource(pkg.model.eResource)
if (compDefCandidate !== null && compDefCandidate.name == compDef.name) {
return compDefCandidate
}
}
}
// not found in additional model list, return copy
return TransformationContext.current.copier.getCopy(compDef)
}
return null
}
/**
* Check whether a given srcSystemRes has already been copied into the target
* model. If yes, it returns the system found in there.
* Otherwise, it returns a copy of the system found in the src-model
* resource (the resource is not transformed)
*/
def static findOrCopySystem(Resource srcSystemRes) {
var system = ScanUtils.getSystemFromResource(srcSystemRes)
if (system !== null) {
val mmList = new ArrayList(TransformationContext.current.copier.additionalRootPkgs)
mmList.add(TransformationContext.current.mm)
for (pkg : mmList) {
if (StereotypeUtil.isApplied(pkg.model, SystemComponentArchitectureModel)) {
val systemCandidate = ScanUtils.getSystemFromResource(pkg.model.eResource)
if (systemCandidate !== null && systemCandidate.name == system.name) {
return systemCandidate
}
}
}
// not found in additional model list, return copy
return TransformationContext.current.copier.getCopy(system)
}
return null
}
/**
* return a list of component definitions that are defined in a project.
* If code generation is launched from a component within a package, the
* resource set will likely not have the complete set of models defined in
* that package as these are needed to generate the complete set.
* Note that the different components are typically defined in multiple models, but these models
* must be stored in a common location (Eclipse project) aligned with RobMoSys naming conventions
* @param project an Eclipse project hosting models.
*/
def static getCompDefs(IProject project) {
val compDefsURIs = new ArrayList<URI>()
val compDefs = new ArrayList<Class>()
ScanUtils.processContainer(project, FileExtensions.COMPDEF_UML, compDefsURIs)
val srcRS = TransformationContext.current.copier.source.eResource.resourceSet
for (compDefURI : compDefsURIs) {
val srcCompRes = srcRS.getResource(compDefURI, true)
val compDef = findOrCopyCompDef(srcCompRes);
if (compDef !== null) {
val root = PackageUtil.getRootPackage(compDef);
val cdm = UMLUtil.getStereotypeApplication(root, ComponentDefinitionModel)
if (cdm !== null && !cdm.isExternal) {
compDefs.add(compDef)
}
}
}
return compDefs
}
/**
* return a list of component definitions that are defined in a project.
* Note that the different components are typically defined in multiple models, but these models
* must be stored in a common location (Eclipse project) aligned with RobMoSys naming conventions
* @param project an Eclipse project hosting models.
*/
def static getSystem(IProject project) {
val systemURIs = new ArrayList<URI>()
ScanUtils.processContainer(project, FileExtensions.SYSTEM_UML, systemURIs)
val srcRS = TransformationContext.current.copier.source.eResource.resourceSet
if (systemURIs.iterator.hasNext) {
val systemURI = systemURIs.iterator.next
val srcSystemRes = srcRS.getResource(systemURI, true);
return findOrCopySystem(srcSystemRes)
}
return null
}
/**
* Get the project from an existing model
* @param pkg an element of a model
*/
def static getProjectName(Package pkg) {
if (pkg.eResource === null) {
throw new TransformationException("Package " + pkg.name + " is not in a resource - proxy?");
}
val uri = pkg.eResource.URI;
if (uri.isPlatformResource || uri.isPlatformPlugin) {
if (uri.segments().size() > 5) {
// model is part of an example plugin that contains more than one example
// in separate folders (below the models sub-folder), e.g.
// .../models/<example-name>/models/components/<compName>.compdef.uml
// In this case, the example name corresponds to the project name
return uri.segment(3)
}
// segment(0) = plugin or resource, segment(1) = project name
return URI.decode(uri.segment(1))
}
// pathmap case, project is first entry
return URI.decode(uri.segment(0))
}
}