| /***************************************************************************** |
| * 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.fromfile; |
| |
| import java.io.BufferedReader; |
| import java.io.InputStreamReader; |
| |
| import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; |
| import org.eclipse.cdt.core.model.CoreModel; |
| import org.eclipse.cdt.core.model.ITranslationUnit; |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.transaction.RecordingCommand; |
| import org.eclipse.gmf.runtime.notation.Diagram; |
| import org.eclipse.papyrus.designer.languages.common.base.StringUtils; |
| import org.eclipse.papyrus.designer.languages.cpp.library.CppUriConstants; |
| import org.eclipse.papyrus.infra.core.resource.BadArgumentExcetion; |
| import org.eclipse.papyrus.infra.core.resource.NotFoundException; |
| import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel; |
| import org.eclipse.papyrus.robotics.core.utils.FileExtensions; |
| import org.eclipse.papyrus.robotics.ros2.reverse.Activator; |
| import org.eclipse.papyrus.robotics.ros2.reverse.ReverseConstants; |
| import org.eclipse.papyrus.robotics.ros2.reverse.fromsys.ReverseMessages; |
| import org.eclipse.papyrus.robotics.ros2.reverse.utils.FolderUtils; |
| import org.eclipse.papyrus.robotics.ros2.reverse.utils.ModelTemplate; |
| import org.eclipse.papyrus.robotics.ros2.reverse.utils.ReverseUtils; |
| import org.eclipse.papyrus.uml.tools.utils.PackageUtil; |
| import org.eclipse.uml2.uml.Class; |
| import org.eclipse.uml2.uml.Package; |
| |
| public class ReverseNodeFromSource { |
| |
| private static final String PACKAGE_XML = "package.xml"; //$NON-NLS-1$ |
| private static final String NAME_TAG = "<name>"; //$NON-NLS-1$ |
| private static final String NAME_TAG_END = "</name>"; //$NON-NLS-1$ |
| |
| public static void reverseNode(IFile file, IProgressMonitor monitor) { |
| try { |
| String pkgName = null; |
| IFile packageXML = scanPackageXML(file.getParent()); |
| if (packageXML != null) { |
| BufferedReader results = new BufferedReader(new InputStreamReader(packageXML.getContents())); |
| String line; |
| while ((line = results.readLine()) != null) { |
| line = line.trim(); |
| if (line.startsWith(NAME_TAG)) { |
| pkgName = line.substring(NAME_TAG.length()); |
| int idx = pkgName.indexOf(NAME_TAG_END); |
| if (idx != -1) { |
| pkgName = pkgName.substring(0, idx); |
| } |
| break; |
| } |
| } |
| } |
| // TODO - obtain nodeName from code |
| String name = file.getName(); |
| if (name.endsWith(".cpp")) { |
| name = name.substring(0, name.length() - 4); |
| } |
| |
| monitor.beginTask("reverse component " + name, 3); |
| monitor.subTask("obtain AST"); |
| ITranslationUnit itu = (ITranslationUnit) CoreModel.getDefault().create(file); |
| IASTTranslationUnit ast = itu.getAST(); |
| monitor.worked(1); |
| |
| String fileName = name + FileExtensions.COMPDEF_UML; |
| // pass complete filename (a bit abusing the extension attribute) |
| IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); |
| if (pkgName == null) { |
| IProject project = FolderUtils.obtainProject(fileName); |
| if (project != null) { |
| pkgName = project.getName(); |
| } else { |
| pkgName = name; |
| } |
| } |
| |
| IProject project = root.getProject(pkgName); |
| IProgressMonitor progressMonitor = new NullProgressMonitor(); |
| if (!project.exists()) { |
| project.create(progressMonitor); |
| } |
| if (!project.isOpen()) { |
| project.open(progressMonitor); |
| } |
| |
| IFolder fModels = FolderUtils.createFolderStructure(project); |
| IFolder fComponents = FolderUtils.getComponentFolder(fModels); |
| IFile fCompModel = fComponents.getFile(fileName); |
| |
| if (!fCompModel.exists()) { |
| URI newURI = URI.createURI("platform:/resource/" + pkgName + "/models/components/" + fileName); |
| ModelTemplate mt = new ModelTemplate(newURI, "compdef"); |
| final NotationModel notation = mt.getNotationModel(); |
| |
| final Package pkg = mt.getUMLModel(); |
| // load primitive types |
| PackageUtil.loadPackage(URI.createURI(ReverseMessages.PATHMAP_ROS2_PRIMITIVE_UML), pkg.eResource().getResourceSet()); |
| PackageUtil.loadPackage(CppUriConstants.ANSIC_LIB, pkg.eResource().getResourceSet()); |
| |
| final String nameFinal = name; |
| final String pkgNameFinal = pkgName; |
| RecordingCommand reverseComponent = new RecordingCommand(mt.getDomain()) { |
| @Override |
| protected void doExecute() { |
| pkg.setName(pkgNameFinal); |
| ReverseUtils.setXmlID(pkg); |
| |
| Class clazz = (Class) pkg.getOwnedType(ReverseConstants.MODEL_NAME_UC); |
| clazz.setName(nameFinal); |
| ReverseUtils.setXmlID(clazz); |
| |
| Diagram diagram; |
| try { |
| diagram = notation.getDiagram(ReverseConstants.MODEL_NAME_UC); |
| final String newName = StringUtils.upperCaseFirst(nameFinal) + " diagram"; |
| diagram.setName(newName); |
| } catch (NotFoundException | BadArgumentExcetion e) { |
| e.printStackTrace(); |
| } |
| |
| monitor.subTask("obtain ports"); |
| ReversePortsFromSource.updatePorts(clazz, ast); |
| monitor.worked(1); |
| |
| monitor.subTask("obtain parameters"); |
| ReverseParametersFromSource.updateParameters(clazz, ast); |
| monitor.worked(1); |
| } |
| }; |
| mt.executeCmd(reverseComponent); |
| |
| mt.save(monitor); |
| } |
| } catch (Exception e) { |
| Activator.log.error(e); |
| } |
| } |
| |
| /** |
| * Scan folder for package.xml file |
| * |
| * @param folder |
| * a folder where the seach is started |
| * @return |
| */ |
| public static IFile scanPackageXML(IContainer folder) { |
| IFile candidate = folder.getFile(new Path(PACKAGE_XML)); |
| if (candidate != null && candidate.exists()) { |
| return candidate; |
| } |
| if (folder.getParent() != null) { |
| IFile result = scanPackageXML(folder.getParent()); |
| if (result != null) { |
| return result; |
| } |
| } |
| return null; |
| } |
| } |