| /***************************************************************************** |
| * 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.reverse.utils; |
| |
| import java.io.IOException; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.xmi.XMLResource; |
| import org.eclipse.emf.transaction.RecordingCommand; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.papyrus.designer.languages.common.base.StringConstants; |
| import org.eclipse.papyrus.designer.transformation.base.utils.ModelManagement; |
| import org.eclipse.papyrus.infra.core.resource.ModelSet; |
| import org.eclipse.papyrus.infra.core.services.ExtensionServicesRegistry; |
| import org.eclipse.papyrus.infra.core.services.ServiceException; |
| import org.eclipse.papyrus.infra.core.services.ServicesRegistry; |
| import org.eclipse.papyrus.robotics.core.utils.FileExtensions; |
| import org.eclipse.papyrus.robotics.profile.robotics.commobject.CommunicationObject; |
| import org.eclipse.papyrus.robotics.ros2.reverse.Activator; |
| import org.eclipse.papyrus.uml.diagram.wizards.command.InitFromTemplateCommand; |
| import org.eclipse.papyrus.uml.diagram.wizards.command.NewPapyrusModelCommand; |
| import org.eclipse.papyrus.uml.tools.utils.PackageUtil; |
| import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil; |
| import org.eclipse.uml2.uml.DataType; |
| import org.eclipse.uml2.uml.NamedElement; |
| import org.eclipse.uml2.uml.Package; |
| import org.eclipse.uml2.uml.UMLPackage; |
| |
| public class ReverseUtils { |
| |
| /** |
| * Create a new message package |
| * |
| * @param folder |
| * the folder in which a new model will be created |
| * @param msgPkgName |
| * the ROS2 message package name |
| * @return the root package of the created model |
| */ |
| @SuppressWarnings("nls") |
| public static Package createMsgPackage(IFolder folder, String msgPkgName) { |
| |
| try { |
| ServicesRegistry registry = new ExtensionServicesRegistry(org.eclipse.papyrus.infra.core.Activator.PLUGIN_ID); |
| registry.startServicesByClassKeys(ModelSet.class); |
| |
| ModelSet modelSet = registry.getService(ModelSet.class); |
| |
| TransactionalEditingDomain domain = modelSet.getTransactionalEditingDomain(); |
| |
| URI newURI = getURIfromFolder(folder, msgPkgName); |
| RecordingCommand command = new NewPapyrusModelCommand(modelSet, newURI); |
| domain.getCommandStack().execute(command); |
| |
| InitFromTemplateCommand tp = new InitFromTemplateCommand(modelSet.getTransactionalEditingDomain(), modelSet, |
| "org.eclipse.papyrus.robotics.wizards", |
| "templates/robotics.servicedef.uml", "templates/robotics.servicedef.notation", "templates/robotics.servidedef.di"); |
| domain.getCommandStack().execute(tp); |
| |
| modelSet.save(new NullProgressMonitor()); |
| registry.disposeRegistry(); |
| |
| Resource r = ModelManagement.getResourceSet().getResource(newURI, true); |
| Package pkg = (Package) r.getContents().get(0); |
| pkg.setName(msgPkgName); |
| setXmlID(pkg); |
| return pkg; |
| } catch (ServiceException | IOException e) { |
| Activator.log.error(e); |
| } |
| return null; |
| } |
| |
| /* |
| * @param folder |
| * the folder in which a new model will be created |
| * |
| * @param msgPkgName |
| * the ROS2 message package name |
| * |
| * @return the URI the model representing a message package within a folder |
| */ |
| public static URI getURIfromFolder(IFolder folder, String msgPkgName) { |
| String path = folder.getProjectRelativePath() + StringConstants.SLASH + msgPkgName + FileExtensions.SERVICEDEF_UML; |
| return URI.createPlatformResourceURI(folder.getProject().getName() + StringConstants.SLASH + path, true); |
| } |
| |
| /* |
| * @param pkg a UML2 package |
| * |
| * @param nestedName the name of a sub-package |
| * |
| * @return the created (or obtained) sub-package within the passed package |
| */ |
| public static Package getOrCreatePackage(Package pkg, String nestedName) { |
| Package nested = pkg.getNestedPackage(nestedName); |
| if (nested == null) { |
| nested = pkg.createNestedPackage(nestedName); |
| setXmlID(nested); |
| } |
| return nested; |
| } |
| |
| /** |
| * Does the given service package already exist? |
| * |
| * @param folder |
| * the folder in which a new model will be created |
| * @param pathMapURIs |
| * a list of pathMapURIs to scan |
| * @param msgPkgName |
| * the ROS2 message package name |
| * @return true, if existing |
| */ |
| public static boolean existsAlready(IFolder folder, List<URI> pathMapURIs, String msgPkgName) { |
| String fileName = fileName(msgPkgName); |
| IFile file = folder.getFile(fileName); |
| if (file != null && file.exists()) { |
| return true; |
| } |
| // now check whether a file with the right name is accessible via a service definition |
| for (URI pathURI : pathMapURIs) { |
| if (pathURI.toString().endsWith(fileName)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Load a message package into the MM resourceSet. |
| * |
| * @param folder |
| * the folder in which a new model will be created |
| * @param pathMapURIs |
| * a list of pathMapURIs to scan |
| * @param msgPkgName |
| * the ROS2 message package name |
| * @return true, if successful |
| */ |
| public static boolean loadMessagePackage(IFolder folder, List<URI> pathMapURIs, String msgPkgName) { |
| String fileName = fileName(msgPkgName); |
| IFile file = folder.getFile(fileName); |
| if (file != null && file.exists()) { |
| URI uri = getURIfromFolder(folder, msgPkgName); |
| return ModelManagement.getResourceSet().getResource(uri, true) != null; |
| } |
| // now check whether a file with the right name is accessible via a service definition |
| for (URI pathURI : pathMapURIs) { |
| if (pathURI.toString().endsWith(fileName)) { |
| return ModelManagement.getResourceSet().getResource(pathURI, true) != null; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Return the file name of the model representing a message package |
| * |
| * @param msgPkgName |
| * the ROS2 message package name |
| * @return the file name |
| */ |
| public static String fileName(String msgPkgName) { |
| return msgPkgName + FileExtensions.SERVICEDEF_UML; |
| } |
| |
| /** |
| * get or create a communication object |
| * |
| * @param pkg |
| * a UML package in which to search a communication object |
| * @param commObjects |
| * a list of communication objects. The new or obtained |
| * communication object will be added to the list |
| * @param name |
| * the name the communication object to get or create |
| * @return true, if the communication object existed already. |
| */ |
| public static boolean getOrCreateCommObject(Package pkg, List<DataType> commObjects, String name) { |
| DataType commObject = (DataType) pkg.getOwnedType(name); |
| if (commObject == null) { |
| commObject = (DataType) pkg.createOwnedType(name, UMLPackage.eINSTANCE.getDataType()); |
| StereotypeUtil.apply(commObject, CommunicationObject.class); |
| setXmlID(commObject); |
| commObjects.add(commObject); |
| return true; |
| } |
| commObjects.add(commObject); |
| return false; |
| } |
| |
| @SuppressWarnings("nls") |
| /** |
| * Write an XML id based on its name (without the top-level package name) |
| * @param ne |
| */ |
| public static void setXmlID(NamedElement ne) { |
| Package root = PackageUtil.getRootPackage(ne); |
| setXmlID(ne, "ID" + ne.getQualifiedName().replaceFirst(root.getName(), "").replaceAll(NamedElement.SEPARATOR, "_")); |
| } |
| |
| /** |
| * Set the XML ID of an eObject |
| * |
| * @param eObject |
| * @param uniqueID |
| */ |
| public static void setXmlID(EObject eObject, String uniqueID) { |
| Resource eObjectRes = eObject.eResource(); |
| |
| if (eObjectRes instanceof XMLResource) { |
| XMLResource xmlResource = (XMLResource) eObjectRes; |
| xmlResource.setID(eObject, uniqueID); |
| } |
| } |
| } |