statemachine 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +1 -1
- data/lib/statemachine/builder.rb +14 -0
- data/lib/statemachine/generate/java/java_statemachine.rb +54 -28
- data/lib/statemachine/state.rb +5 -1
- data/lib/statemachine/statemachine.rb +3 -3
- data/lib/statemachine/stub_context.rb +24 -0
- data/lib/statemachine/superstate.rb +10 -2
- data/lib/statemachine/transition.rb +4 -7
- data/lib/statemachine/version.rb +1 -1
- data/spec/generate/java/java_statemachine_spec.rb +114 -25
- data/spec/transition_spec.rb +2 -2
- metadata +14 -6
data/README.rdoc
CHANGED
@@ -14,7 +14,7 @@ Where to start:
|
|
14
14
|
== Documentation
|
15
15
|
|
16
16
|
Some documentation is available here in this RDOC documentation.
|
17
|
-
You may also find useful documentation on the Statemachine website: http://
|
17
|
+
You may also find useful documentation on the Statemachine website: http://slagyr.github.com/statemachine
|
18
18
|
|
19
19
|
A detailed tutorial and overview of Finite State Machines and this library can be found
|
20
20
|
at http://blog.8thlight.com/articles/2006/11/17/understanding-statemachines-part-1-states-and-transitions.
|
data/lib/statemachine/builder.rb
CHANGED
@@ -261,6 +261,20 @@ module Statemachine
|
|
261
261
|
@statemachine.context = a_context
|
262
262
|
a_context.statemachine = @statemachine if a_context.respond_to?(:statemachine=)
|
263
263
|
end
|
264
|
+
|
265
|
+
# Stubs the context. This makes statemachine immediately useable, even if functionless.
|
266
|
+
# The stub will print all the actions called so it's nice for trial runs.
|
267
|
+
#
|
268
|
+
# sm = Statemachine.build do
|
269
|
+
# ...
|
270
|
+
# stub_context :verbose => true
|
271
|
+
# end
|
272
|
+
#
|
273
|
+
# Statemachine.context may also be used.
|
274
|
+
def stub_context(options={})
|
275
|
+
require 'statemachine/stub_context'
|
276
|
+
context StubContext.new(options)
|
277
|
+
end
|
264
278
|
end
|
265
279
|
|
266
280
|
end
|
@@ -42,8 +42,6 @@ module Statemachine
|
|
42
42
|
private ###########################################
|
43
43
|
|
44
44
|
def explore_sm
|
45
|
-
@state_names = @sm.states.keys.reject{|k| k.nil? }.map { |id| id.to_s.camalized }.sort
|
46
|
-
|
47
45
|
events = []
|
48
46
|
actions = []
|
49
47
|
@sm.states.values.each do |state|
|
@@ -59,6 +57,8 @@ module Statemachine
|
|
59
57
|
add_action(actions, state.exit_action)
|
60
58
|
end
|
61
59
|
@action_names = actions.uniq.map {|e| e.to_s.camalized(:lower)}.sort
|
60
|
+
|
61
|
+
@startstate = @sm.get_state(@sm.startstate).resolve_startstate
|
62
62
|
end
|
63
63
|
|
64
64
|
def add_action(actions, action)
|
@@ -72,7 +72,8 @@ module Statemachine
|
|
72
72
|
src << "public class #{@classname}" << endl
|
73
73
|
begin_scope(src)
|
74
74
|
|
75
|
-
|
75
|
+
add_instance_variables(src)
|
76
|
+
add_constructor(src)
|
76
77
|
add_statemachine_boilerplate_code(src)
|
77
78
|
add_event_delegation(src)
|
78
79
|
add_statemachine_exception(src)
|
@@ -83,20 +84,42 @@ module Statemachine
|
|
83
84
|
return src.to_s
|
84
85
|
end
|
85
86
|
|
86
|
-
def
|
87
|
-
src << "//
|
88
|
-
@
|
89
|
-
|
87
|
+
def add_instance_variables (src)
|
88
|
+
src << "// Instance variables" << endl
|
89
|
+
concrete_states = @sm.states.values.reject { |state| state.id.nil? || !state.concrete? }.sort { |a, b| a.id <=> b.id }
|
90
|
+
concrete_states.each do |state|
|
91
|
+
name = state.id.to_s.camalized
|
92
|
+
src << "public final State #{name.upcase} = new #{name}State(this);" << endl
|
90
93
|
end
|
91
|
-
|
94
|
+
superstates = @sm.states.values.reject { |state| state.concrete? }.sort { |a, b| a.id <=> b.id }
|
95
|
+
superstates.each do |superstate|
|
96
|
+
startstate = superstate.resolve_startstate
|
97
|
+
src << "public final State #{superstate.id.to_s.upcase} = #{startstate.id.to_s.upcase};" << endl
|
98
|
+
end
|
99
|
+
src << "private State state = #{@startstate.id.to_s.upcase};" << endl
|
100
|
+
src << endl
|
101
|
+
src << "private #{@context_classname} context;" << endl
|
92
102
|
src << endl
|
93
103
|
end
|
94
104
|
|
105
|
+
def add_constructor(src)
|
106
|
+
src << "// Statemachine constructor" << endl
|
107
|
+
add_method(src, nil, @classname, "#{@context_classname} context") do
|
108
|
+
src << "this.context = context;" << endl
|
109
|
+
entered_states = []
|
110
|
+
entry_state = @startstate
|
111
|
+
while entry_state != @sm.root
|
112
|
+
entered_states << entry_state
|
113
|
+
entry_state = entry_state.superstate
|
114
|
+
end
|
115
|
+
entered_states.reverse.each do |state|
|
116
|
+
src << "context.#{state.entry_action.to_s.camalized(:lower)}();" << endl if state.entry_action
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
95
121
|
def add_statemachine_boilerplate_code(src)
|
96
122
|
src << "// The following is boiler plate code standard to all statemachines" << endl
|
97
|
-
src << "private #{@context_classname} context;" << endl
|
98
|
-
src << endl
|
99
|
-
add_one_liner(src, nil, @classname, "#{@context_classname} context", "this.context = context")
|
100
123
|
add_one_liner(src, @context_classname, "getContext", nil, "return context")
|
101
124
|
add_one_liner(src, "State", "getState", nil, "return state")
|
102
125
|
add_one_liner(src, "void", "setState", "State newState", "state = newState")
|
@@ -115,7 +138,7 @@ module Statemachine
|
|
115
138
|
begin_scope(src)
|
116
139
|
src << "public StatemachineException(State state, String event)" << endl
|
117
140
|
begin_scope(src)
|
118
|
-
src << "super(\"Missing transition from
|
141
|
+
src << "super(\"Missing transition from '\" + state.getClass().getSimpleName() + \"' with the '\" + event + \"' event.\");" << endl
|
119
142
|
end_scope(src)
|
120
143
|
end_scope(src)
|
121
144
|
src << endl
|
@@ -137,34 +160,41 @@ module Statemachine
|
|
137
160
|
|
138
161
|
def add_state_implementations(src)
|
139
162
|
src << "// State implementations" << endl
|
140
|
-
@sm.states.keys.sort.each do |state_id|
|
141
|
-
|
163
|
+
@sm.states.keys.reject{|k| k.nil? }.sort.each do |state_id|
|
164
|
+
state = @sm.states[state_id]
|
165
|
+
state_name = state.id.to_s.camalized
|
166
|
+
base_class = state.superstate == @sm.root ? "State" : state.superstate.id.to_s.camalized
|
167
|
+
|
168
|
+
add_concrete_state_class(src, state, state_name, base_class) if state_id
|
142
169
|
end
|
143
170
|
end
|
144
171
|
|
145
|
-
def
|
146
|
-
state = @sm.states[state_id]
|
147
|
-
state_name = state_id.to_s.camalized
|
172
|
+
def add_concrete_state_class(src, state, state_name, base_class)
|
148
173
|
src << "public static class #{state_name}State extends State" << endl
|
149
174
|
src << "{" << endl
|
150
175
|
src.indent!
|
151
176
|
add_one_liner(src, nil, "#{state_name}State", "#{@classname} statemachine", "super(statemachine)")
|
152
177
|
state.transitions.keys.sort.each do |event_id|
|
153
|
-
|
178
|
+
transition = state.transitions[event_id]
|
179
|
+
add_state_event_handler(transition, src)
|
154
180
|
end
|
155
181
|
src.undent!
|
156
182
|
src << "}" << endl
|
157
183
|
src << endl
|
158
184
|
end
|
159
185
|
|
160
|
-
def add_state_event_handler(
|
161
|
-
|
162
|
-
|
186
|
+
def add_state_event_handler(transition, src)
|
187
|
+
event_name = transition.event.to_s.camalized(:lower)
|
188
|
+
exits, entries = transition.exits_and_entries(@sm.get_state(transition.origin_id), @sm.get_state(transition.destination_id))
|
163
189
|
add_method(src, "void", event_name, nil) do
|
164
|
-
|
165
|
-
src << "statemachine.getContext().#{
|
190
|
+
exits.each do |exit|
|
191
|
+
src << "statemachine.getContext().#{exit.exit_action.to_s.camalized(:lower)}();" << endl if exit.exit_action
|
166
192
|
end
|
193
|
+
src << "statemachine.getContext().#{transition.action.to_s.camalized(:lower)}();" << endl if transition.action
|
167
194
|
src << "statemachine.setState(statemachine.#{transition.destination_id.to_s.upcase});" << endl
|
195
|
+
entries.each do |entry|
|
196
|
+
src << "statemachine.getContext().#{entry.entry_action.to_s.camalized(:lower)}();" << endl if entry.entry_action
|
197
|
+
end
|
168
198
|
end
|
169
199
|
end
|
170
200
|
|
@@ -175,7 +205,7 @@ module Statemachine
|
|
175
205
|
end
|
176
206
|
|
177
207
|
def add_method(src, return_type, name, params)
|
178
|
-
src << "public #{return_type} #{name}(#{params})".sub('
|
208
|
+
src << "public #{return_type} #{name}(#{params})".sub(' ' * 2, ' ') << endl
|
179
209
|
begin_scope(src)
|
180
210
|
yield
|
181
211
|
end_scope(src)
|
@@ -191,10 +221,6 @@ module Statemachine
|
|
191
221
|
src.undent! << "}" << endl
|
192
222
|
end
|
193
223
|
|
194
|
-
def default_state_name
|
195
|
-
@sm.startstate.nil? ? "null" : @sm.startstate.to_s.upcase
|
196
|
-
end
|
197
|
-
|
198
224
|
def build_context_src
|
199
225
|
src = begin_src
|
200
226
|
src << "public interface #{@context_classname}" << endl
|
data/lib/statemachine/state.rb
CHANGED
@@ -50,7 +50,7 @@ module Statemachine
|
|
50
50
|
# Resets the statemachine back to its starting state.
|
51
51
|
def reset
|
52
52
|
@state = get_state(@root.startstate_id)
|
53
|
-
while @state and not @state.
|
53
|
+
while @state and not @state.concrete?
|
54
54
|
@state = get_state(@state.startstate_id)
|
55
55
|
end
|
56
56
|
raise StatemachineException.new("The state machine doesn't know where to start. Try setting the startstate.") if @state == nil
|
@@ -106,7 +106,7 @@ module Statemachine
|
|
106
106
|
elsif(is_history_state_id?(id))
|
107
107
|
superstate_id = base_id(id)
|
108
108
|
superstate = @states[superstate_id]
|
109
|
-
raise StatemachineException.new("No history exists for #{superstate} since it is not a super state.") if superstate.
|
109
|
+
raise StatemachineException.new("No history exists for #{superstate} since it is not a super state.") if superstate.concrete?
|
110
110
|
return load_history(superstate)
|
111
111
|
else
|
112
112
|
state = State.new(id, @root, self)
|
@@ -162,7 +162,7 @@ module Statemachine
|
|
162
162
|
100.times do
|
163
163
|
history = superstate.history_id ? get_state(superstate.history_id) : nil
|
164
164
|
raise StatemachineException.new("#{superstate} doesn't have any history yet.") if not history
|
165
|
-
if history.
|
165
|
+
if history.concrete?
|
166
166
|
return history
|
167
167
|
else
|
168
168
|
superstate = history
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Statemachine
|
2
|
+
|
3
|
+
class StubContext
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@verbose = options[:verbose]
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :statemachine
|
10
|
+
|
11
|
+
def method(name)
|
12
|
+
super(name)
|
13
|
+
rescue
|
14
|
+
self.class.class_eval "def #{name}(*args, &block); __generic_method(:#{name}, *args, &block); end"
|
15
|
+
return super(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def __generic_method(name, *args)
|
19
|
+
puts "action invoked: #{name}(#{args.join(", ")}) #{block_given? ? "with block" : ""}" if @verbose
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -11,10 +11,18 @@ module Statemachine
|
|
11
11
|
@history_id = nil
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def concrete?
|
15
15
|
return false
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
|
+
def startstate
|
19
|
+
return @statemachine.get_state(@startstate_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def resolve_startstate
|
23
|
+
return startstate.resolve_startstate
|
24
|
+
end
|
25
|
+
|
18
26
|
def substate_exiting(substate)
|
19
27
|
@history_id = substate.id
|
20
28
|
end
|
@@ -19,20 +19,16 @@ module Statemachine
|
|
19
19
|
|
20
20
|
origin.statemachine.invoke_action(@action, args, "transition action from #{origin} invoked by '#{@event}' event") if @action
|
21
21
|
|
22
|
-
terminal_state =
|
23
|
-
while terminal_state and not terminal_state.is_concrete?
|
24
|
-
terminal_state = statemachine.get_state(terminal_state.startstate_id)
|
25
|
-
entries << terminal_state
|
26
|
-
end
|
22
|
+
terminal_state = entries.last
|
27
23
|
terminal_state.activate if terminal_state
|
28
24
|
|
29
25
|
entries.each { |entered_state| entered_state.enter(args) }
|
30
26
|
end
|
31
27
|
|
32
28
|
def exits_and_entries(origin, destination)
|
29
|
+
return [], [] if origin == destination
|
33
30
|
exits = []
|
34
31
|
entries = exits_and_entries_helper(exits, origin, destination)
|
35
|
-
|
36
32
|
return exits, entries.reverse
|
37
33
|
end
|
38
34
|
|
@@ -52,8 +48,9 @@ module Statemachine
|
|
52
48
|
end
|
53
49
|
|
54
50
|
def entries_to_destination(exit_state, destination)
|
51
|
+
return nil if destination.nil?
|
55
52
|
entries = []
|
56
|
-
state = destination
|
53
|
+
state = destination.resolve_startstate
|
57
54
|
while state
|
58
55
|
entries << state
|
59
56
|
return entries if exit_state == state.superstate
|
data/lib/statemachine/version.rb
CHANGED
@@ -20,26 +20,58 @@ describe Statemachine::Statemachine, "(Java)" do
|
|
20
20
|
@sm.to_java(:output => @output, :name => "JavaTurnstile", :package => "test.turnstile")
|
21
21
|
end
|
22
22
|
|
23
|
+
def generate_complex_turnstile_sm
|
24
|
+
@sm = Statemachine.build do
|
25
|
+
superstate :operational do
|
26
|
+
on_entry :operate
|
27
|
+
on_exit :beep
|
28
|
+
state :locked do
|
29
|
+
on_entry :lock
|
30
|
+
event :coin, :unlocked
|
31
|
+
event :pass, :locked, :alarm
|
32
|
+
end
|
33
|
+
state :unlocked do
|
34
|
+
on_entry :unlock
|
35
|
+
event :coin, :unlocked, :thanks
|
36
|
+
event :pass, :locked
|
37
|
+
end
|
38
|
+
event :diagnose, :diagnostics
|
39
|
+
end
|
40
|
+
state :diagnostics do
|
41
|
+
on_entry :disable
|
42
|
+
on_exit :beep
|
43
|
+
event :operate, :operational
|
44
|
+
end
|
45
|
+
stub_context :verbose => true
|
46
|
+
end
|
47
|
+
|
48
|
+
@sm.to_java(:output => @output, :name => "JavaTurnstile", :package => "test.turnstile")
|
49
|
+
end
|
50
|
+
|
51
|
+
def load_lines(*segs)
|
52
|
+
filename = File.join(*segs)
|
53
|
+
File.should exist( filename)
|
54
|
+
return IO.read(filename).split("\n")
|
55
|
+
end
|
56
|
+
|
23
57
|
def empty_sm_lines
|
24
58
|
@sm.to_java(:name => "JavaTest", :output => @output, :package => "test.blank")
|
25
|
-
|
26
|
-
File.should exist( filename)
|
27
|
-
lines = IO.read(filename).split("\n")
|
28
|
-
return lines
|
59
|
+
return load_lines(@output, "test", "blank", "JavaTest.java")
|
29
60
|
end
|
30
61
|
|
31
|
-
def
|
62
|
+
def turnstile_lines
|
32
63
|
generate_turnstile_sm
|
33
|
-
|
34
|
-
File.should exist( filename)
|
35
|
-
return IO.read(filename).split("\n")
|
64
|
+
return load_lines(@output, "test", "turnstile", "JavaTurnstile.java")
|
36
65
|
end
|
37
66
|
|
38
|
-
def
|
67
|
+
def turnstile_context_lines
|
39
68
|
generate_turnstile_sm
|
40
|
-
|
41
|
-
|
42
|
-
|
69
|
+
return load_lines(@output, "test", "turnstile", "JavaTurnstileContext.java")
|
70
|
+
end
|
71
|
+
|
72
|
+
def complex_turnstile_lines
|
73
|
+
generate_complex_turnstile_sm
|
74
|
+
return load_lines(@output, "test", "turnstile", "JavaTurnstile.java")
|
43
75
|
end
|
44
76
|
|
45
77
|
def find_lines_after(lines, goose)
|
@@ -78,17 +110,19 @@ describe Statemachine::Statemachine, "(Java)" do
|
|
78
110
|
lines.last.should == "}"
|
79
111
|
end
|
80
112
|
|
81
|
-
it "should generate
|
82
|
-
lines = empty_sm_lines
|
83
|
-
lines = find_lines_after(lines, "// The following is boiler plate code standard to all statemachines")
|
113
|
+
it "should generate the constructor" do
|
114
|
+
lines = find_lines_after(empty_sm_lines, "// Statemachine constructor")
|
84
115
|
|
85
|
-
lines.shift.should == " private JavaTestContext context;"
|
86
|
-
lines.shift.should == ""
|
87
116
|
lines.shift.should == " public JavaTest(JavaTestContext context)"
|
88
117
|
lines.shift.should == " {"
|
89
118
|
lines.shift.should == " this.context = context;"
|
90
119
|
lines.shift.should == " }"
|
91
120
|
lines.shift.should == ""
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should generate sm boilerplate code" do
|
124
|
+
lines = find_lines_after(empty_sm_lines, "// The following is boiler plate code standard to all statemachines")
|
125
|
+
|
92
126
|
lines.shift.should == " public JavaTestContext getContext()"
|
93
127
|
lines.shift.should == " {"
|
94
128
|
lines.shift.should == " return context;"
|
@@ -113,9 +147,9 @@ describe Statemachine::Statemachine, "(Java)" do
|
|
113
147
|
lines.shift.should == " {"
|
114
148
|
lines.shift.should == " public StatemachineException(State state, String event)"
|
115
149
|
lines.shift.should == " {"
|
116
|
-
lines.shift.should == " super(\"Missing transition from
|
150
|
+
lines.shift.should == " super(\"Missing transition from '\" + state.getClass().getSimpleName() + \"' with the '\" + event + \"' event.\");"
|
117
151
|
lines.shift.should == " }"
|
118
|
-
lines.shift.should == " }"
|
152
|
+
lines.shift.should == " }"
|
119
153
|
end
|
120
154
|
|
121
155
|
it "should generate base state" do
|
@@ -136,7 +170,7 @@ describe Statemachine::Statemachine, "(Java)" do
|
|
136
170
|
|
137
171
|
it "should generate the context" do
|
138
172
|
@sm.to_java(:name => "JavaTest", :output => @output, :package => "com.blah")
|
139
|
-
|
173
|
+
|
140
174
|
filename = File.join(@output, "com", "blah", "JavaTestContext.java")
|
141
175
|
File.should exist(filename)
|
142
176
|
lines = IO.read(filename).split("\n")
|
@@ -153,15 +187,17 @@ describe Statemachine::Statemachine, "(Java)" do
|
|
153
187
|
end
|
154
188
|
|
155
189
|
it "should generate the state instance variables" do
|
156
|
-
lines = find_lines_after(
|
190
|
+
lines = find_lines_after(turnstile_lines, "// Instance variables")
|
157
191
|
|
158
192
|
lines.shift.should == " public final State LOCKED = new LockedState(this);"
|
159
193
|
lines.shift.should == " public final State UNLOCKED = new UnlockedState(this);"
|
160
194
|
lines.shift.should == " private State state = LOCKED;"
|
195
|
+
lines.shift.should == ""
|
196
|
+
lines.shift.should == " private JavaTurnstileContext context;"
|
161
197
|
end
|
162
198
|
|
163
199
|
it "should generate all the sm event handlers" do
|
164
|
-
lines = find_lines_after(
|
200
|
+
lines = find_lines_after(turnstile_lines, "// Event delegation")
|
165
201
|
|
166
202
|
lines.shift.should == " public void coin()"
|
167
203
|
lines.shift.should == " {"
|
@@ -176,7 +212,7 @@ describe Statemachine::Statemachine, "(Java)" do
|
|
176
212
|
end
|
177
213
|
|
178
214
|
it "should generate all the default event handlers" do
|
179
|
-
lines = find_lines_after(
|
215
|
+
lines = find_lines_after(turnstile_lines, "// The base state")
|
180
216
|
|
181
217
|
lines.shift.should == " public static abstract class State"
|
182
218
|
lines.shift.should == " {"
|
@@ -201,7 +237,7 @@ describe Statemachine::Statemachine, "(Java)" do
|
|
201
237
|
end
|
202
238
|
|
203
239
|
it "should generate state classes" do
|
204
|
-
lines = find_lines_after(
|
240
|
+
lines = find_lines_after(turnstile_lines, "// State implementations")
|
205
241
|
|
206
242
|
lines.shift.should == " public static class LockedState extends State"
|
207
243
|
lines.shift.should == " {"
|
@@ -248,7 +284,7 @@ describe Statemachine::Statemachine, "(Java)" do
|
|
248
284
|
end
|
249
285
|
|
250
286
|
it "should generate all the context methods" do
|
251
|
-
lines = find_lines_after(
|
287
|
+
lines = find_lines_after(turnstile_context_lines, "// Actions")
|
252
288
|
|
253
289
|
lines.shift.should == " void alarm();"
|
254
290
|
lines.shift.should == " void lock();"
|
@@ -256,4 +292,57 @@ describe Statemachine::Statemachine, "(Java)" do
|
|
256
292
|
lines.shift.should == " void unlock();"
|
257
293
|
end
|
258
294
|
|
295
|
+
it "should generate complext state instances" do
|
296
|
+
lines = find_lines_after(complex_turnstile_lines, "// Instance variables")
|
297
|
+
|
298
|
+
lines.shift.should == " public final State DIAGNOSTICS = new DiagnosticsState(this);"
|
299
|
+
lines.shift.should == " public final State LOCKED = new LockedState(this);"
|
300
|
+
lines.shift.should == " public final State UNLOCKED = new UnlockedState(this);"
|
301
|
+
lines.shift.should == " public final State OPERATIONAL = LOCKED;"
|
302
|
+
lines.shift.should == " private State state = LOCKED;"
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should generate entry actions on startup" do
|
306
|
+
lines = find_lines_after(complex_turnstile_lines, "// Statemachine constructor")
|
307
|
+
|
308
|
+
lines.shift.should == " public JavaTurnstile(JavaTurnstileContext context)"
|
309
|
+
lines.shift.should == " {"
|
310
|
+
lines.shift.should == " this.context = context;"
|
311
|
+
lines.shift.should == " context.operate();"
|
312
|
+
lines.shift.should == " context.lock();"
|
313
|
+
lines.shift.should == " }"
|
314
|
+
lines.shift.should == ""
|
315
|
+
end
|
316
|
+
|
317
|
+
it "should add entry/exit actions to each transition" do
|
318
|
+
lines = find_lines_after(complex_turnstile_lines, "public static class LockedState extends State")
|
319
|
+
|
320
|
+
lines.shift.should == " {"
|
321
|
+
lines.shift.should == " public LockedState(JavaTurnstile statemachine)"
|
322
|
+
lines.shift.should == " {"
|
323
|
+
lines.shift.should == " super(statemachine);"
|
324
|
+
lines.shift.should == " }"
|
325
|
+
lines.shift.should == ""
|
326
|
+
lines.shift.should == " public void coin()"
|
327
|
+
lines.shift.should == " {"
|
328
|
+
lines.shift.should == " statemachine.setState(statemachine.UNLOCKED);"
|
329
|
+
lines.shift.should == " statemachine.getContext().unlock();"
|
330
|
+
lines.shift.should == " }"
|
331
|
+
lines.shift.should == ""
|
332
|
+
lines.shift.should == " public void diagnose()"
|
333
|
+
lines.shift.should == " {"
|
334
|
+
lines.shift.should == " statemachine.getContext().beep();"
|
335
|
+
lines.shift.should == " statemachine.setState(statemachine.DIAGNOSTICS);"
|
336
|
+
lines.shift.should == " statemachine.getContext().disable();"
|
337
|
+
lines.shift.should == " }"
|
338
|
+
lines.shift.should == ""
|
339
|
+
lines.shift.should == " public void pass()"
|
340
|
+
lines.shift.should == " {"
|
341
|
+
lines.shift.should == " statemachine.getContext().alarm();"
|
342
|
+
lines.shift.should == " statemachine.setState(statemachine.LOCKED);"
|
343
|
+
lines.shift.should == " }"
|
344
|
+
lines.shift.should == ""
|
345
|
+
lines.shift.should == " }"
|
346
|
+
end
|
347
|
+
|
259
348
|
end
|
data/spec/transition_spec.rb
CHANGED
@@ -17,8 +17,8 @@ describe "Transition Calculating Exits and Entries" do
|
|
17
17
|
it "to itself" do
|
18
18
|
@a = Statemachine::State.new("a", nil, nil)
|
19
19
|
exits, entries = @transition.exits_and_entries(@a, @a)
|
20
|
-
exits.
|
21
|
-
entries.
|
20
|
+
exits.should == []
|
21
|
+
entries.should == []
|
22
22
|
end
|
23
23
|
|
24
24
|
it "to friend" do
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: statemachine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 5
|
8
|
+
- 1
|
9
|
+
version: 0.5.1
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Micah Martin
|
@@ -9,7 +14,7 @@ autorequire: statemachine
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-25 00:00:00 -05:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -35,6 +40,7 @@ files:
|
|
35
40
|
- lib/statemachine/generate/util.rb
|
36
41
|
- lib/statemachine/state.rb
|
37
42
|
- lib/statemachine/statemachine.rb
|
43
|
+
- lib/statemachine/stub_context.rb
|
38
44
|
- lib/statemachine/superstate.rb
|
39
45
|
- lib/statemachine/transition.rb
|
40
46
|
- lib/statemachine/version.rb
|
@@ -65,21 +71,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
65
71
|
requirements:
|
66
72
|
- - ">="
|
67
73
|
- !ruby/object:Gem::Version
|
74
|
+
segments:
|
75
|
+
- 0
|
68
76
|
version: "0"
|
69
|
-
version:
|
70
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
78
|
requirements:
|
72
79
|
- - ">="
|
73
80
|
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 0
|
74
83
|
version: "0"
|
75
|
-
version:
|
76
84
|
requirements: []
|
77
85
|
|
78
86
|
rubyforge_project: statemachine
|
79
|
-
rubygems_version: 1.3.
|
87
|
+
rubygems_version: 1.3.6
|
80
88
|
signing_key:
|
81
89
|
specification_version: 3
|
82
|
-
summary: Statemachine-0.5.
|
90
|
+
summary: Statemachine-0.5.1 - Statemachine Library for Ruby http://slagyr.github.com/statemachine
|
83
91
|
test_files:
|
84
92
|
- spec/action_invokation_spec.rb
|
85
93
|
- spec/builder_spec.rb
|