MINT-scxml 1.0.0
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/.gemtest +0 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +18 -0
- data/History.txt +4 -0
- data/MINT-scxml.gemspec +35 -0
- data/Manifest.txt +49 -0
- data/README.rdoc +50 -0
- data/Rakefile +31 -0
- data/lib/MINT-scxml.rb +5 -0
- data/lib/MINT-scxml/scxml-parser.rb +228 -0
- data/spec/atm_spec.rb +69 -0
- data/spec/parser_spec.rb +394 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/test_handgestures_spec.rb +53 -0
- data/spec/testmachines/atm_enhanced.rb +129 -0
- data/spec/testmachines/handgestures-scxmlgui.png +0 -0
- data/spec/testmachines/handgestures-scxmlgui.scxml +106 -0
- data/spec/testmachines/multiplestates.rb +25 -0
- data/spec/testmachines/traffic_light_enhanced.rb +56 -0
- data/spec/testmachines/vending_machine1.rb +18 -0
- data/spec/testmachines/vending_machine2.rb +42 -0
- data/spec/testmachines/vending_machine3.rb +48 -0
- data/spec/testmachines/vending_machine4.rb +29 -0
- data/spec_helper.rb +8 -0
- data/statemachines/AICommand_scxml_spec.rb +38 -0
- data/statemachines/AIO_scxml_spec.rb +36 -0
- data/statemachines/aui-scxml/AIC.scxml +26 -0
- data/statemachines/aui-scxml/AICommand.scxml +34 -0
- data/statemachines/aui-scxml/AICommand2.scxml +32 -0
- data/statemachines/aui-scxml/AIO.scxml +25 -0
- data/statemachines/aui/AIC.rb +29 -0
- data/statemachines/aui/AIChoiceElement.rb +32 -0
- data/statemachines/aui/AICommand.rb +34 -0
- data/statemachines/aui/AIIN.rb +7 -0
- data/statemachines/aui/AIINContinous.rb +41 -0
- data/statemachines/aui/AIMultiChoice.rb +46 -0
- data/statemachines/aui/AIMultiChoiceElement.rb +46 -0
- data/statemachines/aui/AIOUTContinous.rb +41 -0
- data/statemachines/aui/AISingleChoice.rb +42 -0
- data/statemachines/aui/AISingleChoiceElement.rb +45 -0
- data/statemachines/aui/aio.rb +28 -0
- data/statemachines/specs/AICommand_spec.rb +58 -0
- data/statemachines/specs/AIINContinous_spec.rb +61 -0
- data/statemachines/specs/AIMultiChoiceElement_spec.rb +70 -0
- data/statemachines/specs/AIMultiChoice_spec.rb +56 -0
- data/statemachines/specs/AIOUTContinous_spec.rb +71 -0
- data/statemachines/specs/AIO_spec.rb +53 -0
- data/statemachines/specs/AISingleChoiceElement_spec.rb +58 -0
- data/statemachines/specs/AISingleChoice_spec.rb +68 -0
- metadata +146 -0
data/.gemtest
ADDED
File without changes
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
MINT-statemachine (1.2.3)
|
5
|
+
hoe (2.9.6)
|
6
|
+
rake (~> 0.8)
|
7
|
+
rake (0.9.2)
|
8
|
+
rspec (1.3.1)
|
9
|
+
|
10
|
+
PLATFORMS
|
11
|
+
ruby
|
12
|
+
x86-mingw32
|
13
|
+
|
14
|
+
DEPENDENCIES
|
15
|
+
MINT-statemachine (= 1.2.3)
|
16
|
+
hoe (= 2.9.6)
|
17
|
+
rake (= 0.9.2)
|
18
|
+
rspec (= 1.3.1)
|
data/History.txt
ADDED
data/MINT-scxml.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{MINT-scxml}
|
5
|
+
s.version = "1.0.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = [%q{Jessica H. Colnago, Sebastian Feuerstack}]
|
9
|
+
s.date = %q{2011-11-01}
|
10
|
+
s.description = %q{}
|
11
|
+
s.email = %q{Sebastian@Feuerstack.org}
|
12
|
+
s.extra_rdoc_files = [%q{History.txt}, %q{Manifest.txt}, %q{README.txt}]
|
13
|
+
s.files = [%q{.autotest}, %q{.idea/workspace.xml}, %q{Gemfile}, %q{Gemfile.lock}, %q{History.txt}, %q{MINT-scxml.gemspec}, %q{Manifest.txt}, %q{README.rdoc}, %q{README.txt}, %q{Rakefile}, %q{lib/MINT-scxml.rb}, %q{lib/MINT-scxml/scxml-parser.rb}, %q{spec/atm_spec.rb}, %q{spec/parser_spec.rb}, %q{spec/spec.opts}, %q{spec/spec_helper.rb}, %q{spec/test_handgestures_spec.rb}, %q{spec/testmachines/atm_enhanced.rb}, %q{spec/testmachines/handgestures-scxmlgui.png}, %q{spec/testmachines/handgestures-scxmlgui.scxml}, %q{spec/testmachines/multiplestates.rb}, %q{spec/testmachines/traffic_light_enhanced.rb}, %q{spec/testmachines/vending_machine1.rb}, %q{spec/testmachines/vending_machine2.rb}, %q{spec/testmachines/vending_machine3.rb}, %q{spec/testmachines/vending_machine4.rb}, %q{spec_helper.rb}, %q{statemachines/AICommand_scxml_spec.rb}, %q{statemachines/AIO_scxml_spec.rb}, %q{statemachines/aui-scxml/AIC.scxml}, %q{statemachines/aui-scxml/AICommand.scxml}, %q{statemachines/aui-scxml/AICommand2.scxml}, %q{statemachines/aui-scxml/AIO.scxml}, %q{statemachines/aui/AIC.rb}, %q{statemachines/aui/AIChoiceElement.rb}, %q{statemachines/aui/AICommand.rb}, %q{statemachines/aui/AIIN.rb}, %q{statemachines/aui/AIINContinous.rb}, %q{statemachines/aui/AIMultiChoice.rb}, %q{statemachines/aui/AIMultiChoiceElement.rb}, %q{statemachines/aui/AIOUTContinous.rb}, %q{statemachines/aui/AISingleChoice.rb}, %q{statemachines/aui/AISingleChoiceElement.rb}, %q{statemachines/aui/aio.rb}, %q{statemachines/specs/AICommand_spec.rb}, %q{statemachines/specs/AIINContinous_spec.rb}, %q{statemachines/specs/AIMultiChoiceElement_spec.rb}, %q{statemachines/specs/AIMultiChoice_spec.rb}, %q{statemachines/specs/AIOUTContinous_spec.rb}, %q{statemachines/specs/AIO_spec.rb}, %q{statemachines/specs/AISingleChoiceElement_spec.rb}, %q{statemachines/specs/AISingleChoice_spec.rb}, %q{.gemtest}]
|
14
|
+
s.homepage = %q{http://www.multi-access.de}
|
15
|
+
s.rdoc_options = [%q{--main}, %q{README.rdoc}]
|
16
|
+
s.require_paths = [%q{lib}]
|
17
|
+
s.rubyforge_project = %q{MINT-scxml}
|
18
|
+
s.rubygems_version = %q{1.8.5}
|
19
|
+
s.summary = %q{}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
s.specification_version = 3
|
23
|
+
|
24
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
25
|
+
s.add_runtime_dependency(%q<MINT-statemachine>, ["~> 1.2.3"])
|
26
|
+
s.add_development_dependency(%q<hoe>, ["~> 2.9"])
|
27
|
+
else
|
28
|
+
s.add_dependency(%q<MINT-statemachine>, ["~> 1.2.3"])
|
29
|
+
s.add_dependency(%q<hoe>, ["~> 2.9"])
|
30
|
+
end
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<MINT-statemachine>, ["~> 1.2.3"])
|
33
|
+
s.add_dependency(%q<hoe>, ["~> 2.9"])
|
34
|
+
end
|
35
|
+
end
|
data/Manifest.txt
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
Gemfile
|
2
|
+
Gemfile.lock
|
3
|
+
History.txt
|
4
|
+
MINT-scxml.gemspec
|
5
|
+
Manifest.txt
|
6
|
+
README.rdoc
|
7
|
+
Rakefile
|
8
|
+
lib/MINT-scxml.rb
|
9
|
+
lib/MINT-scxml/scxml-parser.rb
|
10
|
+
spec/atm_spec.rb
|
11
|
+
spec/parser_spec.rb
|
12
|
+
spec/spec.opts
|
13
|
+
spec/spec_helper.rb
|
14
|
+
spec/test_handgestures_spec.rb
|
15
|
+
spec/testmachines/atm_enhanced.rb
|
16
|
+
spec/testmachines/handgestures-scxmlgui.png
|
17
|
+
spec/testmachines/handgestures-scxmlgui.scxml
|
18
|
+
spec/testmachines/multiplestates.rb
|
19
|
+
spec/testmachines/traffic_light_enhanced.rb
|
20
|
+
spec/testmachines/vending_machine1.rb
|
21
|
+
spec/testmachines/vending_machine2.rb
|
22
|
+
spec/testmachines/vending_machine3.rb
|
23
|
+
spec/testmachines/vending_machine4.rb
|
24
|
+
spec_helper.rb
|
25
|
+
statemachines/AICommand_scxml_spec.rb
|
26
|
+
statemachines/AIO_scxml_spec.rb
|
27
|
+
statemachines/aui-scxml/AIC.scxml
|
28
|
+
statemachines/aui-scxml/AICommand.scxml
|
29
|
+
statemachines/aui-scxml/AICommand2.scxml
|
30
|
+
statemachines/aui-scxml/AIO.scxml
|
31
|
+
statemachines/aui/AIC.rb
|
32
|
+
statemachines/aui/AIChoiceElement.rb
|
33
|
+
statemachines/aui/AICommand.rb
|
34
|
+
statemachines/aui/AIIN.rb
|
35
|
+
statemachines/aui/AIINContinous.rb
|
36
|
+
statemachines/aui/AIMultiChoice.rb
|
37
|
+
statemachines/aui/AIMultiChoiceElement.rb
|
38
|
+
statemachines/aui/AIOUTContinous.rb
|
39
|
+
statemachines/aui/AISingleChoice.rb
|
40
|
+
statemachines/aui/AISingleChoiceElement.rb
|
41
|
+
statemachines/aui/aio.rb
|
42
|
+
statemachines/specs/AICommand_spec.rb
|
43
|
+
statemachines/specs/AIINContinous_spec.rb
|
44
|
+
statemachines/specs/AIMultiChoiceElement_spec.rb
|
45
|
+
statemachines/specs/AIMultiChoice_spec.rb
|
46
|
+
statemachines/specs/AIOUTContinous_spec.rb
|
47
|
+
statemachines/specs/AIO_spec.rb
|
48
|
+
statemachines/specs/AISingleChoiceElement_spec.rb
|
49
|
+
statemachines/specs/AISingleChoice_spec.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
= MINT Statemachine SCXML parser
|
2
|
+
|
3
|
+
* http://www.multi-access.de
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
This gem implements a state chart XML (SCXML) parser that generates a ruby statemachine.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* Currently only supports the very basic set of SCXML
|
12
|
+
|
13
|
+
== SYNOPSIS:
|
14
|
+
|
15
|
+
See tests
|
16
|
+
|
17
|
+
== REQUIREMENTS:
|
18
|
+
|
19
|
+
* Depends on MINT-statemachine gem
|
20
|
+
|
21
|
+
== INSTALL:
|
22
|
+
|
23
|
+
* sudo gem install MINT-scxml
|
24
|
+
|
25
|
+
== DEVELOPERS:
|
26
|
+
|
27
|
+
After checking out the source, run:
|
28
|
+
|
29
|
+
$ rake newb
|
30
|
+
|
31
|
+
This task will install any missing dependencies, run the tests/specs,
|
32
|
+
and generate the RDoc.
|
33
|
+
|
34
|
+
== LICENSE:
|
35
|
+
|
36
|
+
Copyright (C) 2010,2011 Sebastian Feuerstack, Jessica H. Colnago
|
37
|
+
|
38
|
+
This library is free software; you can redistribute it and/or
|
39
|
+
modify it under the terms of the GNU Lesser General Public
|
40
|
+
License as published by the Free Software Foundation; either
|
41
|
+
version 2.1 of the License, or (at your option) any later version.
|
42
|
+
|
43
|
+
This library is distributed in the hope that it will be useful,
|
44
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
45
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
46
|
+
Lesser General Public License for more details.
|
47
|
+
|
48
|
+
You should have received a copy of the GNU Lesser General Public
|
49
|
+
License along with this library; if not, write to the Free Software
|
50
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
|
6
|
+
# Hoe.plugin :compiler
|
7
|
+
# Hoe.plugin :cucumberfeatures
|
8
|
+
# Hoe.plugin :gem_prelude_sucks
|
9
|
+
# Hoe.plugin :inline
|
10
|
+
# Hoe.plugin :manifest
|
11
|
+
Hoe.plugin :newgem
|
12
|
+
# Hoe.plugin :racc
|
13
|
+
# Hoe.plugin :rubyforge
|
14
|
+
# Hoe.plugin :website
|
15
|
+
|
16
|
+
Hoe.spec 'MINT-scxml' do
|
17
|
+
self.developer 'Jessica H. Colnago, Sebastian Feuerstack', 'Sebastian@Feuerstack.org'
|
18
|
+
self.rubyforge_name = self.name # TODO this is default value
|
19
|
+
self.extra_deps = [['MINT-statemachine','~> 1.2.3']]
|
20
|
+
self.email = "Sebastian@Feuerstack.org"
|
21
|
+
|
22
|
+
# HEY! If you fill these out in ~/.hoe_template/Rakefile.erb then
|
23
|
+
# you'll never have to touch them again!
|
24
|
+
# (delete this comment too, of course)
|
25
|
+
|
26
|
+
# developer('FIX', 'FIX@example.com')
|
27
|
+
|
28
|
+
# self.rubyforge_name = 'scxml-gemx' # if different than 'scxml-gem'
|
29
|
+
end
|
30
|
+
|
31
|
+
# vim: syntax=ruby
|
data/lib/MINT-scxml.rb
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
# -*- coding: raw-text -*-
|
2
|
+
require 'rubygems'
|
3
|
+
require "bundler/setup"
|
4
|
+
require 'statemachine'
|
5
|
+
require 'rexml/document'
|
6
|
+
require 'rexml/streamlistener'
|
7
|
+
|
8
|
+
|
9
|
+
class State
|
10
|
+
attr_accessor :id, :initial
|
11
|
+
end
|
12
|
+
|
13
|
+
class Transition
|
14
|
+
attr_accessor :event, :target, :cond
|
15
|
+
end
|
16
|
+
|
17
|
+
class StatemachineParser < Statemachine::StatemachineBuilder
|
18
|
+
include REXML
|
19
|
+
include StreamListener
|
20
|
+
|
21
|
+
def initialize(context = nil, logger = nil, queue = nil)
|
22
|
+
super()
|
23
|
+
@actions = Array.new
|
24
|
+
@current_transition = nil
|
25
|
+
@current_state = nil
|
26
|
+
@current_element = nil
|
27
|
+
@parallel = nil
|
28
|
+
@state = Array.new
|
29
|
+
@statemachine.messenger = logger
|
30
|
+
@statemachine.message_queue = queue
|
31
|
+
@statemachine.context= context
|
32
|
+
@substate = Array.new
|
33
|
+
@transitions = Array.new
|
34
|
+
@history_states = Array.new
|
35
|
+
@history_target = Array.new
|
36
|
+
@history_state = nil
|
37
|
+
@history = false
|
38
|
+
@is_parallel = false
|
39
|
+
@scxml_state = false
|
40
|
+
@parallel_state = Array.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_from_scxml(filename)
|
44
|
+
source = File.new filename
|
45
|
+
Document.parse_stream(source, self)
|
46
|
+
@statemachine.reset
|
47
|
+
return @statemachine
|
48
|
+
end
|
49
|
+
|
50
|
+
# parses scxml directly from string parameter stringbuffer
|
51
|
+
def build_from_scxml_string(stringbuffer)
|
52
|
+
Document.parse_stream(stringbuffer, self)
|
53
|
+
@statemachine.reset
|
54
|
+
return @statemachine
|
55
|
+
end
|
56
|
+
|
57
|
+
def tag_start(name, attributes)
|
58
|
+
case name
|
59
|
+
when 'scxml'
|
60
|
+
if attributes['name']
|
61
|
+
@scxml_state = true
|
62
|
+
state = nil
|
63
|
+
@current_state = State.new
|
64
|
+
@current_state.id = attributes['name']
|
65
|
+
@current_state.initial = attributes['initial']
|
66
|
+
state = Statemachine::SuperstateBuilder.new(attributes['name'].to_sym, @subject, @statemachine)
|
67
|
+
if (@current_state.initial != nil)
|
68
|
+
state.startstate(@current_state.initial.to_sym)
|
69
|
+
end
|
70
|
+
@state.push(state)
|
71
|
+
end
|
72
|
+
when 'parallel'
|
73
|
+
@parallel = Statemachine::ParallelStateBuilder.new(attributes['id'].to_sym, @subject, @statemachine)
|
74
|
+
@is_parallel = true
|
75
|
+
# If there is a state that encapsulates the parallel state, change it to a superstate
|
76
|
+
if (not @state.empty? and @state.last.is_a? Statemachine::StateBuilder)
|
77
|
+
state = Statemachine::SuperstateBuilder.new(@state.last.subject.id, @state.last.subject.superstate, @state.last.subject.statemachine)
|
78
|
+
@state.pop # pops the old one
|
79
|
+
@state.push(state) # pushes the new one
|
80
|
+
end
|
81
|
+
when 'state'
|
82
|
+
@current_state = State.new
|
83
|
+
@current_state.id = attributes['id']
|
84
|
+
@current_state.initial = attributes['initial']
|
85
|
+
if (@state.empty?) # It is not a substate
|
86
|
+
if (@current_state.initial != nil) # AND it is a superstate
|
87
|
+
state = Statemachine::SuperstateBuilder.new(attributes['id'].to_sym, @subject, @statemachine)
|
88
|
+
state.startstate(@current_state.initial.to_sym)
|
89
|
+
else # AND it is a state
|
90
|
+
state = Statemachine::StateBuilder.new(attributes['id'].to_sym, @subject, @statemachine)
|
91
|
+
end
|
92
|
+
else # It is a substate
|
93
|
+
if (@current_state.initial != nil) # AND it is a superstate
|
94
|
+
state = Statemachine::SuperstateBuilder.new(attributes['id'].to_sym, @state.last.subject, @statemachine)
|
95
|
+
state.startstate(@current_state.initial.to_sym)
|
96
|
+
else # AND it is a subsubstate
|
97
|
+
if (@state.last.is_a? Statemachine::StateBuilder) # but it's parent is not a superstate yet
|
98
|
+
state = Statemachine::SuperstateBuilder.new(@state.last.subject.id, @state.last.subject.superstate, @state.last.subject.statemachine)
|
99
|
+
@state.pop # pops the old one
|
100
|
+
@state.push(state) # pushes the new one
|
101
|
+
if @is_parallel
|
102
|
+
@parallel_state.pop
|
103
|
+
@parallel_state.push(state)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
state = Statemachine::StateBuilder.new(attributes['id'].to_sym, @state.last.subject, @statemachine)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
@state.push(state)
|
110
|
+
@parallel_state.push(state) if @is_parallel
|
111
|
+
when 'transition'
|
112
|
+
@current_transition = Transition.new
|
113
|
+
@current_transition.event = attributes['event']
|
114
|
+
@current_transition.target = attributes['target']
|
115
|
+
if attributes['cond']
|
116
|
+
@current_transition.cond = attributes['cond']
|
117
|
+
else
|
118
|
+
@current_transition.cond = true
|
119
|
+
end
|
120
|
+
@transitions.push(@current_transition)
|
121
|
+
when 'onentry'
|
122
|
+
when 'onexit'
|
123
|
+
when 'history'
|
124
|
+
@history=true
|
125
|
+
@history_states.push(@state.last.subject.id)
|
126
|
+
@history_state = @state.last.subject.id
|
127
|
+
when 'log'
|
128
|
+
@actions.push(["log", attributes['expr']])
|
129
|
+
when 'send'
|
130
|
+
@actions.push(["send", attributes['target'], attributes['event']])
|
131
|
+
when 'invoke'
|
132
|
+
@actions.push(["invoke", attributes['src'].to_sym])
|
133
|
+
else
|
134
|
+
@current_element = name
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def tag_end(name)
|
139
|
+
case name
|
140
|
+
when 'parallel'
|
141
|
+
@statemachine.add_state(@parallel.subject)
|
142
|
+
@is_parallel = false
|
143
|
+
when 'state'
|
144
|
+
if (@state.last.is_a? Statemachine::SuperstateBuilder)
|
145
|
+
s = statemachine.get_state(@state.last.subject.id)
|
146
|
+
|
147
|
+
# Changing the state's id
|
148
|
+
if (s.id == @history_state)
|
149
|
+
s.id = (s.id.to_s + "_H").to_sym
|
150
|
+
s.default_history=@history_target.last.to_sym
|
151
|
+
@history_target.pop
|
152
|
+
end
|
153
|
+
|
154
|
+
# Adds the superstate's transitions to all its substates
|
155
|
+
@substate.each{|j|
|
156
|
+
if (s)
|
157
|
+
s1 = statemachine.get_state(j.subject.id)
|
158
|
+
s.transitions.each {|v,k|
|
159
|
+
if (s1)
|
160
|
+
s1.add(k)
|
161
|
+
end
|
162
|
+
}
|
163
|
+
end
|
164
|
+
}
|
165
|
+
end
|
166
|
+
# In case of parallel statemachines the outmost states will become parallel statemachines
|
167
|
+
# only considering parallel on a root level
|
168
|
+
|
169
|
+
if @parallel_state.size == 1 and @parallel.is_a? Statemachine::ParallelStateBuilder
|
170
|
+
statemachine_aux = Statemachine::Statemachine.new(@parallel_state.last.subject)
|
171
|
+
@substate.each do |j|
|
172
|
+
statemachine_aux.add_state(j.subject)
|
173
|
+
@statemachine.remove_state(j.subject)
|
174
|
+
end
|
175
|
+
statemachine_aux.reset
|
176
|
+
@parallel.subject.add_statemachine(statemachine_aux)
|
177
|
+
end
|
178
|
+
@substate.push(@state.last)
|
179
|
+
|
180
|
+
if (@state.size == 1 and not @scxml_state) or (@state.size == 2 and @scxml_state) or (@parallel_state.size == 1)
|
181
|
+
@substate = []
|
182
|
+
# TODO make this better. Too inefficient
|
183
|
+
while (!(@history_states.size == 0))
|
184
|
+
# change every transitions where @history_states.last was the target state to history_states.last+"_H"
|
185
|
+
# for every history state
|
186
|
+
@statemachine.states.each_value do |s|
|
187
|
+
s.transitions.each_value do |t|
|
188
|
+
if (t.destination_id == @history_states.last)
|
189
|
+
t.destination_id = (t.destination_id.to_s + "_H").to_s
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
@history_states.pop
|
194
|
+
end
|
195
|
+
end
|
196
|
+
@state.pop
|
197
|
+
@parallel_state.pop if @is_parallel
|
198
|
+
when 'transition'
|
199
|
+
if (@transitions.last.event == nil)
|
200
|
+
if @history
|
201
|
+
@history_target.push(@transitions.last.target)
|
202
|
+
@history = false
|
203
|
+
else
|
204
|
+
# TODO spontaneous transitions
|
205
|
+
end
|
206
|
+
else
|
207
|
+
if (@transitions.last.target != nil) # if it has a target state
|
208
|
+
@state.last.event(@transitions.last.event.to_sym, @transitions.last.target.to_sym, @actions, @transitions.last.cond)
|
209
|
+
else # it is its own target state
|
210
|
+
@state.last.event(@transitions.last.event.to_sym, @state.last.subject.id.to_sym, @actions, @transitions.last.cond)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
@actions=[]
|
214
|
+
@transitions.pop
|
215
|
+
when 'onentry'
|
216
|
+
@state.last.on_entry(@actions)
|
217
|
+
@actions=[]
|
218
|
+
when 'onexit'
|
219
|
+
@state.last.on_exit(@actions)
|
220
|
+
@actions=[]
|
221
|
+
when 'history'
|
222
|
+
@history = false
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def xmldecl(version, encoding, standalone)
|
227
|
+
end
|
228
|
+
end
|
data/spec/atm_spec.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe 'ATM' do
|
4
|
+
before (:each) do
|
5
|
+
|
6
|
+
@atm = Statemachine.build do
|
7
|
+
startstate :ocioso
|
8
|
+
superstate :operando do
|
9
|
+
state :esperando_senha do
|
10
|
+
event :senha, :senha_inserida
|
11
|
+
on_entry Proc.new{puts "Digite a senha"}
|
12
|
+
end
|
13
|
+
state :senha_inserida do
|
14
|
+
event :senha_errada, :esperando_senha, Proc.new {puts "Senha incorreta.";true}
|
15
|
+
event :senha_correta, :esperando_opcao
|
16
|
+
on_entry :verifica_senha
|
17
|
+
end
|
18
|
+
state :esperando_opcao do
|
19
|
+
event :opcao, :opcao_escolhida
|
20
|
+
on_entry Proc.new{puts "Digite a sua escolha"}
|
21
|
+
end
|
22
|
+
state :opcao_escolhida do
|
23
|
+
event :saldo, :exibindo_saldo
|
24
|
+
event :saque, :emitindo_quantia
|
25
|
+
event :invalida, :esperando_opcao
|
26
|
+
on_entry :verifica_escolha
|
27
|
+
end
|
28
|
+
state :exibindo_saldo do
|
29
|
+
event :nova_opcao, :esperando_opcao
|
30
|
+
on_entry :saldo
|
31
|
+
|
32
|
+
end
|
33
|
+
state :emitindo_quantia do
|
34
|
+
event :nova_opcao, :esperando_opcao
|
35
|
+
on_entry :emitindo
|
36
|
+
end
|
37
|
+
|
38
|
+
event :cancelar, :ocioso, Proc.new {puts "Saindo...";true}
|
39
|
+
end
|
40
|
+
|
41
|
+
state :ocioso do
|
42
|
+
event :cartao, :esperando_senha
|
43
|
+
event :cancelar, :ocioso
|
44
|
+
end
|
45
|
+
stub_context :verbose => true # this is an nternal verbose stub context from statemachine that prints out action invocations.
|
46
|
+
end
|
47
|
+
|
48
|
+
# uncomment the next line to start testing your code
|
49
|
+
# @atm = Statemachine.build_from_scxml "testmachines/atm_enhanced.xml"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should start with the correct state >ocioso<" do
|
53
|
+
@atm.state.should equal(:ocioso)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should support transitions" do
|
57
|
+
@atm.cartao
|
58
|
+
@atm.state.should==:esperando_senha
|
59
|
+
@atm.senha
|
60
|
+
@atm.state.should==:senha_inserida
|
61
|
+
@atm.senha_errada
|
62
|
+
@atm.state.should==:esperando_senha
|
63
|
+
@atm.senha
|
64
|
+
@atm.senha_correta
|
65
|
+
@atm.opcao
|
66
|
+
@atm.state.should==:opcao_escolhida
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|