blob: 0f03a535a3a12b196cd51c516411b0e9cad1f4cd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2022 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:
* Florian Pauker (TU Wien) pauker@ift.at
* Thomas Fruhwirth (TU Wien) thomas.fruehwirth@tuwien.ac.at
* Saadia Dhouib (CEA LIST) saadia.dhouib@cea.fr
* Fadwa Tmar (CEA LIST) fadwa.tmar@cea.fr
*******************************************************************************/
package org.eclipse.papyrus.opcua.uml2opcua.qvt;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.m2m.qvt.oml.BasicModelExtent;
import org.eclipse.m2m.qvt.oml.ExecutionContextImpl;
import org.eclipse.m2m.qvt.oml.ModelExtent;
import org.eclipse.m2m.qvt.oml.TransformationExecutor;
import org.eclipse.m2m.qvt.oml.util.StringBufferLog;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.uml2.uml.PackageableElement;
import org.eclipse.uml2.uml.internal.impl.ProfileImpl;
import org.eclipse.papyrus.ocpua.robotics.profile.opcuaroboticsprofile.OPCUARoboticsProfilePackage;
import org.eclipse.papyrus.sysml16.*;
import org.eclipse.papyrus.sysml16.activities.ActivitiesPackage;
import org.eclipse.papyrus.sysml16.allocations.AllocationsPackage;
import org.eclipse.papyrus.sysml16.blocks.BlocksPackage;
import org.eclipse.papyrus.sysml16.constraintblocks.ConstraintBlocksPackage;
import org.eclipse.papyrus.sysml16.deprecatedelements.DeprecatedElementsPackage;
import org.eclipse.papyrus.sysml16.modelelements.ModelElementsPackage;
import org.eclipse.papyrus.sysml16.portsandflows.PortsAndFlowsPackage;
import org.eclipse.papyrus.sysml16.requirements.RequirementsPackage;
import org.eclipse.papyrus.sysml16.sysml.SysMLPackage;
public class Uml2OpcuaTransformer {
/*
* Performs the UML to OPC UA model transformation using a QVTo transformation
* file.
*
* @param umlFilePath Path to the UML XMI file that is used as in input for the
* transformation, e.g. a file created with Papyrus.
*
* @param qvtTransformationFileUri URI identifying the qvto file to be used for
* transformation, e.g. a file created with the QVTo Eclipse Plugin. An internal
* qvto file is used if no qvtoTransformationFileUri is provided.
*
* @param informationOutputStream Can be used to provide an OutputStream to
* write Error Messages, etc. to. System.out is used if no
* informationOutputStream is provided.
*
* @param transformationResults[0] opcuaNodesetOutput the OPC UA model resulting
* from the transformation
*
* @param transformationResults[1] opcuaNodeIdsCsvOutput the NodeIdsCsv model
* resulting from the transformation
*
* @return true if the transformation process if successful, False otherwise.
* Information about problems is provided via the informationOutputStream.
*/
// Obtain a new resource set
ResourceSet resSet = new ResourceSetImpl();
protected ModelExtent roboticsModel, roboticsLibraryModel, diModel, diLibraryModel, uaModel, uaLibraryModel, sysMLModelExtent, sysMLBlocksModelExtent;
//protected BasicModelExtent
protected ModelExtent roboticsProfileExtent;
public boolean transform(URI resourceURI, URI qvtoTransformationFileUri, ModelExtent[] transformationResults,
OutputStream informationOutputStream) {
PrintWriter informationOutputStreamWriter;
if (informationOutputStream != null) {
System.out.println("output stream provided");
informationOutputStreamWriter = new PrintWriter(informationOutputStream);
} else {
System.out.println("No output stream provided, using System.out");
informationOutputStreamWriter = new PrintWriter(System.out);
}
if (resourceURI == null || !(new File(resourceURI.path()).exists())) { // Error: No UML file provided, throw an
// execption
informationOutputStreamWriter.println("No umlFilePath or File does not exist provided: " + resourceURI);
return false;
}
if (qvtoTransformationFileUri == null) { // no QVTo transformation file provided, use the one provided by
// org.eclipse.papyrus.opcua.uml2opcua.qvt.transformation
// Obtain a new resource set
//ResourceSet resSet = new ResourceSetImpl();
Resource roboticsProfileResource = resSet.getResource(URI.createURI("pathmap://Papyrus_OPC_UA_ROBOTICS_PROFILE/OPC_UA_Robotics_CS.profile.uml", true), true);
roboticsProfileExtent = new BasicModelExtent(roboticsProfileResource.getContents());
// register opc ua set metamodel
// Resource setMetamodel =
// resSet.getResource(URI.createURI("platform:/plugin/org.eclipse.papyrus.opcua.uml2opcua.qvt.transformation/metamodels/set.ecore"),
// true);
Resource setMetamodel = resSet.getResource(
URI.createURI(
"platform:/plugin/org.eclipse.papyrus.uml2opcua.qvto.transformation/metamodels/set.ecore"),
true);
EObject eObject = setMetamodel.getContents().get(0);
if (eObject instanceof EPackage) {
EPackage p = (EPackage) eObject;
// rs.getPackageRegistry().put(p.getNsURI(), p);
// System.out.println("p.getNsURI(): " + p.getNsURI() );
EPackage.Registry.INSTANCE.put(p.getNsURI(), p);
}
// register opc ua types metamodel
// TODO: check if this is actually required
Resource typesMetamodel = resSet.getResource(URI.createURI(
"platform:/plugin/org.eclipse.papyrus.uml2opcua.qvto.transformation/metamodels/types.ecore"), true);
EObject eObject2 = typesMetamodel.getContents().get(0);
if (eObject2 instanceof EPackage) {
EPackage p = (EPackage) eObject2;
// rs.getPackageRegistry().put(p.getNsURI(), p);
// System.out.println("p.getNsURI(): " + p.getNsURI() );
EPackage.Registry.INSTANCE.put(p.getNsURI(), p);
}
//register opc ua di set and Type metamodel
setMetamodel = resSet.getResource(
URI.createURI(
"platform:/plugin/org.eclipse.papyrus.uml2opcua.qvto.transformation/metamodels/di/Opc.Ua.di.ecore"),
true);
eObject = setMetamodel.getContents().get(0);
if (eObject instanceof EPackage) {
EPackage p = (EPackage) eObject;
EPackage.Registry.INSTANCE.put(p.getNsURI(), p);
}
setMetamodel = resSet.getResource(
URI.createURI(
"platform:/plugin/org.eclipse.papyrus.uml2opcua.qvto.transformation/metamodels/di/types.ecore"),
true);
eObject = setMetamodel.getContents().get(0);
if (eObject instanceof EPackage) {
EPackage p = (EPackage) eObject;
EPackage.Registry.INSTANCE.put(p.getNsURI(), p);
}
//register opc ua robotics set and type metamodel
setMetamodel = resSet.getResource(
URI.createURI(
"platform:/plugin/org.eclipse.papyrus.uml2opcua.qvto.transformation/metamodels/robotics/Opc.Ua.Robotics.ecore"),
true);
eObject = setMetamodel.getContents().get(0);
if (eObject instanceof EPackage) {
EPackage p = (EPackage) eObject;
EPackage.Registry.INSTANCE.put(p.getNsURI(), p);
}
setMetamodel = resSet.getResource(
URI.createURI(
"platform:/plugin/org.eclipse.papyrus.uml2opcua.qvto.transformation/metamodels/robotics/types1.ecore"),
true);
eObject = setMetamodel.getContents().get(0);
if (eObject instanceof EPackage) {
EPackage p = (EPackage) eObject;
EPackage.Registry.INSTANCE.put(p.getNsURI(), p);
}
// //add OPC UA Robotics profile to the ressource set
// URI RoboticsProfileURI = URI.createURI("pathmap://Papyrus_OPC_UA_ROBOTICS_PROFILE/OPC_UA_Robotics_CS.profile.uml");
// Resource roboticsProfileResouce = resSet.getResource(RoboticsProfileURI,true);
// BasicModelExtent roboticsProfile = new BasicModelExtent(roboticsProfileResouce.getContents());
// EObject roboticsEObject = roboticsProfileResouce.getContents().get(0);
// if (roboticsEObject instanceof ProfileImpl) {
// ProfileImpl roboticsPackage = (ProfileImpl) roboticsEObject;
//
// // System.err.println("roboticsPackage.getDefinition().getNsURI(): " + roboticsPackage.getDefinition().getNsURI() );
// (EPackage.Registry.INSTANCE).put(roboticsPackage.getDefinition().getNsURI(), OPCUARoboticsProfilePackage.eINSTANCE);
// }
// URI SysMLProfileURI = URI.createURI("pathmap://SysML16_PROFILES/SysML.profile.uml");
//
// Resource sysMLProfile = resSet.getResource(SysMLProfileURI, true);
//
// EObject eObjectSysML = EMFHelper.getEObject(sysMLProfile.getContents().get(0));
//
// if (eObjectSysML instanceof ProfileImpl ) {
//
// ProfileImpl epSysML = (ProfileImpl) eObjectSysML;
// System.err.println("p.getNsURI(): " + epSysML.getURI() );
// //EPackage.Registry.INSTANCE.put(epSysML.getDefinition().getNsURI(), SysMLPackage.eINSTANCE);
// EPackage.Registry.INSTANCE.put("http://www.eclipse.org/papyrus/sysml/1.6/SysML",SysMLPackage.eINSTANCE);
//
//// EPackage[] tabEpackage = new EPackage[5];
//
//// for (PackageableElement e : epSysML.getPackagedElements()) {
////
//// if (e instanceof ProfileImpl) {
//// ProfileImpl p = (ProfileImpl) e;
//// // rs.getPackageRegistry().put(p.getNsURI(), p);
////
//// System.err.println("p.getNsURI(): " + p.getDefinition().getNsURI() );
//// EPackage.Registry.INSTANCE.put(p.getDefinition().getNsURI(), p.getDefinition());
////
//// }
//// }
//
// EPackage.Registry.INSTANCE.put("http://www.eclipse.org/papyrus/sysml/1.6/SysML/Activities",ActivitiesPackage.eINSTANCE);
// EPackage.Registry.INSTANCE.put("http://www.eclipse.org/papyrus/sysml/1.6/SysML/Allocations",AllocationsPackage.eINSTANCE);
// EPackage.Registry.INSTANCE.put("http://www.eclipse.org/papyrus/sysml/1.6/SysML/Blocks",BlocksPackage.eINSTANCE);
// EPackage.Registry.INSTANCE.put("http://www.eclipse.org/papyrus/sysml/1.6/SysML/ConstraintBlocks",ConstraintBlocksPackage.eINSTANCE);
// EPackage.Registry.INSTANCE.put("http://www.eclipse.org/papyrus/sysml/1.6/SysML/DeprecatedElements",DeprecatedElementsPackage.eINSTANCE);
// EPackage.Registry.INSTANCE.put("http://www.eclipse.org/papyrus/sysml/1.6/SysML/ModelElements",ModelElementsPackage.eINSTANCE);
// EPackage.Registry.INSTANCE.put("http://www.eclipse.org/papyrus/sysml/1.6/SysML/PortsAndFlows",PortsAndFlowsPackage.eINSTANCE);
// EPackage.Registry.INSTANCE.put("http://www.eclipse.org/papyrus/sysml/1.6/SysML/Requirements",RequirementsPackage.eINSTANCE);
// }
// set uri for qvto transformation file
qvtoTransformationFileUri = URI.createURI(
"platform:/plugin/org.eclipse.papyrus.uml2opcua.qvto.transformation/transforms/Uml2Opcua.qvto");
//"platform:/plugin/org.eclipse.papyrus.uml2opcua.qvto.transformation/transforms/SysML2Opcua.qvto");
}
// QVTo allows to define blackbox libraries
// the following line is not needed if the class is registered as blackbox in
// the plugin.xml file
// TransformationExecutor.BlackboxRegistry.INSTANCE.registerModule(MyBlackbox.class);
TransformationExecutor transformationExecutor = new TransformationExecutor(qvtoTransformationFileUri);
// define the transformation input
ExecutionContextImpl executionContext = new ExecutionContextImpl();
executionContext.setConfigProperty("keepModeling", true);
//Resource umlXmiResource = new XMIResourceImpl(URI.createFileURI(resourceURI));
Resource umlXmiResource = resSet.getResource(resourceURI, true);
try {
umlXmiResource.load(null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//whit this code we cannot
//EList<EObject> eObjects = umlXmiResource.getContents();
//ModelExtent xmlInput = new BasicModelExtent(eObjects);
//new way to import input model
//Resource modelResource = resSet.getResource(URI.createPlatformPluginURI("/org.eclipse.papyrus.teststaticprofile.qvt/test/test_opc_robotics.uml", true), true);
//Resource modelResource = resSet.getResource(URI.createURI("/org.eclipse.papyrus.teststaticprofile.qvt/test/test_opc_robotics.uml", true), true);
Resource modelResource = resSet.getResource(resourceURI, true);
ModelExtent xmlInput = new BasicModelExtent(modelResource.getContents());
if (transformationResults[0] == null) {
transformationResults[0] = new BasicModelExtent();
}
if (transformationResults[1] == null) {
transformationResults[1] = new BasicModelExtent();
}
// ModelExtent modelParameters = new BasicModelExtent();
// transformationDiagnostic = te.execute(executionContext, input, output);
// Diagnostic transformationDiagnostic = te.loadTransformation();
StringBufferLog qvtoLog = new StringBufferLog();
executionContext.setLog(qvtoLog);
// List<ModelExtent> extents = getModelExtents();
// transformation execution
//getInOPCUARoboticsModel adds robotics modelExtent
Diagnostic transformationDiagnostic = transformationExecutor.execute(executionContext,
xmlInput,
roboticsProfileExtent,
transformationResults[0], transformationResults[1]);
informationOutputStreamWriter.println(qvtoLog.getContents());
informationOutputStreamWriter.flush();
if (transformationDiagnostic.getSeverity() != Diagnostic.OK) {
informationOutputStreamWriter
.println("Executing QVT transformation failed with error " + transformationDiagnostic.toString());
informationOutputStreamWriter.flush();
return false;
}
return true;
}
// the transfo parameters :
// protected List<ModelExtent> getModelExtents() {
// List<ModelExtent> allExtents = new LinkedList<ModelExtent>();
// allExtents.add(getInOPCUARoboticsModelExtent());
//
// return allExtents;
// }
private ModelExtent getInOPCUARoboticsModelExtent() {
URI roboticsProfileURI = URI.createURI("pathmap://Papyrus_OPC_UA_ROBOTICS_PROFILE/OPC_UA_Robotics_CS.profile.uml", true);
Resource roboticsProfile = resSet.getResource(roboticsProfileURI, true);
roboticsModel= new BasicModelExtent(roboticsProfile.getContents());
return roboticsModel;
}
private ModelExtent getInOPCUARoboticsLibararyModelExtent() {
URI roboticsLibararyURI = URI.createURI("pathmap://Papyrus_OPC_UA_ROBOTICS_LIBRARY/OPC_UA_Robotics_CS_Library.library.uml", true);
Resource roboticsLibrary = resSet.getResource(roboticsLibararyURI, true);
roboticsLibraryModel= new BasicModelExtent(roboticsLibrary.getContents());
return roboticsLibraryModel;
}
private ModelExtent getInOPCUADIModelExtent() {
URI diProfileURI = URI.createURI("pathmap://Papyrus_OPC_UA_DI_PROFILE/OPC_UA_DI.profile.uml", true);
Resource diProfile = resSet.getResource(diProfileURI, true);
diModel= new BasicModelExtent(diProfile.getContents());
return diModel;
}
private ModelExtent getInOPCUADILibraryModelExtent() {
URI diLibraryURI = URI.createURI("pathmap://Papyrus_OPC_UA_DI_LIBRARY/OPC_UA_DI.library.uml", true);
Resource diLibraryR = resSet.getResource(diLibraryURI, true);
diLibraryModel= new BasicModelExtent(diLibraryR.getContents());
return diLibraryModel;
}
private ModelExtent getInOPCUAModelExtent() {
URI uaProfileURI = URI.createURI("pathmap://Papyrus_OPC_UA_PROFILE/OPC_UA.profile.uml", true);
Resource uaProfile = resSet.getResource(uaProfileURI, true);
uaModel= new BasicModelExtent(uaProfile.getContents());
return uaModel;
}
private ModelExtent getInOPCUALibraryModelExtent() {
URI uaLibraryURI = URI.createURI("pathmap://Papyrus_OPC_UA_LIBRARY/OPC_UA.library.uml", true);
Resource uaLibraryR = resSet.getResource(uaLibraryURI, true);
uaLibraryModel= new BasicModelExtent(uaLibraryR.getContents());
return uaLibraryModel;
}
private ModelExtent getInSysMLModelExtent() {
URI sysMLProfileURI = URI.createURI("pathmap://SysML16_PROFILES/SysML.profile.uml", true);
Resource sysMLProfile = resSet.getResource(sysMLProfileURI, true);
sysMLModelExtent = new BasicModelExtent(sysMLProfile.getContents());
return sysMLModelExtent;
}
private ModelExtent getInSysMLBlocksModelExtent() {
URI sysMLBlocksProfileURI = URI.createURI("http://www.eclipse.org/papyrus/sysml/1.6/SysML/Blocks", true);
Resource sysMLBlocksProfile = resSet.getResource(sysMLBlocksProfileURI, true);
sysMLBlocksModelExtent = new BasicModelExtent(sysMLBlocksProfile.getContents());
return sysMLBlocksModelExtent;
}
/*
* Serializes a OPC UA model to an OPC UA Nodeset xml file.
*
* @param opcUaModel ModelExtent object describing the OPC UA model that shall
* be serialized. Typically the result of a transformation process.
*
* @param opcuaNodesetFilePath Path to the Nodeset file that will be created.
* Must have an "xml" file extension.
*
* @param informationOutputStream Can be used to provide an OutputStream to
* write Error Messages, etc. to. System.out is used if no
* informationOutputStream is provided.
*
* @return true if successful, false otherwise. Information about problems is
* provided via the informationOutputStream.
*/
public boolean serializeNodeset(ModelExtent opcUaModel, String opcuaNodesetFilePath,
OutputStream informationOutputStream) {
PrintWriter informationOutputStreamWriter; // An output stream for debug messages and similar
if (informationOutputStream != null)
informationOutputStreamWriter = new PrintWriter(informationOutputStream);
else
informationOutputStreamWriter = new PrintWriter(System.out);
// Create a new resource and copy all resources from the transformation result
// to the new Resource Set
Resource resource = resSet.createResource(URI.createURI(opcuaNodesetFilePath));
EList<EObject> contents = resource.getContents();
contents.addAll(opcUaModel.getContents());
// Serialize the resource to an OPC UA Nodeset
File outputFile = new File(opcuaNodesetFilePath);
try {
serializeNodeset(resource, outputFile);
} catch (IOException e) {
informationOutputStreamWriter.println("Serializing nodeset failed with execption: " + e.getMessage());
return false;
}
return true;
}
/*
* Serializes a OPC UA model to an OPC UA Nodeset xml file.
*
* @param nodeIdsCsvModel ModelExtent object describing the the contents of the
* nodeIdsCsv model. Typically the result of a transformation process.
*
* @param nodeIdsCsvFilePath Path to the NodeIdsCsv file that will be created.
* Must have an "csv" file extension.
*
* @param informationOutputStream Can be used to provide an OutputStream to
* write Error Messages, etc. to. System.out is used if no
* informationOutputStream is provided.
*
* @return true if successful, false otherwise. Information about problems is
* provided via the informationOutputStream.
*/
public boolean serializeNodeIdsCsv(ModelExtent nodeIdsCsvModel, String nodeIdsCsvFilePath,
OutputStream informationOutputStream) {
PrintWriter informationOutputStreamWriter; // An output stream for debug messages and similar
if (informationOutputStream != null)
informationOutputStreamWriter = new PrintWriter(informationOutputStream);
else
informationOutputStreamWriter = new PrintWriter(System.out);
// Create a new resource and copy all resources from the transformation result
// to the new Resource Set
ResourceSet resSet = new ResourceSetImpl();
Resource resource = resSet.createResource(URI.createURI(nodeIdsCsvFilePath));
EList<EObject> contents = resource.getContents();
contents.addAll(nodeIdsCsvModel.getContents());
Map<Object, Object> options = new HashMap<Object, Object>();
URI nodesetURI = URI.createFileURI(nodeIdsCsvFilePath);
resource.setURI(nodesetURI);
try {
resource.save(options);
} catch (IOException e) {
informationOutputStreamWriter.println("Serializing NodeIdsCsv failed with execption: " + e.getMessage());
}
/*
* // Obtain a new resource set ResourceSet resSet = new ResourceSetImpl();
*
* // Create a new resource and copy all resources from the transformation
* result to the new Resource Set Resource resource =
* resSet.createResource(URI.createURI(opcuaNodesetFilePath)); EList <EObject>
* contents = resource.getContents(); contents.addAll(opcUaModel.getContents());
*
* // Serialize the resource to an OPC UA Nodeset File outputFile = new
* File(opcuaNodesetFilePath); OpcuaSerializer serializer = new
* OpcuaSerializer(); try { serializer.writeNodeset(resource, outputFile); }
* catch (IOException e) { informationOutputStreamWriter.
* println("Serializing nodeset failed with execption: " + e.getMessage());
* return false; }
*/
return true;
}
public void serializeNodeset(Resource resource, File outputFile) throws IOException {
// set metadata options, in particular utf-8 encoding attribute
ExtendedMetaData extendedMetaData = new BasicExtendedMetaData(resource.getResourceSet().getPackageRegistry());
Map<Object, Object> options = new HashMap<Object, Object>();
options.put(XMLResource.OPTION_EXTENDED_META_DATA, extendedMetaData);
options.put(XMLResource.OPTION_ENCODING, "utf-8");
options.put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.FALSE); // omit xsi:schemaLocation in the output file
// Try to set the xmlns to the OPC UA Namespace Uri
if (extendedMetaData.demandPackage("http://opcfoundation.org/UA/2011/03/UANodeSet.xsd") != null)
extendedMetaData.demandPackage("http://opcfoundation.org/UA/2011/03/UANodeSet.xsd").setNsPrefix("");
// serialize/persist the model to a nodeset XML file
URI nodesetURI = URI.createFileURI(outputFile.getAbsolutePath());
resource.setURI(nodesetURI);
resource.save(options);
System.out.println("Nodeset written to " + outputFile.getAbsolutePath());
}
}