MINT-statemachine 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGES +135 -0
  2. data/LICENSE +16 -0
  3. data/MINT-statemachine.gemspec +27 -0
  4. data/README.rdoc +69 -0
  5. data/Rakefile +88 -0
  6. data/TODO +2 -0
  7. data/lib/statemachine.rb +26 -0
  8. data/lib/statemachine/action_invokation.rb +83 -0
  9. data/lib/statemachine/builder.rb +383 -0
  10. data/lib/statemachine/generate/dot_graph.rb +1 -0
  11. data/lib/statemachine/generate/dot_graph/dot_graph_statemachine.rb +127 -0
  12. data/lib/statemachine/generate/java.rb +1 -0
  13. data/lib/statemachine/generate/java/java_statemachine.rb +265 -0
  14. data/lib/statemachine/generate/src_builder.rb +48 -0
  15. data/lib/statemachine/generate/util.rb +50 -0
  16. data/lib/statemachine/parallelstate.rb +196 -0
  17. data/lib/statemachine/state.rb +102 -0
  18. data/lib/statemachine/statemachine.rb +279 -0
  19. data/lib/statemachine/stub_context.rb +26 -0
  20. data/lib/statemachine/superstate.rb +53 -0
  21. data/lib/statemachine/transition.rb +76 -0
  22. data/lib/statemachine/version.rb +17 -0
  23. data/spec/action_invokation_spec.rb +101 -0
  24. data/spec/builder_spec.rb +243 -0
  25. data/spec/default_transition_spec.rb +111 -0
  26. data/spec/generate/dot_graph/dot_graph_stagemachine_spec.rb +27 -0
  27. data/spec/generate/java/java_statemachine_spec.rb +349 -0
  28. data/spec/history_spec.rb +107 -0
  29. data/spec/noodle.rb +23 -0
  30. data/spec/sm_action_parameterization_spec.rb +99 -0
  31. data/spec/sm_activation_spec.rb +116 -0
  32. data/spec/sm_entry_exit_actions_spec.rb +99 -0
  33. data/spec/sm_odds_n_ends_spec.rb +67 -0
  34. data/spec/sm_parallel_state_spec.rb +207 -0
  35. data/spec/sm_simple_spec.rb +26 -0
  36. data/spec/sm_super_state_spec.rb +55 -0
  37. data/spec/sm_turnstile_spec.rb +76 -0
  38. data/spec/spec_helper.rb +121 -0
  39. data/spec/transition_spec.rb +107 -0
  40. metadata +115 -0
