diff --git a/QvtoTransformationRules/transforms/ClassDiagram/Operations.qvto b/QvtoTransformationRules/transforms/ClassDiagram/Operations.qvto index 8876c32..fceaf95 100644 --- a/QvtoTransformationRules/transforms/ClassDiagram/Operations.qvto +++ b/QvtoTransformationRules/transforms/ClassDiagram/Operations.qvto @@ -6,8 +6,6 @@ modeltype UML uses 'http://www.eclipse.org/uml2/5.0.0/UML'; modeltype OPCUA uses set('http://opcfoundation.org/UA/2011/03/UANodeSet.xsd'); modeltype TYPES uses types('http://opcfoundation.org/UA/2008/02/Types.xsd'); modeltype ecore "strict" uses 'http://www.eclipse.org/emf/2002/Ecore'; -modeltype UMLTYPES uses types('http://www.eclipse.org/uml2/5.0.0/Types'); -modeltype UMLPARAMETER uses umlParameter('http://www.eclipse.org/papyrus/uml/textedit/parameter/xtext/UmlParameter'); /* * Transforming UML Operations to OPC UA Methods requires an UAMethod node and, possibly, @@ -37,7 +35,7 @@ mapping UML::Operation::operation2UAMethod(inout parent : OPCUA::UANode, inout n if (self.ownedElement->selectByType(UML::Parameter)->select(direction = UML::ParameterDirectionKind::_'in')->size() > 0){ // if the operation has input parameters // create a UAVariable for input arguments var inputArgumentsVariable := object OPCUA::UAVariable{ - nodeId := self.createNodeId() + "InputArguments"; + nodeId := self.createNodeId(false); browseName := "InputArguments"; displayName := object OPCUA::LocalizedText{value := "InputArguments"}; dataType := getIdOrAlias("Argument"); @@ -72,7 +70,7 @@ mapping UML::Operation::operation2UAMethod(inout parent : OPCUA::UANode, inout n if (self.ownedElement->selectByType(UML::Parameter)->select(direction = UML::ParameterDirectionKind::_'out')->size() > 0){ // if the operation has output parameters // create a UAVariable for output arguments var outputArgumentsVariable := object OPCUA::UAVariable{ - nodeId := self.createNodeId() + "OutputArguments"; + nodeId := self.createNodeId(false); browseName := "OutputArguments"; displayName := object OPCUA::LocalizedText{value := "OutputArguments"}; dataType := "Argument"; diff --git a/QvtoTransformationRules/transforms/ClassDiagram/References.qvto b/QvtoTransformationRules/transforms/ClassDiagram/References.qvto index fa43420..302bb45 100644 --- a/QvtoTransformationRules/transforms/ClassDiagram/References.qvto +++ b/QvtoTransformationRules/transforms/ClassDiagram/References.qvto @@ -43,7 +43,7 @@ mapping UML::Property::property2Reference(inout parent : OPCUA::UANode, inout no }; var targetObject := object OPCUA::UAObject{ - nodeId := self.createNodeId(targetObjectName); + nodeId := self.createNodeId(false); parentNodeId := parent.nodeId; }; @@ -94,7 +94,7 @@ mapping UML::Property::property2Reference(inout parent : OPCUA::UANode, inout no log("Creating new reference type " + self.association.name); var newReferenceType := object OPCUA::UAReferenceType { - nodeId := self.createNodeId(self.association.name); + nodeId := self.association.createNodeId(); browseName := self.association.name; displayName := object OPCUA::LocalizedText{value := self.association.name}; }; diff --git a/QvtoTransformationRules/transforms/Common/Helpers.qvto b/QvtoTransformationRules/transforms/Common/Helpers.qvto index 71b1587..69db55d 100644 --- a/QvtoTransformationRules/transforms/Common/Helpers.qvto +++ b/QvtoTransformationRules/transforms/Common/Helpers.qvto @@ -14,6 +14,9 @@ modeltype OPCUA uses set('http://opcfoundation.org/UA/2011/03/UANodeSet.xsd'); // identifier have the form i=256 // nodeIds have the form ns=2;s=someString +property nodeIdCount : Integer = 1000; +property nodeIdLookupTable : Dict(UML::Element, String); // used to ensure that a nodeId is reused if it is generated for the same UML::Element twice + // entries are of the form "http://opcfoundation.org/UA/","NonHierarchicalReferences","i=32" property IdentifierLookupTable : Dict(String,Dict(String,String)); @@ -65,9 +68,9 @@ helper UML::Element::getUri() : String { return uri; } -helper UML::NamedElement::getNodeIdPrefix() : String { +helper UML::Element::getNodeIdPrefix() : String { var ns := self.getUri(); - return "ns=" + NamespaceUri2NamespaceIndex->get(ns).toString() + ";s="; + return "ns=" + NamespaceUri2NamespaceIndex->get(ns).toString() + ";i="; } helper UML::NamedElement::getNamePostfix() : String { @@ -78,14 +81,32 @@ helper UML::NamedElement::getNamePostfix() : String { }; } -helper UML::NamedElement::createNodeId() : String { - return self.getNodeIdPrefix() + self.name + self.getNamePostfix(); +helper UML::Element::createNodeId() : String { + // check if there has already been generated a nodeId for this UML::Element and if so, reuse that node id; + var nodeId := ""; + if(nodeIdLookupTable->keys()->includes(self)) { + nodeId := nodeIdLookupTable->get(self); + } else { + nodeId := self.getNodeIdPrefix() + nodeIdCount.toString(); + nodeIdLookupTable->put(self, nodeId); + nodeIdCount := nodeIdCount + 1; + }; + return nodeId; } -helper UML::NamedElement::createNodeId(nodeName : String) : String { - return self.getNodeIdPrefix() + nodeName + self.getNamePostfix(); +helper UML::Element::createNodeId(canReuseExistingNode : Boolean) : String { + var nodeId := ""; + if(canReuseExistingNode) { + nodeId := self.createNodeId(); + } else { + nodeId := self.getNodeIdPrefix() + nodeIdCount.toString(); + nodeIdLookupTable->put(self, nodeId); + nodeIdCount := nodeIdCount + 1; + }; + return nodeId; } + helper UML::NamedElement::createBrowseName() : String { return self.name + self.getNamePostfix(); } @@ -119,6 +140,7 @@ helper loadInternalNodeIds() { y->put("String", "i=12"); y->put("LocalizedText", "i=21"); y->put("NonHierarchicalReferences", "i=32"); + y->put("Organizes", "i=35"); y->put("HasModellingRule", "i=37"); y->put("HasTypeDefinition", "i=40"); y->put("HasSubtype", "i=45"); @@ -133,6 +155,7 @@ helper loadInternalNodeIds() { y->put("PropertyType", "i=68"); y->put("ModellingRule_Mandatory", "i=78"); y->put("ModellingRule_Optional", "i=80"); + y->put("ObjectsFolder", "i=85"); y->put("HasSubStateMachine", "i=117"); y->put("ModellingRule_OptionalPlaceholder", "i=11508"); y->put("ModellingRule_MandatoryPlaceholder", "i=11510"); diff --git a/QvtoTransformationRules/transforms/StateMachineDiagram/Transitions.qvto b/QvtoTransformationRules/transforms/StateMachineDiagram/Transitions.qvto index 3bc7cea..062938d 100644 --- a/QvtoTransformationRules/transforms/StateMachineDiagram/Transitions.qvto +++ b/QvtoTransformationRules/transforms/StateMachineDiagram/Transitions.qvto @@ -21,7 +21,7 @@ mapping UML::Transition::transition2Transition(inout nodeset : OPCUA::UANodeSetT // set attributes of the OPCUA::UAObjectType browseName := transitionName; - nodeId := self.createNodeId(transitionName); + nodeId := self.createNodeId(); displayName := displayName := object OPCUA::LocalizedText{value := browseName}; parentNodeId := parent.nodeId;