This document describes how the FD2PN component has been reused for several workflow languages. This component features a reusable transformation from a Workflow concept to a Petri net, which is able to deal with several of the patterns defined in the Workflow patterns catalog.
The menu provides links to the different artefacts of the case study.
Sequential function chart (SFC) is a graphical programming language used for programmable logic controllers (PLCs). It is based on Grafcet, whose semantics is based on Petri nets, and supported by the IEC 61131-3 standard
The following diagram is an excerpt with the relevant elements of the SFC/Grafcet meta-model. The complete diagrams are also available in SVG and PNG formats.
The actual Ecore meta-model has been extracted from the XML Schema provided by the PLC Open initiative (available here). Models conforming to the XML format can be created using the Beremiz tool.
This binding is highly influenced by the fact that the meta-model basically represents the tree structure of an XML document, and there is little inheritance and no explicit references.
All SFC elements that represent a node in the workflow must be mapped the Node class in the concept (line 6), because there is no common superclass in SFC. In SFC both steps and transitions have the task semantics, and edges are represented by Connection elements (lines 13-15). The "out" references in the concept cannot be mapped to any reference in SFC, because the target element of SFC node is identified by the "localId" attribute. Hence, it must be resolved by explicitly locating the Connection object with the corresponding identifier.
binding sfc { concept FD : "platform:/resource/bento.examples.flow_diagrams.petrinets/metamodels/flow_concept.ecore" metamodel SFC : "platform:/resource/bento.examples.flow_diagrams.petrinets/bindings/sfc2pn/tc60201.ecore" class FlowDiagram to SFCType1 class Node to StepType, TransitionType1, -- Important to add here every "virtual subclass" SelectionDivergenceType, SelectionConvergenceType, SimultaneousDivergenceType, SimultaneousConvergenceType -- Edges are not transitions (which has a different semantics), -- but Connection/ConnectionPointIn which is an structural concept to link "SFC nodes" -- (which include transitions) class FlowEdge to Connection class Task to StepType, TransitionType1 class FinalTask to NONE class ExclusiveChoice to SelectionDivergenceType class SimpleMerge to SelectionConvergenceType class Synchronization to SimultaneousConvergenceType class ParallelSplit to SimultaneousDivergenceType class MultiChoice to NONE feature FlowDiagram.nodes is allNodes feature FlowDiagram.edges is transition feature FlowEdge."in" = SFC!SFCType1.allInstances()->first().allNodes->any(n | n.localId = self.refLocalId) feature FlowEdge.out is parent feature Node[StepType]."in" = self.connectionPointIn.connection feature Node[StepType].out = SFC!Connection.allInstances()->select(c | c.refLocalId = self.localId) feature Node[TransitionType1]."in" = self.connectionPointIn.connection feature Node[TransitionType1].out = SFC!Connection.allInstances()->select(c | c.refLocalId = self.localId) feature Node[SelectionDivergenceType]."in" = self.connectionPointIn.connection feature Node[SelectionDivergenceType].out = SFC!Connection.allInstances()->select(c | c.refLocalId = self.localId) feature Node[SelectionConvergenceType]."in" = self.connectionPointIn.connection feature Node[SelectionConvergenceType].out = SFC!Connection.allInstances()->select(c | c.refLocalId = self.localId) feature Node[SimultaneousDivergenceType]."in" = self.connectionPointIn.connection feature Node[SimultaneousDivergenceType].out = SFC!Connection.allInstances()->select(c | c.refLocalId = self.localId) feature Node[SimultaneousConvergenceType]."in" = self.connectionPointIn.connection feature Node[SimultaneousConvergenceType].out = SFC!Connection.allInstances()->select(c | c.refLocalId = self.localId) feature Task[StepType].isInitial is initialStep feature Task[TransitionType1].isInitial = false feature FinalTask.isTerminating = false helper Connection.parent : OclAny = self.refImmediateComposite().refImmediateComposite() helper SFCType1.allNodes : OclAny = self.step.union(self.transition). union(self.selectionDivergence). union(self.selectionConvergence). union(self.simultaneousDivergence). union(self.simultaneousConvergence) }