| /***************************************************************************** |
| * 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)) |
| } |
| } |