ruote-maestrodev 2.2.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.
Files changed (265) hide show
  1. data/CHANGELOG.txt +290 -0
  2. data/CREDITS.txt +99 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.rdoc +88 -0
  5. data/Rakefile +108 -0
  6. data/TODO.txt +488 -0
  7. data/lib/ruote.rb +7 -0
  8. data/lib/ruote/context.rb +194 -0
  9. data/lib/ruote/engine.rb +1062 -0
  10. data/lib/ruote/engine/process_error.rb +122 -0
  11. data/lib/ruote/engine/process_status.rb +448 -0
  12. data/lib/ruote/exp/command.rb +87 -0
  13. data/lib/ruote/exp/commanded.rb +69 -0
  14. data/lib/ruote/exp/condition.rb +227 -0
  15. data/lib/ruote/exp/fe_add_branches.rb +138 -0
  16. data/lib/ruote/exp/fe_apply.rb +154 -0
  17. data/lib/ruote/exp/fe_cancel_process.rb +78 -0
  18. data/lib/ruote/exp/fe_command.rb +156 -0
  19. data/lib/ruote/exp/fe_concurrence.rb +321 -0
  20. data/lib/ruote/exp/fe_concurrent_iterator.rb +219 -0
  21. data/lib/ruote/exp/fe_cron.rb +141 -0
  22. data/lib/ruote/exp/fe_cursor.rb +324 -0
  23. data/lib/ruote/exp/fe_define.rb +112 -0
  24. data/lib/ruote/exp/fe_echo.rb +60 -0
  25. data/lib/ruote/exp/fe_equals.rb +115 -0
  26. data/lib/ruote/exp/fe_error.rb +82 -0
  27. data/lib/ruote/exp/fe_filter.rb +648 -0
  28. data/lib/ruote/exp/fe_forget.rb +88 -0
  29. data/lib/ruote/exp/fe_given.rb +154 -0
  30. data/lib/ruote/exp/fe_if.rb +127 -0
  31. data/lib/ruote/exp/fe_inc.rb +205 -0
  32. data/lib/ruote/exp/fe_iterator.rb +234 -0
  33. data/lib/ruote/exp/fe_let.rb +75 -0
  34. data/lib/ruote/exp/fe_listen.rb +304 -0
  35. data/lib/ruote/exp/fe_lose.rb +110 -0
  36. data/lib/ruote/exp/fe_noop.rb +45 -0
  37. data/lib/ruote/exp/fe_once.rb +215 -0
  38. data/lib/ruote/exp/fe_participant.rb +287 -0
  39. data/lib/ruote/exp/fe_read.rb +69 -0
  40. data/lib/ruote/exp/fe_redo.rb +82 -0
  41. data/lib/ruote/exp/fe_ref.rb +152 -0
  42. data/lib/ruote/exp/fe_registerp.rb +110 -0
  43. data/lib/ruote/exp/fe_reserve.rb +126 -0
  44. data/lib/ruote/exp/fe_restore.rb +102 -0
  45. data/lib/ruote/exp/fe_save.rb +72 -0
  46. data/lib/ruote/exp/fe_sequence.rb +59 -0
  47. data/lib/ruote/exp/fe_set.rb +154 -0
  48. data/lib/ruote/exp/fe_subprocess.rb +211 -0
  49. data/lib/ruote/exp/fe_that.rb +92 -0
  50. data/lib/ruote/exp/fe_undo.rb +67 -0
  51. data/lib/ruote/exp/fe_unregisterp.rb +69 -0
  52. data/lib/ruote/exp/fe_wait.rb +95 -0
  53. data/lib/ruote/exp/flowexpression.rb +886 -0
  54. data/lib/ruote/exp/iterator.rb +81 -0
  55. data/lib/ruote/exp/merge.rb +118 -0
  56. data/lib/ruote/exp/ro_attributes.rb +212 -0
  57. data/lib/ruote/exp/ro_filters.rb +136 -0
  58. data/lib/ruote/exp/ro_persist.rb +154 -0
  59. data/lib/ruote/exp/ro_variables.rb +189 -0
  60. data/lib/ruote/exp/ro_vf.rb +68 -0
  61. data/lib/ruote/fei.rb +260 -0
  62. data/lib/ruote/id/mnemo_wfid_generator.rb +43 -0
  63. data/lib/ruote/id/wfid_generator.rb +81 -0
  64. data/lib/ruote/log/default_history.rb +122 -0
  65. data/lib/ruote/log/pretty.rb +176 -0
  66. data/lib/ruote/log/storage_history.rb +159 -0
  67. data/lib/ruote/log/test_logger.rb +208 -0
  68. data/lib/ruote/log/wait_logger.rb +64 -0
  69. data/lib/ruote/part/block_participant.rb +137 -0
  70. data/lib/ruote/part/code_participant.rb +81 -0
  71. data/lib/ruote/part/engine_participant.rb +189 -0
  72. data/lib/ruote/part/local_participant.rb +138 -0
  73. data/lib/ruote/part/no_op_participant.rb +60 -0
  74. data/lib/ruote/part/null_participant.rb +54 -0
  75. data/lib/ruote/part/rev_participant.rb +169 -0
  76. data/lib/ruote/part/smtp_participant.rb +116 -0
  77. data/lib/ruote/part/storage_participant.rb +392 -0
  78. data/lib/ruote/part/template.rb +84 -0
  79. data/lib/ruote/participant.rb +7 -0
  80. data/lib/ruote/reader.rb +278 -0
  81. data/lib/ruote/reader/json.rb +49 -0
  82. data/lib/ruote/reader/radial.rb +290 -0
  83. data/lib/ruote/reader/ruby_dsl.rb +186 -0
  84. data/lib/ruote/reader/xml.rb +99 -0
  85. data/lib/ruote/receiver/base.rb +212 -0
  86. data/lib/ruote/storage/base.rb +364 -0
  87. data/lib/ruote/storage/composite_storage.rb +121 -0
  88. data/lib/ruote/storage/fs_storage.rb +139 -0
  89. data/lib/ruote/storage/hash_storage.rb +211 -0
  90. data/lib/ruote/svc/dispatch_pool.rb +158 -0
  91. data/lib/ruote/svc/dollar_sub.rb +298 -0
  92. data/lib/ruote/svc/error_handler.rb +138 -0
  93. data/lib/ruote/svc/expression_map.rb +97 -0
  94. data/lib/ruote/svc/participant_list.rb +397 -0
  95. data/lib/ruote/svc/tracker.rb +172 -0
  96. data/lib/ruote/svc/treechecker.rb +141 -0
  97. data/lib/ruote/tree_dot.rb +85 -0
  98. data/lib/ruote/util/filter.rb +525 -0
  99. data/lib/ruote/util/hashdot.rb +79 -0
  100. data/lib/ruote/util/look.rb +128 -0
  101. data/lib/ruote/util/lookup.rb +127 -0
  102. data/lib/ruote/util/misc.rb +167 -0
  103. data/lib/ruote/util/ometa.rb +71 -0
  104. data/lib/ruote/util/serializer.rb +103 -0
  105. data/lib/ruote/util/subprocess.rb +88 -0
  106. data/lib/ruote/util/time.rb +100 -0
  107. data/lib/ruote/util/tree.rb +58 -0
  108. data/lib/ruote/version.rb +29 -0
  109. data/lib/ruote/worker.rb +386 -0
  110. data/lib/ruote/workitem.rb +394 -0
  111. data/phil.txt +14 -0
  112. data/ruote.gemspec +44 -0
  113. data/test/bm/ci.rb +55 -0
  114. data/test/bm/ici.rb +71 -0
  115. data/test/bm/juuman.rb +54 -0
  116. data/test/bm/launch_bench.rb +37 -0
  117. data/test/bm/load_26c.rb +97 -0
  118. data/test/bm/mega.rb +64 -0
  119. data/test/bm/seq_thousand.rb +31 -0
  120. data/test/bm/t.rb +35 -0
  121. data/test/functional/base.rb +247 -0
  122. data/test/functional/concurrent_base.rb +98 -0
  123. data/test/functional/crunner.rb +31 -0
  124. data/test/functional/ct_0_concurrence.rb +65 -0
  125. data/test/functional/ct_1_iterator.rb +67 -0
  126. data/test/functional/ct_2_cancel.rb +81 -0
  127. data/test/functional/eft_0_process_definition.rb +65 -0
  128. data/test/functional/eft_10_cancel_process.rb +46 -0
  129. data/test/functional/eft_11_wait.rb +109 -0
  130. data/test/functional/eft_12_listen.rb +500 -0
  131. data/test/functional/eft_13_iterator.rb +342 -0
  132. data/test/functional/eft_14_cursor.rb +456 -0
  133. data/test/functional/eft_15_loop.rb +69 -0
  134. data/test/functional/eft_16_if.rb +183 -0
  135. data/test/functional/eft_17_equals.rb +55 -0
  136. data/test/functional/eft_18_concurrent_iterator.rb +410 -0
  137. data/test/functional/eft_19_reserve.rb +136 -0
  138. data/test/functional/eft_1_echo.rb +68 -0
  139. data/test/functional/eft_20_save.rb +116 -0
  140. data/test/functional/eft_21_restore.rb +61 -0
  141. data/test/functional/eft_22_noop.rb +28 -0
  142. data/test/functional/eft_23_apply.rb +168 -0
  143. data/test/functional/eft_24_add_branches.rb +98 -0
  144. data/test/functional/eft_25_command.rb +28 -0
  145. data/test/functional/eft_26_error.rb +77 -0
  146. data/test/functional/eft_27_inc.rb +280 -0
  147. data/test/functional/eft_28_once.rb +135 -0
  148. data/test/functional/eft_29_cron.rb +64 -0
  149. data/test/functional/eft_2_sequence.rb +58 -0
  150. data/test/functional/eft_30_ref.rb +155 -0
  151. data/test/functional/eft_31_registerp.rb +130 -0
  152. data/test/functional/eft_32_lose.rb +93 -0
  153. data/test/functional/eft_33_let.rb +31 -0
  154. data/test/functional/eft_34_given.rb +123 -0
  155. data/test/functional/eft_35_filter.rb +375 -0
  156. data/test/functional/eft_36_read.rb +95 -0
  157. data/test/functional/eft_3_participant.rb +149 -0
  158. data/test/functional/eft_4_set.rb +296 -0
  159. data/test/functional/eft_5_subprocess.rb +163 -0
  160. data/test/functional/eft_6_concurrence.rb +304 -0
  161. data/test/functional/eft_7_forget.rb +61 -0
  162. data/test/functional/eft_8_undo.rb +114 -0
  163. data/test/functional/eft_9_redo.rb +138 -0
  164. data/test/functional/ft_0_worker.rb +65 -0
  165. data/test/functional/ft_10_dollar.rb +304 -0
  166. data/test/functional/ft_11_recursion.rb +109 -0
  167. data/test/functional/ft_12_launchitem.rb +43 -0
  168. data/test/functional/ft_13_variables.rb +151 -0
  169. data/test/functional/ft_14_re_apply.rb +324 -0
  170. data/test/functional/ft_15_timeout.rb +226 -0
  171. data/test/functional/ft_16_participant_params.rb +98 -0
  172. data/test/functional/ft_17_conditional.rb +102 -0
  173. data/test/functional/ft_18_kill.rb +138 -0
  174. data/test/functional/ft_19_participant_code.rb +67 -0
  175. data/test/functional/ft_1_process_status.rb +796 -0
  176. data/test/functional/ft_20_storage_participant.rb +543 -0
  177. data/test/functional/ft_21_forget.rb +153 -0
  178. data/test/functional/ft_22_process_definitions.rb +90 -0
  179. data/test/functional/ft_23_load_defs.rb +79 -0
  180. data/test/functional/ft_24_block_participant.rb +235 -0
  181. data/test/functional/ft_25_receiver.rb +207 -0
  182. data/test/functional/ft_26_participant_rtimeout.rb +179 -0
  183. data/test/functional/ft_27_var_indirection.rb +128 -0
  184. data/test/functional/ft_28_null_noop_participants.rb +51 -0
  185. data/test/functional/ft_29_part_template.rb +60 -0
  186. data/test/functional/ft_2_errors.rb +380 -0
  187. data/test/functional/ft_30_smtp_participant.rb +122 -0
  188. data/test/functional/ft_31_part_blocking.rb +72 -0
  189. data/test/functional/ft_33_participant_subprocess_priority.rb +32 -0
  190. data/test/functional/ft_34_cursor_rewind.rb +101 -0
  191. data/test/functional/ft_35_add_service.rb +56 -0
  192. data/test/functional/ft_36_storage_history.rb +150 -0
  193. data/test/functional/ft_37_default_history.rb +109 -0
  194. data/test/functional/ft_38_participant_more.rb +193 -0
  195. data/test/functional/ft_39_wait_for.rb +136 -0
  196. data/test/functional/ft_3_participant_registration.rb +574 -0
  197. data/test/functional/ft_40_wait_logger.rb +62 -0
  198. data/test/functional/ft_41_participants.rb +91 -0
  199. data/test/functional/ft_42_storage_copy.rb +71 -0
  200. data/test/functional/ft_43_participant_on_reply.rb +87 -0
  201. data/test/functional/ft_44_var_participant.rb +35 -0
  202. data/test/functional/ft_45_participant_accept.rb +64 -0
  203. data/test/functional/ft_46_launch_single.rb +83 -0
  204. data/test/functional/ft_47_wfid_generator.rb +54 -0
  205. data/test/functional/ft_48_lose.rb +112 -0
  206. data/test/functional/ft_49_engine_on_error.rb +201 -0
  207. data/test/functional/ft_4_cancel.rb +132 -0
  208. data/test/functional/ft_50_engine_config.rb +22 -0
  209. data/test/functional/ft_51_misc.rb +67 -0
  210. data/test/functional/ft_52_case.rb +134 -0
  211. data/test/functional/ft_53_engine_on_terminate.rb +95 -0
  212. data/test/functional/ft_54_patterns.rb +104 -0
  213. data/test/functional/ft_55_engine_participant.rb +303 -0
  214. data/test/functional/ft_56_filter_attribute.rb +259 -0
  215. data/test/functional/ft_57_rev_participant.rb +252 -0
  216. data/test/functional/ft_58_workitem.rb +69 -0
  217. data/test/functional/ft_59_pause.rb +343 -0
  218. data/test/functional/ft_5_on_error.rb +384 -0
  219. data/test/functional/ft_60_code_participant.rb +45 -0
  220. data/test/functional/ft_61_trailing_fields.rb +34 -0
  221. data/test/functional/ft_62_exp_name_and_dollar_substitution.rb +35 -0
  222. data/test/functional/ft_6_on_cancel.rb +221 -0
  223. data/test/functional/ft_7_tags.rb +177 -0
  224. data/test/functional/ft_8_participant_consumption.rb +124 -0
  225. data/test/functional/ft_9_subprocesses.rb +146 -0
  226. data/test/functional/restart_base.rb +34 -0
  227. data/test/functional/rt_0_wait.rb +55 -0
  228. data/test/functional/rt_1_listen.rb +56 -0
  229. data/test/functional/rt_2_errors.rb +56 -0
  230. data/test/functional/rt_3_once.rb +70 -0
  231. data/test/functional/rt_4_cron.rb +64 -0
  232. data/test/functional/rt_5_timeout.rb +60 -0
  233. data/test/functional/rtest.rb +8 -0
  234. data/test/functional/storage_helper.rb +93 -0
  235. data/test/functional/test.rb +44 -0
  236. data/test/functional/vertical.rb +46 -0
  237. data/test/path_helper.rb +15 -0
  238. data/test/test.rb +13 -0
  239. data/test/test_helper.rb +28 -0
  240. data/test/unit/storage.rb +428 -0
  241. data/test/unit/storages.rb +37 -0
  242. data/test/unit/test.rb +28 -0
  243. data/test/unit/ut_0_ruby_reader.rb +223 -0
  244. data/test/unit/ut_11_lookup.rb +122 -0
  245. data/test/unit/ut_13_serializer.rb +65 -0
  246. data/test/unit/ut_14_is_uri.rb +28 -0
  247. data/test/unit/ut_15_util.rb +57 -0
  248. data/test/unit/ut_16_reader.rb +225 -0
  249. data/test/unit/ut_18_engine.rb +47 -0
  250. data/test/unit/ut_19_part_template.rb +86 -0
  251. data/test/unit/ut_1_fei.rb +165 -0
  252. data/test/unit/ut_20_composite_storage.rb +74 -0
  253. data/test/unit/ut_21_svc_participant_list.rb +46 -0
  254. data/test/unit/ut_22_filter.rb +1094 -0
  255. data/test/unit/ut_23_svc_tracker.rb +48 -0
  256. data/test/unit/ut_24_radial_reader.rb +332 -0
  257. data/test/unit/ut_25_merge.rb +113 -0
  258. data/test/unit/ut_3_wait_logger.rb +39 -0
  259. data/test/unit/ut_4_expmap.rb +20 -0
  260. data/test/unit/ut_5_tree.rb +54 -0
  261. data/test/unit/ut_6_condition.rb +303 -0
  262. data/test/unit/ut_7_workitem.rb +99 -0
  263. data/test/unit/ut_8_tree_to_dot.rb +72 -0
  264. data/test/unit/ut_9_xml_reader.rb +61 -0
  265. metadata +504 -0
