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,87 @@
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::Exp
27
+
28
+ #
29
+ # Commands are understood by the cursor, loop and iterator expressions.
30
+ #
31
+ module CommandMixin
32
+
33
+ F_COMMAND = '__command__'
34
+ ATT_COMMANDS = %w[ break rewind reset over stop ]
35
+
36
+ protected
37
+
38
+ # TODO : :ignore_workitem / :disallow => 'workitem' thing ?
39
+
40
+ def get_command(workitem)
41
+
42
+ command, step = workitem['fields'].delete(F_COMMAND)
43
+ command, step = lookup_attribute_command(workitem) unless command
44
+ command = 'break' if command == 'over' || command == 'stop'
45
+
46
+ step = 1 if step == ''
47
+
48
+ return nil if command == nil
49
+
50
+ if command == 'back'
51
+ command = 'skip'
52
+ step = step ? -step : -1
53
+ elsif command == 'skip'
54
+ step ||= 1
55
+ end
56
+
57
+ [ command, step ]
58
+ end
59
+
60
+ def set_command(workitem, command, step=nil)
61
+
62
+ workitem['fields'][F_COMMAND] = [ command, step ]
63
+ end
64
+
65
+ def lookup_attribute_command(workitem)
66
+
67
+ lookup_att_com('if', workitem) || lookup_att_com('unless', workitem)
68
+ end
69
+
70
+ def lookup_att_com(dir, workitem)
71
+
72
+ ATT_COMMANDS.each do |com|
73
+
74
+ c = attribute("#{com}_#{dir}", workitem)
75
+
76
+ next unless c
77
+
78
+ c = Condition.true?(c)
79
+
80
+ return [ com, nil ] if (dir == 'if' && c) || (dir == 'unless' && ( ! c))
81
+ end
82
+
83
+ nil
84
+ end
85
+ end
86
+ end
87
+
@@ -0,0 +1,69 @@
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
+ require 'ruote/exp/command'
27
+ require 'ruote/exp/iterator'
28
+
29
+
30
+ module Ruote::Exp
31
+
32
+ #
33
+ # A parent class for CursorExpression and IteratorExpression
34
+ #
35
+ class CommandedExpression < FlowExpression
36
+
37
+ include CommandMixin
38
+
39
+ def reply(workitem)
40
+
41
+ workitem = h.command_workitem || workitem
42
+ h.command_workitem = nil
43
+
44
+ # command/answer may come from
45
+ #
46
+ # a) a child, regular case, easy
47
+ # b) somewhere else, which means we have to cancel the current child
48
+ # and then make sure the comand is interpreted
49
+
50
+ # a)
51
+
52
+ if Ruote::FlowExpressionId.direct_child?(h.fei, workitem['fei'])
53
+ return move_on(workitem)
54
+ end
55
+
56
+ # b)
57
+
58
+ h.command_workitem = workitem
59
+ h.command_workitem['fei'] = h.children.first
60
+
61
+ do_persist || return
62
+
63
+ @context.storage.put_msg('cancel', 'fei' => h.children.first)
64
+
65
+ # iteration will be done at when cancelled child replies
66
+ end
67
+ end
68
+ end
69
+
@@ -0,0 +1,227 @@
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::Exp
27
+
28
+ #
29
+ # A few helper methods for evaluating :if and :unless expression
30
+ # attributes in process definitions.
31
+ #
32
+ module Condition
33
+
34
+ #
35
+ # A runtime error for unusable comparison strings.
36
+ #
37
+ class ConditionError < RuntimeError
38
+
39
+ def initialize(code)
40
+ super(
41
+ "couldn't interpret >#{code}<, " +
42
+ "if it comes from a ${xx} construct, please use ${\"xx} or ${'yy}")
43
+ end
44
+ end
45
+
46
+ REGEXES = {
47
+ 'evl_set' => /^(.+?)( +is)?( +not)?( +set)$/,
48
+ 'evl_null' => /^(.+?)( +is)?( +not)?( +null)$/,
49
+ 'evl_empty' => /^(.+[\]}"'])( +is)?( +not)?( +empty)$/,
50
+ 'evl_in' => /^(.+?)( +is)?( +not)?( +in +)(\[.*\]|\{.*\})$/
51
+ }
52
+
53
+ def self.apply?(sif, sunless)
54
+
55
+ return (true?(sif)) if sif
56
+ return ( ! true?(sunless)) if sunless
57
+
58
+ true
59
+ end
60
+
61
+ # Returns true if the given conditional string evaluates to true.
62
+ #
63
+ def self.true?(conditional)
64
+
65
+ conditional = unescape(conditional.to_s)
66
+
67
+ REGEXES.each do |method, regex|
68
+ if m = regex.match(conditional)
69
+ return self.send(method, m)
70
+ end
71
+ end
72
+
73
+ evl(conditional) ? true : false
74
+
75
+ rescue ArgumentError => ae
76
+
77
+ raise ConditionError.new(conditional)
78
+ end
79
+
80
+ # Evaluates the given [conditional] code string and returns the
81
+ # result.
82
+ #
83
+ # Note : this is not a full Ruby evaluation !
84
+ #
85
+ def self.eval(code)
86
+
87
+ evl(code)
88
+
89
+ rescue ArgumentError => ae
90
+
91
+ raise ConditionError.new(code)
92
+ end
93
+
94
+ protected
95
+
96
+ def self.parse(conditional)
97
+
98
+ Rufus::TreeChecker.parse(conditional)
99
+
100
+ rescue NoMethodError => nme
101
+
102
+ raise NoMethodError.new(
103
+ "/!\\ please upgrade your rufus-treechecker gem /!\\"
104
+ )
105
+
106
+ rescue SyntaxError => se
107
+
108
+ [ :str, conditional ]
109
+
110
+ rescue Exception => e
111
+
112
+ [ :false ]
113
+ end
114
+
115
+ def self.unescape(s)
116
+
117
+ s.gsub('&amp;', '&').gsub('&gt;', '>').gsub('&lt;', '<')
118
+ end
119
+
120
+ COMPARATORS = %w[ == > < != >= <= ].collect { |c| c.to_sym }
121
+
122
+ def self.evl(tree)
123
+
124
+ return evl(parse(tree)) if tree.is_a?(String)
125
+
126
+ return nil if tree == []
127
+
128
+ return tree.last if tree.first == :str
129
+ return tree.last if tree.first == :lit
130
+ return tree.last.to_s if tree.first == :const
131
+ return nil if tree == [ :nil ]
132
+ return true if tree == [ :true ]
133
+ return false if tree == [ :false ]
134
+
135
+ return ( ! evl(tree.last)) if tree.first == :not
136
+
137
+ return evl(tree[1]) && evl(tree[2]) if tree[0] == :and
138
+ return evl(tree[1]) || evl(tree[2]) if tree[0] == :or
139
+
140
+ return tree[1..-1].collect { |e| evl(e) } if tree[0] == :array
141
+ return Hash.[](*tree[1..-1].collect { |e| evl(e) }) if tree[0] == :hash
142
+
143
+ if tree[0] == :match3
144
+ return evl(tree[2]) =~ evl(tree[1])
145
+ end
146
+ if tree[0] == :call && tree[2] == :=~
147
+ return evl(tree[1]) =~ Regexp.new(evl(tree.last.last).to_s)
148
+ end
149
+
150
+ if tree[0] == :call && COMPARATORS.include?(tree[2])
151
+ return evl(tree[1]).send(tree[2], evl(tree.last.last))
152
+ end
153
+
154
+ if (c = flatten_and_compare(tree)) != nil
155
+ return c
156
+ end
157
+
158
+ if tree[0] == :call
159
+ return flatten(tree)
160
+ end
161
+
162
+ raise ArgumentError
163
+ # TODO : consider returning false
164
+
165
+ #require 'ruby2ruby'
166
+ #Ruby2Ruby.new.process(Sexp.from_array(tree))
167
+ # returns the raw Ruby as a String
168
+ # it's nice but "Loan/Grant" becomes "(Loan / Grant)"
169
+ end
170
+
171
+ def self.flatten_and_compare(tree)
172
+
173
+ ftree = tree.flatten
174
+ comparator = (ftree & COMPARATORS).first
175
+
176
+ return nil unless comparator
177
+
178
+ icomparator = ftree.index(comparator)
179
+ left = ftree[0..icomparator - 1]
180
+ right = ftree[icomparator + 1..-1]
181
+
182
+ evl("#{flatten(left).inspect} #{comparator} #{flatten(right).inspect}")
183
+ end
184
+
185
+ KEYWORDS = %w[ call const arglist str ].collect { |w| w.to_sym }
186
+
187
+ def self.flatten(tree)
188
+
189
+ (tree.flatten - KEYWORDS).collect { |e| e.nil? ? ' ' : e.to_s }.join.strip
190
+ end
191
+
192
+ def self.evl_set(match)
193
+
194
+ set = evl(match[1])
195
+ set = set != nil && set != ''
196
+ set = false if match[1].match(/is$/) && match[2].nil?
197
+
198
+ match[3].nil? ? set : ( ! set)
199
+ end
200
+
201
+ def self.evl_empty(match)
202
+
203
+ object = evl(match[1])
204
+
205
+ empty = if object.respond_to?(:empty?)
206
+ object.empty?
207
+ elsif object.nil?
208
+ true
209
+ else
210
+ false
211
+ end
212
+
213
+ ( ! match[3].nil? ^ empty)
214
+ end
215
+
216
+ def self.evl_null(match)
217
+
218
+ ( ! match[3].nil? ^ evl(match[1]).nil?)
219
+ end
220
+
221
+ def self.evl_in(match)
222
+
223
+ ( ! match[3].nil? ^ evl(match[5]).include?(evl(match[1]))) rescue false
224
+ end
225
+ end
226
+ end
227
+
@@ -0,0 +1,138 @@
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 'ruote/exp/iterator'
26
+
27
+
28
+ module Ruote::Exp
29
+
30
+ #
31
+ # The 'add_branches'/'add_branch' expression can be used to add branches
32
+ # to a concurrent-iterator while it is running.
33
+ #
34
+ # concurrent_iterator :on => 'a, b, c' do
35
+ # sequence do
36
+ # participant :ref => 'worker_${v:i}'
37
+ # add_branches 'd, e', :if => '${v:/not_sufficient}'
38
+ # end
39
+ # end
40
+ #
41
+ # In this example, if the process level variable 'not_sufficient' is set to
42
+ # true, workers d and e will be added to the iterated elements.
43
+ #
44
+ # 'add_branches' understand comma-separated list of values or direcltly
45
+ # array of values, like the concurrent_iterator does. The :sep or :separator
46
+ # attribute can be used for custom separators :
47
+ #
48
+ # add_branches 'd|e|f', :sep => '|'
49
+ #
50
+ #
51
+ # == :ref
52
+ #
53
+ # By default, add_branches looks up the first parent expression that is
54
+ # concurrent_iterator. This is all well, but what when you have nested
55
+ # concurrent_iterator and want to hit the enclosing one from inside the
56
+ # enclosed one ? Or when you want to add branches from somewhere else
57
+ # in the process instance, outside of the concurrent_iterator ?
58
+ #
59
+ # concurrence do
60
+ #
61
+ # concurrent_iterator :on => 'a, b, c', :tag => 'main' do
62
+ # subprocess :ref => 'perform_work'
63
+ # end
64
+ #
65
+ # sequence do
66
+ # subprocess :ref => 'supervise_work'
67
+ # add_branches 'd, e', :ref => 'main', :if => '${f:more_cowbell}'
68
+ # rewind :if => '${f:more_cowbell}'
69
+ # end
70
+ # end
71
+ #
72
+ # The add_branches expression refers to the 'main' concurrent_iterator via
73
+ # the :ref => 'main' attribute.
74
+ #
75
+ #
76
+ # == missing concurrent_iterator
77
+ #
78
+ # If :ref points to nothing or add_branch has no :ref and is not placed
79
+ # inside of a concurrent_iterator, the expression will silently have no
80
+ # effect.
81
+ #
82
+ class AddBranchesExpression < FlowExpression
83
+
84
+ include IteratorMixin
85
+
86
+ names :add_branches, :add_branch
87
+
88
+ def apply
89
+
90
+ list = split_list(lookup_val_prefix('on') || attribute_text)
91
+ it_fei = find_concurrent_iterator
92
+
93
+ if list && it_fei
94
+
95
+ wi = Ruote.fulldup(h.applied_workitem)
96
+ wi['fields'][ConcurrentIteratorExpression::ADD_BRANCHES_FIELD] = list
97
+
98
+ @context.storage.put_msg('reply', 'fei' => it_fei, 'workitem' => wi)
99
+ end
100
+
101
+ reply_to_parent(h.applied_workitem)
102
+ end
103
+
104
+ def reply(workitem)
105
+
106
+ # never called
107
+ end
108
+
109
+ protected
110
+
111
+ def find_concurrent_iterator
112
+
113
+ #
114
+ # ref ?
115
+
116
+ if ref = attribute(:ref)
117
+
118
+ return lookup_variable(ref)
119
+ end
120
+
121
+ #
122
+ # no :ref, lookup first parent that is a concurrent_iterator
123
+
124
+ exp = self.parent
125
+
126
+ loop do
127
+
128
+ break if exp.nil?
129
+ break if exp.is_a?(ConcurrentIteratorExpression)
130
+
131
+ exp = exp.parent
132
+ end
133
+
134
+ exp ? exp.h.fei : nil
135
+ end
136
+ end
137
+ end
138
+