data/CHANGES ADDED
@@ -0,0 +1,135 @@
1
+ = Statemachine Changelog
2
+
3
+ == Version 1.2.2
4
+
5
+ * Transitions can fail
6
+
7
+ == Version 1.2.1
8
+
9
+ * Multiple actions
10
+
11
+ Instead of a single action, multiple actions can be defined for a transition
12
+ by using an array.
13
+
14
+ * Redefinition of states without loosing transitions
15
+
16
+ In a statemachine definition you can pass another statemachine and replace for the
17
+ new statemachine a state with a superstate without loosing the original transitions.
18
+
19
+ Each action that is called during a transaction has to return true for the transition to suceed.
20
+ Otherwise the entire transition is assumed as failed and the statemachine remains in its origin
21
+ state.
22
+
23
+ * Support for GemBundler
24
+
25
+ rake make_spec can be used to create a gemspec file that is required for GemBundler
26
+ integration.
27
+
28
+ == Version 1.1.0
29
+
30
+ DotGraph
31
+ * DotGraph generator was added to generate graphs of statemachines using Omnigraffle.
32
+ * Fixed bug in Java generator where Statenames where not formated correctly.
33
+
34
+ == Version 1.0.0
35
+
36
+ Generator
37
+ * Java generator was added. Statemachines defined in the Ruby DSL can generate Java code.
38
+
39
+ == Version 0.4.2
40
+
41
+ Simple Fixes
42
+ * Fixed respond_to? to handle the, what should be impossible, case when the state is nil
43
+ * Switch history members variable to store id rather than object.
44
+
45
+ == Version 0.4.1
46
+
47
+ Simple Fixes
48
+ * Fixed priority of default transitions, self defaults first, then superstate defaults.
49
+
50
+ == Version 0.4.0
51
+
52
+ Feature enhancements
53
+ * enabled nested superstate history
54
+ * TransitionMissingException's are raised when the statemachine can't respond to an event
55
+ * Statmachine overrides respond_to? to respond to valid events.
56
+
57
+ Behavior Fixes
58
+ * fixed default transition so that superstate transitions have priority over default
59
+
60
+ == Version 0.3.0
61
+
62
+ Feature enhancements
63
+ * added default transitions
64
+ * added default history for superstates
65
+ * the context method in the builder will set the context's statemachine variable if the context respond_to?(:statemachine=)
66
+
67
+ Behavior Fixes
68
+ * the entry action of the startstate is called when the statemachine starts or is reset.
69
+ * resetting the statemachine will reset the history state for each superstate.
70
+
71
+ == Version 0.2.2
72
+
73
+ Minor plugin update
74
+ * introduced before_event and after_event hooks for controllers
75
+
76
+ == Version 0.2.1
77
+
78
+ Rails Plugin.
79
+ * Rails plugin introduced
80
+
81
+ == Version 0.2.0
82
+
83
+ Separation of logic from behavior.
84
+ * Prefered builder syntax implemented
85
+ * statemachine have a context which defines all the behavior
86
+ * startstate can be set at any time in the builder
87
+ * states can be declared without blocks
88
+ * context can be set in builder
89
+
90
+ == Version 0.1.0
91
+
92
+ A new way to build the statemachines
93
+ * cleaner API for running a statemachine
94
+ * much refactoring
95
+ * new API for building statemachine
96
+ * process_event accepts strings
97
+
98
+ == Version 0.0.4
99
+
100
+ Some minor improvements
101
+ * Proper handling of state transition implemented, such that the proper state is set for entry and exit actions.
102
+ * can now use State objects in addition to symbols while creating a transition
103
+ * more compliant implementation of history state
104
+
105
+ == Version 0.0.3
106
+
107
+ Bug fix dealing with entry and exit actions. The state machine's state need to be set to the entered/exited state before calling the
108
+ exit/entry action.
109
+ * added a couple specs in the exit_entry_spec
110
+ * modified state.entered/exited methods to set the state
111
+ * modifed the StateMachine.state to accept state objects.
112
+ * removed running attribute from StateMachine because it wasn't much use
113
+ * also removed the nil (end state)
114
+
115
+ == Version 0.0.2
116
+
117
+ More conventional file structure
118
+ * nothing much to report in terms of changes.
119
+
120
+ == Version 0.0.1
121
+
122
+ 0.0.0 didn't seem to work as a gem so maybe this one will.
123
+
124
+ * nothing really, just playing with rake and release configuration
125
+
126
+ == Version 0.0.0
127
+
128
+ The first release. Most finite state machine features are implemented
129
+ * states
130
+ * transitions
131
+ * transition actions
132
+ * super states
133
+ * entry actions
134
+ * exit actions
135
+ * history state
data/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ Copyright (C) 2010,2011 Sebastian Feuerstack, Jessica Colnago
2
+ Copyright (C) 2006-2010 Micah Martin
3
+
4
+ This library is free software; you can redistribute it and/or
5
+ modify it under the terms of the GNU Lesser General Public
6
+ License as published by the Free Software Foundation; either
7
+ version 2.1 of the License, or (at your option) any later version.
8
+
9
+ This library is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ Lesser General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Lesser General Public
15
+ License along with this library; if not, write to the Free Software
16
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{MINT-statemachine}
5
+ s.version = "1.2.2"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = [%q{Sebastian Feuerstack}]
9
+ s.date = %q{2011-06-30}
10
+ s.description = %q{The MINT Statemachine is a ruby library for building Finite State Machines, based on the Statemachine gem by Micah Martin.}
11
+ s.email = %q{Sebastian@Feuerstack.org}
12
+ s.files = [%q{Rakefile}, %q{README.rdoc}, %q{CHANGES}, %q{TODO}, %q{LICENSE}, %q{lib/statemachine/generate/java/java_statemachine.rb}, %q{lib/statemachine/generate/src_builder.rb}, %q{lib/statemachine/generate/java.rb}, %q{lib/statemachine/generate/dot_graph.rb}, %q{lib/statemachine/generate/util.rb}, %q{lib/statemachine/generate/dot_graph/dot_graph_statemachine.rb}, %q{lib/statemachine/transition.rb}, %q{lib/statemachine/superstate.rb}, %q{lib/statemachine/version.rb}, %q{lib/statemachine/statemachine.rb}, %q{lib/statemachine/stub_context.rb}, %q{lib/statemachine/state.rb}, %q{lib/statemachine/parallelstate.rb}, %q{lib/statemachine/action_invokation.rb}, %q{lib/statemachine/builder.rb}, %q{lib/statemachine.rb}, %q{spec/sm_turnstile_spec.rb}, %q{spec/generate/java/java_statemachine_spec.rb}, %q{spec/generate/dot_graph/dot_graph_stagemachine_spec.rb}, %q{spec/sm_odds_n_ends_spec.rb}, %q{spec/noodle.rb}, %q{spec/sm_entry_exit_actions_spec.rb}, %q{spec/default_transition_spec.rb}, %q{spec/action_invokation_spec.rb}, %q{spec/sm_parallel_state_spec.rb}, %q{spec/builder_spec.rb}, %q{spec/sm_activation_spec.rb}, %q{spec/sm_super_state_spec.rb}, %q{spec/transition_spec.rb}, %q{spec/spec_helper.rb}, %q{spec/sm_simple_spec.rb}, %q{spec/sm_action_parameterization_spec.rb}, %q{spec/history_spec.rb}]
13
+ s.homepage = %q{http://www.multi-access.de}
14
+ s.require_paths = [%q{lib}]
15
+ s.rubygems_version = %q{1.8.5}
16
+ s.summary = %q{MINT-Statemachine-1.2.2 - Statemachine Library for Ruby based on statemachine from http://slagyr.github.com/statemachine http://www.multi-access.de/open-source-software/third-party-software-extensions/}
17
+ s.test_files = [%q{spec/sm_turnstile_spec.rb}, %q{spec/sm_odds_n_ends_spec.rb}, %q{spec/sm_entry_exit_actions_spec.rb}, %q{spec/default_transition_spec.rb}, %q{spec/action_invokation_spec.rb}, %q{spec/sm_parallel_state_spec.rb}, %q{spec/builder_spec.rb}, %q{spec/sm_activation_spec.rb}, %q{spec/sm_super_state_spec.rb}, %q{spec/transition_spec.rb}, %q{spec/sm_simple_spec.rb}, %q{spec/sm_action_parameterization_spec.rb}, %q{spec/history_spec.rb}]
18
+
19
+ if s.respond_to? :specification_version then
20
+ s.specification_version = 3
21
+
22
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
23
+ else
24
+ end
25
+ else
26
+ end
27
+ end
data/README.rdoc ADDED
@@ -0,0 +1,69 @@
1
+ = MINT Statemachine Gem extensions
2
+
3
+ This branch contains extensions that we implemented as part of the MINT project
4
+ to run multimodal applications.
5
+
6
+ It is based on the great Statemachine Ruby Library, which enables simple creation
7
+ of full-features Finite Statemachines that has been originally developed by Micah Martin.
8
+
9
+ To get started, please look at the documentation on the Statemachine website:
10
+ http://slagyr.github.com/statemachine
11
+
12
+ == Changes
13
+
14
+ === Multiple actions
15
+
16
+ Instead of a single action, multiple actions can be defined for a transition by using an
17
+ array.
18
+
19
+ sm = Statemachine.build do |smb|
20
+ smb.trans :cold, :fire, :hot, [:cook, Proc.new { @tasty = true;true }, "@shape = 'fettucini'"]
21
+ end
22
+
23
+ === Redefinition of states without loosing transitions
24
+
25
+ In a statemachine definition you can pass another statemachine and replace for the
26
+ new statemachine a state with a superstate without loosing the original transitions.
27
+
28
+ In this example the state :unlocked of @old_sm gets replaced by a super state.
29
+
30
+ @sm = Statemachine.build @old_sm do
31
+ superstate :unlocked do
32
+ trans :u1, :u, :u2
33
+ trans :u2, :e, :maintenance
34
+ end
35
+ end
36
+
37
+ === Transitions can fail
38
+
39
+ Each action that is called during a transaction has to return true for the transition to suceed.
40
+ Otherwise the entire transition is assumed as failed and the statemachine remains in its origin
41
+ state.
42
+
43
+ === Support for GemBundler
44
+
45
+ rake make_spec can be used to create a gemspec file that is required for GemBundler
46
+ integration.
47
+
48
+ == Project website
49
+
50
+ http://www.multi-access.de
51
+
52
+ == License
53
+
54
+ Copyright (C) 2010,2011 Sebastian Feuerstack, Jessica Colnago
55
+ Copyright (C) 2006-2010 Micah Martin
56
+
57
+ This library is free software; you can redistribute it and/or
58
+ modify it under the terms of the GNU Lesser General Public
59
+ License as published by the Free Software Foundation; either
60
+ version 2.1 of the License, or (at your option) any later version.
61
+
62
+ This library is distributed in the hope that it will be useful,
63
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
64
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
65
+ Lesser General Public License for more details.
66
+
67
+ You should have received a copy of the GNU Lesser General Public
68
+ License along with this library; if not, write to the Free Software
69
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
data/Rakefile ADDED
@@ -0,0 +1,88 @@
1
+ $:.unshift('lib')
2
+ require 'rubygems'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/clean'
5
+ require 'rake/rdoctask'
6
+ require 'spec/rake/spectask'
7
+ require 'statemachine'
8
+
9
+ PKG_NAME = "MINT-statemachine"
10
+ PKG_VERSION = Statemachine::VERSION::STRING
11
+ PKG_TAG = Statemachine::VERSION::TAG
12
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
13
+ PKG_FILES = FileList[
14
+ '[A-Z]*',
15
+ 'lib/**/*.rb',
16
+ 'spec/**/*.rb'
17
+ ]
18
+
19
+ task :default => :spec
20
+
21
+ desc "Run all specs"
22
+ Spec::Rake::SpecTask.new do |t|
23
+ t.spec_files = FileList['spec/**/*_spec.rb']
24
+ end
25
+
26
+ desc 'Generate RDoc'
27
+ rd = Rake::RDocTask.new do |rdoc|
28
+ rdoc.options << '--title' << 'Statemachine' << '--line-numbers' << '--inline-source' << '--main' << 'README.rdoc'
29
+ rdoc.rdoc_files.include('README.rdoc', 'CHANGES', 'lib/**/*.rb')
30
+ end
31
+ task :rdoc
32
+
33
+ spec = Gem::Specification.new do |s|
34
+ s.name = PKG_NAME
35
+ s.version = PKG_VERSION
36
+ s.summary = Statemachine::VERSION::DESCRIPTION
37
+ s.description = "The MINT Statemachine is a ruby library for building Finite State Machines, based on the Statemachine gem by Micah Martin."
38
+ s.files = PKG_FILES.to_a
39
+ s.require_path = 'lib'
40
+ s.test_files = Dir.glob('spec/*_spec.rb')
41
+ s.require_path = 'lib'
42
+ s.author = "Sebastian Feuerstack"
43
+ s.email = "Sebastian@Feuerstack.org"
44
+ s.homepage = "http://www.multi-access.de"
45
+ end
46
+
47
+ Rake::GemPackageTask.new(spec) do |pkg|
48
+ pkg.need_zip = true
49
+ pkg.need_tar = true
50
+ end
51
+
52
+ def egrep(pattern)
53
+ Dir['**/*.rb'].each do |fn|
54
+ count = 0
55
+ open(fn) do |f|
56
+ while line = f.gets
57
+ count += 1
58
+ if line =~ pattern
59
+ puts "#{fn}:#{count}:#{line}"
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ desc "create a gemspec file"
67
+ task :make_spec do
68
+ File.open("#{PKG_NAME}.gemspec", "w") do |file|
69
+ file.puts spec.to_ruby
70
+ end
71
+ end
72
+
73
+ desc "Look for TODO and FIXME tags in the code"
74
+ task :todo do
75
+ egrep /(FIXME|TODO|TBD)/
76
+ end
77
+
78
+ task :release => [:clobber, :verify_committed, :verify_user, :verify_password, :spec, :publish_packages, :tag, :publish_website, :publish_news]
79
+
80
+ desc "Verifies that there is no uncommitted code"
81
+ task :verify_committed do
82
+ IO.popen('svn stat') do |io|
83
+ io.each_line do |line|
84
+ raise "\n!!! Do a svn commit first !!!\n\n" if line =~ /^\s*M\s*/
85
+ end
86
+ end
87
+ end
88
+
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ Maybe:
2
+ Implement superstate endstate with automatic transition
@@ -0,0 +1,26 @@
1
+ #--
2
+ # Copyright (C) 2006 Micah Martin
3
+ #
4
+ # This library is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU Lesser General Public
6
+ # License as published by the Free Software Foundation; either
7
+ # version 2.1 of the License, or (at your option) any later version.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+ #++
18
+
19
+ require 'statemachine/action_invokation'
20
+ require 'statemachine/state'
21
+ require 'statemachine/superstate'
22
+ require 'statemachine/parallelstate'
23
+ require 'statemachine/transition'
24
+ require 'statemachine/statemachine'
25
+ require 'statemachine/builder'
26
+ require 'statemachine/version'
@@ -0,0 +1,83 @@
1
+ module Statemachine
2
+
3
+ module ActionInvokation #:nodoc:
4
+
5
+ def invoke_action(action, args, message, messenger, message_queue)
6
+ if !(action.is_a? Array)
7
+ action = [action]
8
+ end
9
+ result = true
10
+ action.each {|a|
11
+ if a.is_a? Symbol
12
+ result = invoke_method(a, args, message)
13
+ elsif a.is_a? Proc
14
+ result = invoke_proc(a, args, message)
15
+ elsif a.is_a? Array
16
+ result = send(a[0],a[1])
17
+ else
18
+ log("#{a}")
19
+ result =invoke_string(a) if not messenger
20
+ end
21
+ return false if result ==false
22
+ }
23
+ result
24
+ end
25
+
26
+ private
27
+
28
+ def send(target,event)
29
+ @message_queue.send(target, event) if @message_queue
30
+ end
31
+
32
+ def log(message)
33
+ @messenger.puts message if @messenger
34
+ end
35
+
36
+ def invoke_method(symbol, args, message)
37
+ method = @context.method(symbol)
38
+ raise StatemachineException.new("No method '#{symbol}' for context. " + message) if not method
39
+
40
+ parameters = params_for_block(method, args, message)
41
+ method.call(*parameters)
42
+ end
43
+
44
+ def invoke_proc(proc, args, message)
45
+ parameters = params_for_block(proc, args, message)
46
+ @context.instance_exec(*parameters, &proc)
47
+ end
48
+
49
+ def invoke_string(expression)
50
+ @context.instance_eval(expression)
51
+ end
52
+
53
+ def params_for_block(block, args, message)
54
+ arity = block.arity
55
+ required_params = arity < 0 ? arity.abs - 1 : arity
56
+
57
+ raise StatemachineException.new("Insufficient parameters. (#{message})") if required_params > args.length
58
+
59
+ return arity < 0 ? args : args[0...arity]
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
66
+ class Object
67
+
68
+ module InstanceExecHelper; end
69
+
70
+ include InstanceExecHelper
71
+
72
+ def instance_exec(*args, &block) # !> method redefined; discarding old instance_exec
73
+ mname = "__instance_exec_#{Thread.current.object_id.abs}_#{object_id.abs}"
74
+ InstanceExecHelper.module_eval{ define_method(mname, &block) }
75
+ begin
76
+ ret = send(mname, *args)
77
+ ensure
78
+ InstanceExecHelper.module_eval{ undef_method(mname) } rescue nil
79
+ end
80
+ ret
81
+ end
82
+
83
+ end