@@ -0,0 +1,186 @@
1
+ #--
2
+ # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+ require 'sourcify'
26
+ require 'ruote/util/ometa'
27
+
28
+
29
+ module Ruote
30
+
31
+ # Not really a reader, more an AST builder.
32
+ #
33
+ # pdef = Ruote.define :name => 'take_out_garbage' do
34
+ # sequence do
35
+ # take_out_regular_garbage
36
+ # take_out_glass
37
+ # take_out_paper
38
+ # end
39
+ # end
40
+ #
41
+ # engine.launch(pdef)
42
+ #
43
+ def self.define(*attributes, &block)
44
+
45
+ RubyDsl.create_branch('define', attributes, &block)
46
+ end
47
+
48
+ # Same as Ruote.define()
49
+ #
50
+ # pdef = Ruote.process_definition :name => 'take_out_garbage' do
51
+ # sequence do
52
+ # take_out_regular_garbage
53
+ # take_out_paper
54
+ # end
55
+ # end
56
+ #
57
+ # engine.launch(pdef)
58
+ #
59
+ def self.process_definition(*attributes, &block)
60
+
61
+ define(*attributes, &block)
62
+ end
63
+
64
+ # Similar in purpose to Ruote.define and Ruote.process_definition but
65
+ # instead of returning a [process] definition, returns the tree.
66
+ #
67
+ # tree = Ruote.process_definition :name => 'take_out_garbage' do
68
+ # sequence do
69
+ # take_out_regular_garbage
70
+ # take_out_paper
71
+ # end
72
+ # end
73
+ #
74
+ # p tree
75
+ # # => [ 'sequence', {}, [ [ 'take_out_regular_garbage', {}, [] ], [ 'take_out_paper', {}, [] ] ] ],
76
+ #
77
+ # This is useful when modifying a process instance via methods like re_apply :
78
+ #
79
+ # engine.re_apply(
80
+ # fei,
81
+ # :tree => Ruote.to_tree {
82
+ # sequence do
83
+ # participant 'alfred'
84
+ # participant 'bob'
85
+ # end
86
+ # })
87
+ # #
88
+ # # cancels the segment of process at fei and replaces it with
89
+ # # a simple alfred-bob sequence.
90
+ #
91
+ def self.to_tree(&block)
92
+
93
+ RubyDsl.create_branch('x', {}, &block).last.first
94
+ end
95
+
96
+ # :nodoc:
97
+ #
98
+ module RubyDsl
99
+
100
+ class BranchContext < Ruote::BlankSlate
101
+
102
+ def initialize(name, attributes)
103
+
104
+ @name = name
105
+ @attributes = attributes
106
+ @children = []
107
+ end
108
+
109
+ def method_missing(m, *args, &block)
110
+
111
+ @children.push(Ruote::RubyDsl.create_branch(m.to_s, args, &block))
112
+ end
113
+
114
+ def to_a
115
+
116
+ [ @name, @attributes, @children ]
117
+ end
118
+ end
119
+
120
+ def self.create_branch(name, attributes, &block)
121
+
122
+ name = name[1..-1] while name[0, 1] == '_'
123
+
124
+ h = attributes.inject({}) { |h1, a|
125
+
126
+ a.is_a?(Hash) ? h1.merge!(a) : h1[a] = nil
127
+
128
+ h1
129
+
130
+ }.inject({}) { |h1, (k, v)|
131
+
132
+ k = k.is_a?(Regexp) ? k.inspect : k.to_s
133
+ h1[k] = to_json(v)
134
+
135
+ h1
136
+ }
137
+
138
+ c = BranchContext.new(name, h)
139
+ c.instance_eval(&block) if block
140
+
141
+ c.to_a
142
+ end
143
+
144
+ def self.to_json(v)
145
+
146
+ case v
147
+ when Symbol; v.to_s
148
+ when Regexp; v.inspect
149
+ when Array; v.collect { |e| to_json(e) }
150
+ when Hash; v.inject({}) { |h, (k, v)| h[k.to_s] = to_json(v); h }
151
+ when Proc; v.to_raw_source + "\n"
152
+ else v
153
+ end
154
+ end
155
+ end
156
+
157
+ #
158
+ # The same .read and .understands? method as the other readers are found here.
159
+ #
160
+ module RubyReader
161
+
162
+ # Returns true if s seems to contain a Ruby process definition
163
+ #
164
+ def self.understands?(s)
165
+
166
+ s.match(
167
+ /\bRuote\.(process_definition|workflow_definition|define)\b/
168
+ ) != nil
169
+ end
170
+
171
+ # Evaluates the ruby string in the code, but at fist, thanks to the
172
+ # treechecker, makes sure it doesn't code malicious ruby code (at least
173
+ # tries very hard).
174
+ #
175
+ def self.read(s, treechecker)
176
+
177
+ treechecker.definition_check(s)
178
+ eval(s)
179
+
180
+ rescue SyntaxError => se
181
+ #p se
182
+ raise ArgumentError.new("Ruby syntax error : #{se.message}")
183
+ end
184
+ end
185
+ end
186
+
@@ -0,0 +1,99 @@
1
+ #--
2
+ # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+ require 'rexml/parsers/sax2parser'
26
+ require 'rexml/sax2listener'
27
+
28
+
29
+ module Ruote
30
+
31
+ #
32
+ # Turns an XML string into a process definition tree.
33
+ #
34
+ module XmlReader
35
+
36
+ # Returns true if the string seems to be an XML string.
37
+ #
38
+ def self.understands?(s)
39
+
40
+ s.match(/<[a-z]+>/) != nil
41
+ end
42
+
43
+ #
44
+ # A helper class to store the temporary tree while it gets read.
45
+ #
46
+ class Node
47
+
48
+ attr_reader :parent, :attributes, :children
49
+
50
+ def initialize(parent, name, attributes)
51
+
52
+ @parent = parent
53
+ @name = name
54
+ @attributes = attributes.inject({}) { |h, (k, v)|
55
+ h[k.gsub(/-/, '_')] = v
56
+ h
57
+ }
58
+ @children = []
59
+
60
+ parent.children << self if parent
61
+ end
62
+
63
+ def to_a
64
+
65
+ [ @name, @attributes, @children.collect { |c| c.to_a } ]
66
+ end
67
+ end
68
+
69
+ # Parses the XML string into a process definition tree (array of arrays).
70
+ #
71
+ def self.read(s, opt=nil)
72
+
73
+ parser = REXML::Parsers::SAX2Parser.new(s)
74
+
75
+ root = nil
76
+ current = nil
77
+
78
+ # u, l, q, a <=> url, local, qname, attributes
79
+
80
+ parser.listen(:start_element) do |u, l, q, a|
81
+ current = Node.new(current, l.gsub(/-/, '_'), a)
82
+ root ||= current
83
+ end
84
+ parser.listen(:end_element) do |u, l, q, a|
85
+ current = current.parent
86
+ end
87
+
88
+ parser.listen(:characters) do |text|
89
+ t = text.strip
90
+ current.attributes[t] = nil if t.size > 0
91
+ end
92
+
93
+ parser.parse
94
+
95
+ root.to_a
96
+ end
97
+ end
98
+ end
99
+
@@ -0,0 +1,212 @@
1
+ #--
2
+ # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+
26
+ module Ruote
27
+
28
+ #
29
+ # The core methods for the Receiver class (sometimes a Mixin is easier
30
+ # to integrate).
31
+ #
32
+ # (The engine itself includes this mixin, the LocalParticipant module
33
+ # includes it as well).
34
+ #
35
+ module ReceiverMixin
36
+
37
+ # This method pipes back a workitem into the engine, letting it resume
38
+ # in its flow, hopefully.
39
+ #
40
+ def receive(workitem)
41
+
42
+ workitem = workitem.to_h if workitem.respond_to?(:to_h)
43
+
44
+ @context.storage.put_msg(
45
+ 'receive',
46
+ 'fei' => workitem['fei'],
47
+ 'workitem' => workitem,
48
+ 'participant_name' => workitem['participant_name'],
49
+ 'receiver' => sign)
50
+ end
51
+
52
+ # Given a process definitions and optional initial fields and variables,
53
+ # launches a new process instance.
54
+ #
55
+ # This method is mostly used from the Ruote::Engine class (which includes
56
+ # this mixin).
57
+ #
58
+ # process_definition must be a result of Ruote.process_definition call
59
+ # or XML or JSON serialized process definition, as accepted by
60
+ # Ruote::Reader#read.
61
+ #
62
+ # fields are workflow parameters that will be placed in workitem.fields.
63
+ #
64
+ # variables contain engine variables.
65
+ #
66
+ def launch(process_definition, fields={}, variables={})
67
+
68
+ wfid = @context.wfidgen.generate
69
+
70
+ @context.storage.put_msg(
71
+ 'launch',
72
+ 'wfid' => wfid,
73
+ 'tree' => @context.reader.read(process_definition),
74
+ 'workitem' => { 'fields' => fields },
75
+ 'variables' => variables)
76
+
77
+ wfid
78
+ end
79
+
80
+ # Wraps a call to receive(workitem)
81
+ #
82
+ # Not aliasing so that if someone changes the receive implementation,
83
+ # reply is affected as well.
84
+ #
85
+ def reply(workitem)
86
+
87
+ receive(workitem)
88
+ end
89
+
90
+ # Wraps a call to receive(workitem)
91
+ #
92
+ # Not aliasing so that if someone changes the receive implementation,
93
+ # reply_to_engine is affected as well.
94
+ #
95
+ def reply_to_engine(workitem)
96
+
97
+ receive(workitem)
98
+ end
99
+
100
+ # A receiver signs a workitem when it comes back.
101
+ #
102
+ # Not used much as of now.
103
+ #
104
+ def sign
105
+
106
+ self.class.to_s
107
+ end
108
+
109
+ # Convenience method, given a workitem or a fei, returns the
110
+ # corresponding flow expession.
111
+ #
112
+ def fetch_flow_expression(workitem_or_fei)
113
+
114
+ Ruote::Exp::FlowExpression.fetch(
115
+ @context,
116
+ Ruote::FlowExpressionId.extract_h(workitem_or_fei))
117
+ end
118
+
119
+ # For example :
120
+ #
121
+ # fexp = engine.fexp(fei)
122
+ # # or
123
+ # fexp = engine.fexp(workitem)
124
+ #
125
+ alias fexp fetch_flow_expression
126
+
127
+ # A convenience methods for advanced users (like Oleg).
128
+ #
129
+ # Given a fei (flow expression id), fetches the workitem as stored in
130
+ # the expression with that fei.
131
+ # This is the "applied workitem", if the workitem is currently handed to
132
+ # a participant, this method will return the workitem as applied, not
133
+ # the workitem as saved by the participant/user in whatever worklist it
134
+ # uses. If you need that workitem, do the vanilla thing and ask it to
135
+ # the [storage] participant or its worklist.
136
+ #
137
+ # The fei might be a string fei (result of fei.to_storage_id), a
138
+ # FlowExpressionId instance or a hash.
139
+ #
140
+ # on_terminate processes are not triggered for on_error processes.
141
+ # on_error processes are triggered for on_terminate processes as well.
142
+ #
143
+ def applied_workitem(fei)
144
+
145
+ Ruote::Workitem.new(fexp(fei).h.applied_workitem)
146
+ end
147
+ alias workitem applied_workitem
148
+
149
+ protected
150
+
151
+ # Stashes values in the participant expression (in the storage).
152
+ #
153
+ # put(workitem.fei, 'key' => 'value', 'colour' => 'blue')
154
+ #
155
+ # Remember that keys/values must be serializable in JSON.
156
+ #
157
+ # put & get are useful for a participant that needs to communicate
158
+ # between its consume and its cancel.
159
+ #
160
+ # See the thread at
161
+ # http://groups.google.com/group/openwferu-users/t/2e6a95708c10847b for the
162
+ # justification.
163
+ #
164
+ def put(fei, hash)
165
+
166
+ fexp = Ruote::Exp::FlowExpression.fetch(@context, fei.to_h)
167
+
168
+ (fexp.h['stash'] ||= {}).merge!(hash)
169
+
170
+ fexp.persist_or_raise
171
+ end
172
+
173
+ # Fetches back a stashed value.
174
+ #
175
+ # get(fei, 'colour')
176
+ # # => 'blue'
177
+ #
178
+ # To return the whole stash
179
+ #
180
+ # get(fei)
181
+ # # => { 'colour' => 'blue' }
182
+ #
183
+ # put & get are useful for a participant that needs to communicate
184
+ # between its consume and its cancel.
185
+ #
186
+ def get(fei, key=nil)
187
+
188
+ fexp = Ruote::Exp::FlowExpression.fetch(@context, fei.to_h)
189
+
190
+ stash = fexp.h['stash'] rescue {}
191
+
192
+ key ? stash[key] : stash
193
+ end
194
+ end
195
+
196
+ #
197
+ # A receiver is meant to receive workitems and feed them back into the
198
+ # engine (the storage actually).
199
+ #
200
+ class Receiver
201
+ include ReceiverMixin
202
+
203
+ # Accepts context, worker, engine or storage as first argument.
204
+ #
205
+ def initialize(cwes, options={})
206
+
207
+ @context = cwes.context
208
+ @options = options
209
+ end
210
+ end
211
+ end
212
+