1// This source code comes from http://www.odelia-technologies.com/node/200 2 3package com.odelia.groovy.simpleworkflow 4 5 6class SimpleWorkflowEngine { 7 def workflowMap = [:] 8 def context = [:] 9 def beforeActivityName = 'beforeActivity' 10 def afterActivityName = 'afterActivity' 11 12 SimpleWorkflowEngine(workflow, context = [:]) { 13 this.context = context 14 parseWorkflow(workflow) 15 } 16 17 def parseWorkflow(workflow) { 18 workflowMap = new WorkflowParser().parse(workflow) 19 } 20 21 def getActivityValue(activity) { 22 assert activity instanceof String 23 if (!workflowMap[activity]) 24 throw new RuntimeException("$activity activity doesn't exist") 25 workflowMap[activity] 26 } 27 28 def execute(activity, pause) { 29 if (workflowMap[beforeActivityName]) { 30 getActivityValue(beforeActivityName)(context, activity) 31 } 32 33 def activityValue = getActivityValue(activity) 34 35 // Determine the next activity to execute 36 def nextActivity 37 switch (activityValue) { 38 case String: nextActivity = activityValue; break 39 case Closure: nextActivity = activityValue(context); break 40 case Class: nextActivity = activityValue.newInstance()(context) 41 } 42 43 if (workflowMap[afterActivityName]) { 44 getActivityValue(afterActivityName)(context, activity, nextActivity) 45 } 46 47 if (!pause && nextActivity) 48 call(nextActivity) 49 else 50 nextActivity 51 } 52 53 def call(activity) { 54 execute(activity, false) 55 } 56 57 def nextActivity(activity) { 58 execute(activity, true) 59 } 60 61 static void main(String[] args) { 62 if (args.size() != 2) { 63 println 'Usage: com.odelia.groovy.simpleworkflow.SimpleWorkflowEngine <dsl_filename> <activity_name>' 64 return 65 } 66 SimpleWorkflowEngine.newInstance(new File(args[0]))(args[1]) 67 } 68 69} 70 71private class WorkflowParser { 72 def map = [:] 73 74 def methodMissing(String name, args) { 75 map[name] = args[0] 76 } 77 78 def parse(Closure wf) { 79 wf.delegate = this 80 wf.resolveStrategy = Closure.DELEGATE_FIRST 81 wf() 82 map 83 } 84 85 def workflow = { it -> 86 it.delegate = this 87 it.resolveStrategy = Closure.DELEGATE_FIRST 88 it() 89 } 90 91 def parse(File workflowDef) { 92 def binding = new Binding([workflow: workflow]) 93 def shell = new GroovyShell(binding) 94 shell.evaluate(workflowDef) 95 map 96 } 97}