blob: 7177903e6bc38b71c160fbf5d4800ab7d832d9d0 [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 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Saadia Dhouib (CEA LIST) saadia.dhouib@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.aas.codegen.ui.handlers;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import org.apache.maven.model.Model;
import org.eclipse.aas.basyx.codegen.util.Project;
import org.eclipse.aas.basyx.codegen.util.submodel.SubModel;
import org.eclipse.aas.basyx.codegen.util.submodel.SubModelCreator;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.project.IProjectConfigurationManager;
import org.eclipse.m2e.core.project.MavenProjectInfo;
import org.eclipse.m2e.core.project.ProjectImportConfiguration;
import org.eclipse.papyrus.aas.Asset;
import org.eclipse.papyrus.aas.AssetAdministrationShell;
import org.eclipse.papyrus.aas.Submodel;
import org.eclipse.papyrus.aas.impl.AssetAdministrationShellImpl;
import org.eclipse.papyrus.uml.diagram.common.handlers.CmdHandler;
import org.eclipse.ui.PlatformUI;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.ParameterDirectionKind;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.util.UMLUtil;
import org.osgi.framework.Bundle;
public class GenerateAASCodeHandler extends CmdHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
updateSelectedEObject();
IRunnableWithProgress op = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) {
monitor.beginTask("Generating Basyx Code...", IProgressMonitor.UNKNOWN);
try {
executeCodeGen(monitor);
} catch (Exception e) {
e.printStackTrace();
}
monitor.done();
}
};
try {
new ProgressMonitorDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()).run(true, true,
op);
MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Success",
"The project " + ((Class) selectedEObject).getName()
+ " has been successfully generated and imported into your workspace");
} catch (InvocationTargetException e) {
e.printStackTrace();
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error",
e.toString());
} catch (InterruptedException e) {
e.printStackTrace();
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error",
e.toString());
} catch (Exception e) {
e.printStackTrace();
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Error",
e.toString());
}
return null;
}
private Object executeCodeGen(IProgressMonitor monitor) {
Class selectedClass = (Class) selectedEObject;
AssetAdministrationShell aas = UMLUtil.getStereotypeApplication(selectedClass, AssetAdministrationShell.class);
if (aas != null) {
URI uri = selectedClass.eResource().getURI();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
if (uri.segmentCount() < 2) {
return null;
}
String projectLocation = uri.segment(1);
try {
projectLocation = URLDecoder.decode(uri.segment(1), "UTF-8");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// System.err.println("projectLocation "+ projectLocation);
IProject modelProject = root.getProject(projectLocation);
if (modelProject.exists()) {
// TODO Auto-generated method stub
// Set project settings
// Create project files
// List of the submodels from papyrus model
List<Submodel> submodels = new ArrayList<>();
// List of submodels for basyx code generator
List<SubModel> basyx_submodels = new ArrayList<>();
// get submodels of the AAS, their operations and their properties
submodels = aas.getSubmodel();
for (int i = 0; i < submodels.size(); i++) {
Submodel submodel = submodels.get(i);
Class submodelClass = submodel.getBase_Class();
if (submodelClass != null) {
String submodelName = submodelClass.getName();
SubModel basyxSubmodel = new SubModel(submodelName);
// add submodel operations
if (submodelClass.getAllOperations() != null && submodelClass.getAllOperations().size() > 0) {
for (int j = 0; j < submodelClass.getAllOperations().size(); j++) {
Operation op = submodelClass.getAllOperations().get(j);
String opName = op.getName();
if (opName != null && opName.length() > 0) {
basyxSubmodel.addOperation(opName);
basyxSubmodel.addInputVariables(opName,
getOperationParameters(op, ParameterDirectionKind.IN));
basyxSubmodel.addOutputVariables(opName,
getOperationParameters(op, ParameterDirectionKind.OUT));
basyxSubmodel.addInOutputVariables(opName,
getOperationParameters(op, ParameterDirectionKind.INOUT));
} else {
basyxSubmodel.addOperation("op" + j);
}
}
}
// add submodel properties
if (submodelClass.getAllAttributes() != null && submodelClass.getAllAttributes().size() > 0) {
for (int j = 0; j < submodelClass.getAllAttributes().size(); j++) {
Property submodelElement = submodelClass.getAllAttributes().get(j);
String attName = submodelElement.getName();
// Generate a submodel property if there is no stereotype applied on the
// property
if ((submodelElement.getAppliedStereotypes() == null)
|| (submodelElement.getAppliedStereotypes().size() == 0)) {
if (submodelElement.getDefaultValue() != null) {
String attValue = submodelElement.getDefaultValue().stringValue();
if (attName != null && attName.length() > 0 && attValue != null
&& attValue.length() > 0) {
basyxSubmodel.addProperty(attName, attValue);
}
} else if (attName != null && attName.length() > 0) {
basyxSubmodel.addProperty(attName);
} else {
basyxSubmodel.addProperty("attribute" + j);
}
} else {
// aad submodel element collection
generateSubmodelElementCollection(submodelElement, basyxSubmodel);
// add submodel property
generateProperty(submodelElement, basyxSubmodel, j);
generateFile(submodelElement, basyxSubmodel);
}
}
}
basyx_submodels.add(basyxSubmodel);
}
}
SubModelCreator mc = new SubModelCreator();
// Add submodels
for (int i = 0; i < basyx_submodels.size(); i++) {
mc.addSubModel(basyx_submodels.get(i));
}
// get parameters for project creation
// aas url
String aasUrl = "";
if (((AssetAdministrationShellImpl) aas).getUrl() != null) {
aasUrl = ((AssetAdministrationShellImpl) aas).getUrl();
} else {
aasUrl = "localhost";
}
// aas port
String aasPort = "";
if (((AssetAdministrationShellImpl) aas).getPort() > 0) {
aasPort = Integer.toString(((AssetAdministrationShellImpl) aas).getPort());
} else {
aasPort = "5125";
}
// aas id
String aasId = "urn:de.basyfloor:devices:DeviceAAS:1.0:1:floordevice#001";
if (((AssetAdministrationShellImpl) aas).getIdentification() != null
&& ((AssetAdministrationShellImpl) aas).getIdentification().getId() != null) {
aasId = ((AssetAdministrationShellImpl) aas).getIdentification().getId();
}
// asset address
String deviceEndpoint = "opc.tcp://192.168.0.37:4840";
if (((AssetAdministrationShellImpl) aas).getAsset() != null) {
Asset asset = ((AssetAdministrationShellImpl) aas).getAsset();
if (asset.getEndpoint() != null && asset.getEndpoint().size() > 0) {
if (asset.getEndpoint().get(0) != null) {
if (asset.getEndpoint().get(0).getAddress() != null) {
deviceEndpoint = asset.getEndpoint().get(0).getAddress().toString();
}
}
}
}
// Create project files
// Project aasproject = new
// Project("urn:de.basyfloor:devices:DeviceAAS:1.0:1:floordevice#001",
// aasUrl, aasPort, mc, "opc.tcp://192.168.0.37:4840");
Project aasproject = new Project(aasId, aasUrl, aasPort, mc, deviceEndpoint);
// Currently only OPC-UA connection with the devices are possible
// If below is commented out, it creates project files in the working folder.
aasproject.setProjectName(selectedClass.getName()); // The asset name as well as the project name
aasproject.setNamespaceFromProjectName(); // Creates project structure in Eclipse automatically based on
// project name
// testAAS.setNamespace("eu.dfki.canvaas.project"); // Instead, it is possible
// to use explicit namespacing.
aasproject.setProjectFolder(root.getLocation().toString() + "/" + selectedClass.getName() + "/");
Bundle bundle = Platform.getBundle("org.eclipse.aas.basyx.codegen");
if (bundle != null) {
final URL extLibEclipseURL = FileLocator.find(bundle, new Path("/extClasses"), null);
String extLibURL = null;
try {
URL fileURL = FileLocator.toFileURL(extLibEclipseURL);
if (fileURL != null) {
extLibURL = fileURL.toString();
if (extLibURL != null)
{
extLibURL = extLibURL.replaceAll("file:/", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.err.println("CanvAAS full path : " + extLibURL);
aasproject.setExternalClassFolder("/" + extLibURL);
}
aasproject.linkAAS(aasproject);
// Create the runnable project
aasproject.createProject();
// Import and open the project in the workspace
IProjectDescription description;
try {
description = ResourcesPlugin.getWorkspace().loadProjectDescription(
new Path(root.getLocation().toString() + "/" + selectedClass.getName() + "/.project"));
File pomFile = new File(ResourcesPlugin.getWorkspace().getRoot().getLocation().toString() + "/"
+ selectedClass.getName() + "/pom.xml");
importMavenProjects(monitor, pomFile, description.getName(), "aas", "aasmodule", "0.1");
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
private LinkedHashMap<String,String> getOperationParameters(Operation op, int direction) {
LinkedHashMap<String, String> inParamaters = new LinkedHashMap<String, String>();
if (op.getOwnedParameters() != null) {
for (int i = 0; i < op.getOwnedParameters().size(); i++) {
if (op.getOwnedParameters().get(i) != null && op.getOwnedParameters().get(i).getName()!=null) {
System.err.println("searched direction: " + direction);
System.err.println(op.getOwnedParameters().get(i).getName() + " direction: "
+ op.getOwnedParameters().get(i).getDirection());
if (op.getOwnedParameters().get(i).getDirection().getValue() == direction) {
String paramType="String";
System.err.println("found parameter for direction " + direction + "\n");
if(op.getOwnedParameters().get(i).getType()!=null && op.getOwnedParameters().get(i).getType().getName()!=null )
{
paramType=op.getOwnedParameters().get(i).getType().getName();
}
inParamaters.put(op.getOwnedParameters().get(i).getName(),paramType);
}
}
}
}
return inParamaters;
}
private void importMavenProjects(IProgressMonitor monitor, File pomFile, String projectName, String groupId,
String artifactId, String version) throws CoreException {
IProjectConfigurationManager manager = MavenPlugin.getProjectConfigurationManager();
ProjectImportConfiguration config = new ProjectImportConfiguration();
Collection<MavenProjectInfo> infos = new ArrayList<>();
Model model = new Model();
model.setGroupId(groupId);
model.setArtifactId(artifactId);
model.setVersion(version);
model.setPomFile(pomFile);
MavenProjectInfo info = new MavenProjectInfo(projectName, pomFile, model, null);
infos.add(info);
manager.importProjects(infos, config, monitor);
}
private void generateSubmodelElementCollection(Property submodelElement, SubModel basyxSubmodel) {
if (org.eclipse.papyrus.uml.tools.utils.UMLUtil.getAppliedStereotype(submodelElement,
"AAS::SubmodelElementCollection", true) != null) {
basyxSubmodel.addSubModelElementCollection(submodelElement.getName());
if ((submodelElement.getType() != null) && (submodelElement.getType() instanceof Class)) {
Class collection = (Class) submodelElement.getType();
// generate attributes of the submodelelementcollection
for (Property collectionchild : collection.getAllAttributes()) {
// case of addSubModelElementCollection subelement is a Property
if (org.eclipse.papyrus.uml.tools.utils.UMLUtil.getAppliedStereotype(collectionchild,
"AAS::Property", true) != null) {
basyxSubmodel.addPropertyToSubModelElementCollection(collectionchild.getName(),
submodelElement.getName());
}
// case of addSubModelElementCollection subelement is a File
Stereotype stFile = org.eclipse.papyrus.uml.tools.utils.UMLUtil
.getAppliedStereotype(collectionchild, "AAS::File", true);
if (stFile != null) {
Object valueObject = collectionchild.getValue(stFile, "path");
if (valueObject != null) {
basyxSubmodel.addFilePath(valueObject.toString(), submodelElement.getName());
} else {
basyxSubmodel.addFilePath(collectionchild.getName(), submodelElement.getName());
}
}
// case of addSubModelElementCollection subelement is a
// SubModelElementCollection
Stereotype stCollection = org.eclipse.papyrus.uml.tools.utils.UMLUtil
.getAppliedStereotype(collectionchild, "AAS::SubmodelElementCollection", true);
if (stCollection != null) {
// waiting for the basyx API to support this case
//
}
}
// generate operations of the submodelelementcollection
for (Operation collectionchildop : collection.getAllOperations()) {
if (collectionchildop != null) {
String opName = "op";
if (collectionchildop.getName() != null && collectionchildop.getName().isEmpty() != true) {
opName = collectionchildop.getName();
}
basyxSubmodel.addOperationToSubModelElementCollection(opName, submodelElement.getName());
basyxSubmodel.addInputVariables(opName,
getOperationParameters(collectionchildop, ParameterDirectionKind.IN));
basyxSubmodel.addOutputVariables(opName,
getOperationParameters(collectionchildop, ParameterDirectionKind.OUT));
basyxSubmodel.addInOutputVariables(opName,
getOperationParameters(collectionchildop, ParameterDirectionKind.INOUT));
// basyxSubmodel.addInputVariables(opName, null);
// basyxSubmodel.addOutputVariables(opName, null);
}
}
}
}
}
private void generateProperty(Property submodelElement, SubModel basyxSubmodel, int j) {
// TODO Auto-generated method stub
if (org.eclipse.papyrus.uml.tools.utils.UMLUtil.getAppliedStereotype(submodelElement, "AAS::Property",
true) != null) {
String attName = submodelElement.getName();
if (submodelElement.getDefaultValue() != null) {
String attValue = submodelElement.getDefaultValue().stringValue();
if (attName != null && submodelElement.getType() != null
&& submodelElement.getType().getName() != null) {
if (attValue == null) {
basyxSubmodel.addProperty(attName, "undefined", submodelElement.getType().getName());
} else {
basyxSubmodel.addProperty(attName, attValue, submodelElement.getType().getName());
}
}
if (attName != null && attName.length() > 0 && attValue != null && attValue.length() > 0) {
basyxSubmodel.addProperty(attName, attValue);
}
} else if (attName != null && attName.length() > 0) {
basyxSubmodel.addProperty(attName);
} else {
basyxSubmodel.addProperty("attribute" + j);
}
}
}
private void generateFile(Property submodelElement, SubModel basyxSubmodel) {
// TODO Auto-generated method stub
Stereotype stFile = org.eclipse.papyrus.uml.tools.utils.UMLUtil.getAppliedStereotype(submodelElement,
"AAS::File", true);
if (stFile != null) {
Object valueObject = submodelElement.getValue(stFile, "path");
if (valueObject != null) {
basyxSubmodel.addFilePath(valueObject.toString());
} else {
basyxSubmodel.addFilePath(submodelElement.getName());
}
}
}
}