public
Description: Shade is a state machine (or workflow) engine for ColdFusion business objects.
Homepage:
Clone URL: git://github.com/ryanwood/shade.git
shade / README
b336ed32 » ryanwood 2008-07-18 Updated project name to sha... 1 === INFO ===
2
3 Shade is a state machine (or workflow) decorator for ColdFusion business objects.
4
5 === OVERVIEW ===
6
7 You have a Order business object...
8
9 You want to use it as a state machine (workflow), so you create a stateful
10 wrapper (call it what you wish) that extends shade.StateMachine. In it you
11 need to define at least 2 methods: init() and defineStates(). See the example
12 below.
13
14 -- Defining States and Events --
15
16 You add a state and events in the defineStates() method. You create a state
17 by calling addState([name of state]). This will register a state for you
18 object and create two methods available for use in you decorated object.
19
20 For instance addState('closed') will create a close() method to fire the close
21 event and an isClosed() method to check if the object is in a closed state.
22
23 There are 3 events that each state exposes: entering, after, and exit. See
24 "Adding Event Callbacks" for more.
25
26 You also add event here using the addEvent() method. An Event is anything
27 that will cause you object to transition from one state to another. To make
28 an event actually do something, you need to add transitions to that event.
29 The easiest way is to simply chain the addTransitions() method right to
30 addEvent(). A transition is a rule that defines 'from' states and a 'to'
31 state. It can also have a guard method that will prevent the transition
32 unless it returns true. A guard is called on the original business object
33 (not the decorated one).
34
35 -- Adding Event Callbacks --
36
37 You can also define event callback methods in the decorator. The signature
38 for those will be:
39
9bd2d89c » ryanwood 2008-07-18 Updated README 40 before[state]Action: Fires just before you enter this state
41 after[state]Action: Fires just after the state becomes current
42 exit[state]Action: Fires on the previous state just after the new
43 state becomes current (i.e. when you leave this state)
b2457504 » ryanwood 2008-10-13 Updated README 44
45 -- Persistence --
46
47 Without specifying a persistence object (service layer), the state property
48 is updated but not persisted to the database. Obviously, this has a limiting
49 effect on events. An after event will fire after the state is updated even
50 though it will not be changed in the database.
51
52 To get the proper use of the event callbacks, you should pass in a persistence
53 object which will be passed the the business object and is responsible for
54 saving it.
b336ed32 » ryanwood 2008-07-18 Updated project name to sha... 55
56 === EXAMPLE ===
57
58 <cfcomponent displayname="Order" extends="shade.StateMachine" output="false">
59 <cffunction name="getState" ...
60 <cffunction name="setState" ...
61 </cfcomponent>
62
b2457504 » ryanwood 2008-10-13 Updated README 63 <!--- This is optional, but needed for persistence --->
64 <cfcomponent displayname="OrderService" extends="shade.StateMachine" output="false">
65 <cffunction name="save">
66 <cfarguments name="order" ...
67 ...perform the save
68 </cffunction>
69 </cfcomponent>
70
b336ed32 » ryanwood 2008-07-18 Updated project name to sha... 71 <cfcomponent displayname="StatefulOrder" extends="shade.StateMachine" output="false">
72 <cfset instance = structNew() />
73
74 <cffunction name="init" access="public" returntype="any" output="false">
75 <cfargument name="order" required="true" />
b2457504 » ryanwood 2008-10-13 Updated README 76 <cfargument name="persistenceObject" required="false" />
b336ed32 » ryanwood 2008-07-18 Updated project name to sha... 77 <!---
78 Call super passing the original business object and the initial state.
79 You can also pass the method to set the state in your business object (without
80 the get/set in front of it). It defaults to 'State' which would them
81 assume that you business object had getState() and setState() methods.
82 --->
b2457504 » ryanwood 2008-10-13 Updated README 83 <cfset super.init(arguments.order, 'new', 'State', arguments.persistenceObject, 'save') />
84 <!---
85 or <cfset super.init(arguments.order, 'new') /> if there is no persistence object
86 --->
b336ed32 » ryanwood 2008-07-18 Updated project name to sha... 87 <cfreturn this />
88 </cffunction>
89
90 <cffunction name="configureState" access="private" returntype="void" output="false">
91 <cfscript>
92 addState('new');
93 addState('open');
94 addState('closed');
95 addState('returned');
96
97 addEvent('process').addTransitions('new', 'open');
98 addEvent('close').addTransitions('new,open', 'closed');
99 addEvent('return').addTransitions('closed', 'returned', 'canReturn');
100 </cfscript>
101 </cffunction>
102
103 <!--- Observers --->
104
9bd2d89c » ryanwood 2008-07-18 Updated README 105 <cffunction name="beforeClosedAction" access="public" returntype="void" output="false">
b336ed32 » ryanwood 2008-07-18 Updated project name to sha... 106 <!--- Perform some action such as sending a notification when an order is closed. --->
107 <cfmail ... />
108 </cffunction>
109
110 </cfcomponent>
111
112
113 === USAGE ===
114
115 <cfscript>
116 o = createObject("component", "Order").init();
117 order = createObject("component", "OrderState").init(o);
118
119 order.process();
120 order.isOpen(); <!--- true --->
121 order.close(); <!--- notice is sent by mailer --->
122 order.return();
123 </cfscript>