blob: 848ef6374eca1e80ad4c84d3722ab61e23965485 [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.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;
}
}