Flow diagrams to Petri nets

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.

Code for Bentō:
Template:
Concepts:
Meta-models:

Yet Another Workflow Language(YAWL)

YAWL is a workflow language based on the workflow patterns, a joint effort of the Eindhoven University of Technology and the Queensland University of Technology. A YAWL model is made of atomic tasks, or tasks combining split/join behaviour. The supported split types are XOR (which triggers only one outgoing flow), OR (triggers some but not necessarily all outgoing flows), and AND (triggers all outgoing flows). The supported join types include AND (waits for completion of all incoming flows), XOR (waits for at least one incoming flow) and OR (waits for completion of either all incoming flows, or completion of all incoming flows that can finish). The authors of YAWL recommend to use OR-join sparingly, because models with such join can become difficult to understand.

Meta-model

The following diagram shows the YAWL meta-model, which is also available in SVG and PNG formats. It can be observed how Task contains two attributes, which are used to combine split/join behaviour. Tasks are connected trhough the flowsInto/flowsOutOf references, defined on the parent class ProcessControlElement.

Binding

The binding needs to create a virtual class, because there is no class in the meta-model to represent edges, but these are modelled as a pair of references. Then, we maps YAWL Tasks to Task in the concept when they split and join type is #NORMAL. In such case the Task is not considered an initial Task. InputConditions are mapped to initial Tasks, and OutputConditions to FinalTask. Then, depending on its split/join type, Tasks are assigned to ParallelSplit, Synchronization, ExclusiveChoice, SimpleMerge and MultiChoice. We currently do not support OR-join. The virtual class YawlEdge is mapped to FlowEdge, and such class is also used to select the appropriate collections to map the Node.ins and Node.outs features. Finally, FlowDiagram.edges selects all edges connecting tasks in the given process Decomposition.

binding yawl {  
	concept   FD   : "platform:/resource/bento.examples.flow_diagrams.petrinets/metamodels/flow_concept.ecore"
	metamodel YAWL : "platform:/resource/bento.examples.flow_diagrams.petrinets/bindings/yawl2pn/yawl.ecore"
	
	class YawlEdge {
		ref src : ProcessControlElement
		ref tgt : ProcessControlElement
	} init = YAWL!ProcessControlElement.allInstances()->collect(src| src.flowsOutOf->collect(tgt | 
		Tuple { type__ = 'YawlEdge', src = src, tgt = tgt
			, out = tgt, "in" = src
		 }
	))->flatten()
	
	class FlowDiagram     to Decomposition 
	class Node            to ProcessControlElement
	class Task            to Task, InputCondition when 
		if self.oclIsKindOf(YAWL!Task) then self.splitType = #NORMAL and self.joinType = #NORMAL else true endif
	class FinalTask       to OutputCondition
	class ParallelSplit   to Task when self.splitType = #AND
	class Synchronization to Task when self.joinType = #AND 
	class ExclusiveChoice to Task when self.splitType = #XOR
	class SimpleMerge     to Task when self.joinType = #XOR  
	class MultiChoice     to Task when self.splitType = #OR 
		
	class FlowEdge to virtual YawlEdge 	
	
	feature FlowDiagram.nodes is processControlElements 
		
	-- Involved in the virtual class mapping
	feature FlowDiagram.edges = 
		self.YawlEdge_AllInstances->select(y | self.processControlElements->exists(p | p = y.src ))	
	feature Node.outs = self.YawlEdge_AllInstances->select(y | y.src = self) 
	feature Node.ins  = self.YawlEdge_AllInstances->select(y | y.tgt = self) 
	feature FlowEdge."in"  is src
	feature FlowEdge."out" is tgt
		
	feature Task[Task].name is name
	feature Task[InputCondition].name = 'input-condition'

	feature Task[Task].isInitial = false -- self.oclIsKindOf(YAWL!InputCondition)
	feature Task[InputCondition].isInitial = true -- self.oclIsKindOf(YAWL!InputCondition)
	feature FinalTask.isTerminating = true
}