Skip to content

Commit

Permalink
Added support for Guards without semantics using the GuardVariableType
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas authored and Thomas committed Nov 17, 2020
1 parent a057eb8 commit 36aa8cc
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 14 deletions.
4 changes: 4 additions & 0 deletions QvtoTransformationRules/transforms/Common/Helpers.qvto
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,12 @@ helper getNamespaceUri(namespaceIndex : Integer) : String {
helper loadInternalNodeIds() {
// add NodeIds for Namespace 0
var y : Dict(String,String);
y->put("Boolean", "i=1");
y->put("Int32", "i=6");
y->put("Int32", "i=6");
y->put("Double", "i=11");
y->put("String", "i=12");
y->put("LocalizedText", "i=21");
y->put("NonHierarchicalReferences", "i=32");
y->put("HasModellingRule", "i=37");
y->put("HasTypeDefinition", "i=40");
Expand All @@ -140,6 +142,8 @@ helper loadInternalNodeIds() {
y->put("TransitionEventType", "i=2311");
y->put("InitialStateType", "i=2039");
y->put("FiniteStateMachineType", "i=2771");
y->put("HasGuard", "i=15112");
y->put("GuardVariableType", "i=15113");
IdentifierLookupTable->put(OPCUA_NAMESPACE_URI, y);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,20 @@ mapping UML::StateMachine::statemachine2FiniteStateMachineType(inout nodeset : O

// create the list of references object and add FiniteStateMachineType as supertype
_references := object OPCUA::ListOfReferences{};
_references.reference += object OPCUA::Reference{referenceType := "HasSubtype"; value := getId("FiniteStateMachineType"); isForward := false};
_references.reference += object OPCUA::Reference{referenceType := getId("HasSubtype"); value := getId("FiniteStateMachineType"); isForward := false};

// create an OPCUA::Object of type InitialStateType for each state
nodeset.uAObject += self.ownedElement->selectByType(UML::Region).ownedElement->selectByKind(UML::Pseudostate)->map pseudostate2InitialState(result);
nodeset.uAObject += self.ownedElement->selectByType(UML::Region).ownedElement->selectByKind(UML::State)->map state2State(result);
nodeset.uAObject += self.ownedElement->selectByType(UML::Region).ownedElement->selectByKind(UML::Transition)->map transition2Transition(result);
nodeset.uAObject += self.ownedElement->selectByType(UML::Region).ownedElement->selectByKind(UML::Transition)->map transition2Transition(nodeset, result);

//
// create a OPCUA::StateType for each state
}

mapping UML::State::state2State(inout parent : OPCUA::UANode) : OPCUA::UAObject {
log("state2State for UML element " + self.name);

mapping UML::Pseudostate::pseudostate2InitialState(inout parent : OPCUA::UANode) : OPCUA::UAObject {
log("pseudostate2InitialState for UML element " + self.name);

// set attributes of the OPCUA::UAObjectType
browseName := self.createBrowseName();
Expand All @@ -39,16 +40,17 @@ mapping UML::State::state2State(inout parent : OPCUA::UANode) : OPCUA::UAObject

// create the list of references object
_references := object OPCUA::ListOfReferences{};
_references.reference += object OPCUA::Reference{referenceType := getId("HasTypeDefinition"); value := getId("StateType")};
_references.reference += object OPCUA::Reference{referenceType := getId("HasTypeDefinition"); value := getId("InitialStateType")};
_references.reference += object OPCUA::Reference{referenceType := getId("HasModellingRule"); value := getId("ModellingRule_Mandatory")}; // TODO replace with correct modelling rule
_references.reference += object OPCUA::Reference{referenceType := getId("HasComponent"); value := parent.nodeId; isForward := false};

// add a reference from the parent node to this node
parent._references.reference += object OPCUA::Reference{referenceType := "HasComponent"; value := result.nodeId};
parent._references.reference += object OPCUA::Reference{referenceType := getId("HasComponent"); value := result.nodeId};
}

mapping UML::Pseudostate::pseudostate2InitialState(inout parent : OPCUA::UANode) : OPCUA::UAObject {
log("pseudostate2InitialState for UML element " + self.name);

mapping UML::State::state2State(inout parent : OPCUA::UANode) : OPCUA::UAObject {
log("state2State for UML element " + self.name);

// set attributes of the OPCUA::UAObjectType
browseName := self.createBrowseName();
Expand All @@ -58,15 +60,16 @@ mapping UML::Pseudostate::pseudostate2InitialState(inout parent : OPCUA::UANode)

// create the list of references object
_references := object OPCUA::ListOfReferences{};
_references.reference += object OPCUA::Reference{referenceType := getId("HasTypeDefinition"); value := getId("InitialStateType")};
_references.reference += object OPCUA::Reference{referenceType := getId("HasTypeDefinition"); value := getId("StateType")};
_references.reference += object OPCUA::Reference{referenceType := getId("HasModellingRule"); value := getId("ModellingRule_Mandatory")}; // TODO replace with correct modelling rule
_references.reference += object OPCUA::Reference{referenceType := getId("HasComponent"); value := parent.nodeId; isForward := false};

// add a reference from the parent node to this node
parent._references.reference += object OPCUA::Reference{referenceType := getId("HasComponent"); value := result.nodeId};
parent._references.reference += object OPCUA::Reference{referenceType := "HasComponent"; value := result.nodeId};
}

mapping UML::Transition::transition2Transition(inout parent : OPCUA::UANode) : OPCUA::UAObject {
//parent should be a subtype of FiniteStateMachineType
mapping UML::Transition::transition2Transition(inout nodeset : OPCUA::UANodeSetType, inout parent : OPCUA::UANode) : OPCUA::UAObject {
var transitionName : String;
if(self.name <> null) { // if the transition has a name, use it as name for the UAObject
// log("transition2Transition for UML element " + self.name);
Expand Down Expand Up @@ -96,14 +99,17 @@ mapping UML::Transition::transition2Transition(inout parent : OPCUA::UANode) : O
// add a reference from the parent node to this node
parent._references.reference += object OPCUA::Reference{referenceType := getId("HasComponent"); value := result.nodeId};

// process the trigger(s), if specified
// process the trigger(s) if specified
_references.reference += self.trigger->map trigger2HasCause(result);

// process the event, if specified
// process the event if specified
_references.reference += self.trigger->map trigger2HasCause(result);
if(CFG_GENERATE_TRANSITION_EVENTS) {
_references.reference += object OPCUA::Reference{referenceType := getId("HasEffect"); value := getId("TransitionEventType")};
}
};

// process the constraints/guards if specified
_references.reference += self.ownedRule->map constraint2HasGuard(nodeset, result, parent);
}

mapping UML::Trigger::trigger2HasCause(inout parent : OPCUA::UANode) : OPCUA::Reference {
Expand All @@ -114,3 +120,37 @@ mapping UML::Trigger::trigger2HasCause(inout parent : OPCUA::UANode) : OPCUA::Re
referenceType := getId("HasCause");
value := self.event.oclAsType(UML::CallEvent).operation.createNodeId(); // TODO: it is assumed that the UML::Operation is transformed to an OPCUA::Method elsewhere, e.g., by the class transformation rule
}

mapping UML::Constraint::constraint2HasGuard(inout nodeset : OPCUA::UANodeSetType, inout parent : OPCUA::UANode, inout stateMachineType : OPCUA::UANode) : OPCUA::Reference {
log("constraint2HasGuard for UML element " + self.name);

if(self.specification = null) {
log("Processing constraint/guard without specification");

// Create a GuardVariable
var guardVariable := object OPCUA::UAVariable{};
guardVariable.browseName := self.name;
guardVariable.nodeId := self.createNodeId();
guardVariable.displayName := object OPCUA::LocalizedText{value := guardVariable.browseName};
guardVariable.dataType := getId("LocalizedText");

// add list of references
guardVariable._references := object OPCUA::ListOfReferences{};
guardVariable._references.reference += object OPCUA::Reference{referenceType := getId("HasTypeDefinition"); value := getId("GuardVariableType")};
guardVariable._references.reference += object OPCUA::Reference{referenceType := getId("HasComponent"); value := stateMachineType.nodeId; isForward := false};
guardVariable._references.reference += object OPCUA::Reference{referenceType := getId("HasGuard"); value := parent.nodeId; isForward := false};
guardVariable._references.reference += object OPCUA::Reference{referenceType := getId("HasModellingRule"); value := getId("ModellingRule_Mandatory")}; // TODO replace with correct modelling rule

// the GuardVariable is added as a component of the stateMachineType
guardVariable.parentNodeId := stateMachineType.nodeId;

// add the new GuardVariable to the nodeset
nodeset.uAVariable += guardVariable;

// add a HasComponent reference from the containing stateMachine to the new GuardVariable
stateMachineType._references.reference += object OPCUA::Reference{referenceType := getId("HasComponent"); value := guardVariable.nodeId};

referenceType := getId("HasGuard");
value := guardVariable.nodeId;
};
}

0 comments on commit 36aa8cc

Please sign in to comment.