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,154 @@
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
+ # Reopening the FlowExpression class to add [un]persist methods.
30
+ #
31
+ class FlowExpression
32
+
33
+ #--
34
+ # PERSISTENCE
35
+ #++
36
+
37
+ # Persists and fetches the _rev identifier from the storage.
38
+ #
39
+ # Only used by the worker when creating the expression.
40
+ #
41
+ def initial_persist
42
+
43
+ r = @context.storage.put(@h, :update_rev => true)
44
+
45
+ #t = Thread.current.object_id.to_s[-3..-1]
46
+ #puts "+ per #{h.fei['expid']} #{tree[0]} r#{h._rev} t#{t} -> #{r.class}"
47
+ #Ruote.p_caller('+ per')
48
+
49
+ raise_or_return('initial_persist failed', r)
50
+ end
51
+
52
+ def try_persist
53
+
54
+ r = @context.storage.put(@h)
55
+
56
+ #t = Thread.current.object_id.to_s[-3..-1]
57
+ #puts "+ per #{h.fei['expid']} #{tree[0]} r#{h._rev} t#{t} -> #{r.class}"
58
+ #Ruote.p_caller('+ per')
59
+
60
+ r
61
+ end
62
+
63
+ def try_unpersist
64
+
65
+ r = @context.storage.delete(@h)
66
+
67
+ #t = Thread.current.object_id.to_s[-3..-1]
68
+ #puts "- unp #{h.fei['expid']} #{tree[0]} r#{h._rev} t#{t} -> #{r.class}"
69
+ #Ruote.p_caller('- unp')
70
+
71
+ return r if r
72
+
73
+ #if h.has_error
74
+ err = @context.storage.get('errors', "err_#{Ruote.to_storage_id(h.fei)}")
75
+ @context.storage.delete(err) if err
76
+ #end
77
+ # removes any error in the journal for this expression
78
+ # since it will now be gone, no need to keep track of its errors
79
+
80
+ nil
81
+ end
82
+
83
+ def persist_or_raise
84
+
85
+ p_or_raise(true)
86
+ end
87
+
88
+ def unpersist_or_raise
89
+
90
+ p_or_raise(false)
91
+ end
92
+
93
+ alias persist persist_or_raise
94
+ alias unpersist unpersist_or_raise
95
+
96
+ def do_persist
97
+
98
+ do_p(true)
99
+ end
100
+
101
+ def do_unpersist
102
+
103
+ do_p(false)
104
+ end
105
+
106
+ protected
107
+
108
+ def raise_or_return(msg, r)
109
+
110
+ msg = msg.is_a?(String) ?
111
+ msg : (msg ? 'persist' : 'unpersist') + ' failed'
112
+
113
+ raise(
114
+ "#{msg} for " +
115
+ "#{Ruote.to_storage_id(h.fei)} #{tree[0]} #{tree[1].inspect} " +
116
+ 'r(' + (r == true ? 'gone' : "rev : #{r['_rev']}") + ')'
117
+ ) if r
118
+
119
+ r
120
+ end
121
+
122
+ # Does persist or unpersist, returns nothing in particular.
123
+ #
124
+ # Will raise a runtime error if it fails (ie if it happens, there
125
+ # is something wrong with the storage implementation or the engine).
126
+ #
127
+ def p_or_raise(pers)
128
+
129
+ r = pers ? try_persist : try_unpersist
130
+
131
+ raise_or_return(pers, r)
132
+ end
133
+
134
+ # Does persist or unpersist, if successful then return true. If the
135
+ # expression is gone, return false.
136
+ # If there is a 'fresher' version of the expression, re-attempt and return
137
+ # false.
138
+ #
139
+ def do_p(pers)
140
+
141
+ case r = pers ? try_persist : try_unpersist
142
+ when true
143
+ false # do not go on
144
+ when Hash
145
+ self.h = r
146
+ self.send("do_#{@msg['action']}", @msg)
147
+ false # do not go on
148
+ else
149
+ true # success, do go on
150
+ end
151
+ end
152
+ end
153
+ end
154
+
@@ -0,0 +1,189 @@
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
+ # 're-opening' the FlowExpression class to add the methods about variables.
30
+ #
31
+ class FlowExpression
32
+
33
+ # A shortcut to the variables held in the expression (nil if none held).
34
+ #
35
+ def variables
36
+
37
+ @h['variables']
38
+ end
39
+
40
+ # Returns a fresh hash of all the variables visible from this expression.
41
+ #
42
+ # This is used mainly when forgetting an expression.
43
+ #
44
+ def compile_variables
45
+
46
+ vars = h.parent_id ? parent.compile_variables : {}
47
+ vars.merge!(h.variables) if h.variables
48
+
49
+ vars
50
+ end
51
+
52
+ # Looks up the value of a variable in expression tree
53
+ # (seen from a leaf, it looks more like a stack than a tree)
54
+ #
55
+ def lookup_variable(var, prefix=nil)
56
+
57
+ var, prefix = split_prefix(var, prefix)
58
+
59
+ return @context.storage.get_engine_variable(var) \
60
+ if prefix.length >= 2
61
+
62
+ return parent.lookup_variable(var, prefix) \
63
+ if h.parent_id && prefix.length >= 1
64
+
65
+ if h.variables
66
+
67
+ val = Ruote.lookup(h.variables, var)
68
+
69
+ return val if val != nil
70
+ end
71
+
72
+ if h.parent_id && h.parent_id['engine_id'] == @context.engine_id
73
+ #
74
+ # do not lookup variables in a remote engine ...
75
+
76
+ (return parent.lookup_variable(var, prefix)) rescue nil
77
+ # if the lookup fails (parent gone) then rescue and let go
78
+ end
79
+
80
+ @context.storage.get_engine_variable(var)
81
+ end
82
+
83
+ # A shortcut for #lookup_variable
84
+ #
85
+ alias :v :lookup_variable
86
+
87
+ # A shortcut for #lookup_variable
88
+ #
89
+ alias :lv :lookup_variable
90
+
91
+ # Sets a variable to a given value.
92
+ # (will set at the appropriate level).
93
+ #
94
+ def set_variable(var, val)
95
+
96
+ fexp, v = locate_var(var)
97
+
98
+ fexp.un_set_variable(:set, v, val, (fexp.h.fei != h.fei)) if fexp
99
+ end
100
+
101
+ # Unbinds a variables.
102
+ #
103
+ def unset_variable(var)
104
+
105
+ fexp, v = locate_var(var)
106
+
107
+ fexp.un_set_variable(:unset, v, nil, (fexp.h.fei != h.fei)) if fexp
108
+ end
109
+
110
+ # TODO : redoc rewrite needed
111
+ #
112
+ # This method is mostly used by the worker when looking up
113
+ # a process name or participant name bound under a variable.
114
+ #
115
+ def iterative_var_lookup(k)
116
+
117
+ v = lookup_variable(k)
118
+
119
+ return [ k, v ] unless (v.is_a?(String) or v.is_a?(Symbol))
120
+
121
+ iterative_var_lookup(v)
122
+ end
123
+
124
+ protected
125
+
126
+ # Sets (or unsets) the value of a local variable
127
+ #
128
+ # val should be nil in case of 'unset'.
129
+ #
130
+ def un_set_variable(op, var, val, should_persist)
131
+
132
+ if op == :set
133
+ Ruote.set(h.variables, var, val)
134
+ else # op == :unset
135
+ Ruote.unset(h.variables, var)
136
+ end
137
+
138
+ if should_persist && r = try_persist # persist failed, have to retry
139
+
140
+ @h = r
141
+ un_set_variable(op, var, val, true)
142
+
143
+ else # success (even when should_persist == false)
144
+
145
+ @context.storage.put_msg("variable_#{op}", 'var' => var, 'fei' => h.fei)
146
+ end
147
+ end
148
+
149
+ VAR_PREFIX_REGEX = /^(\/*)/
150
+
151
+ # Used by lookup_variable and set_variable to extract the
152
+ # prefix in a variable name
153
+ #
154
+ def split_prefix(var, prefix)
155
+
156
+ if prefix.nil?
157
+ var = var.to_s
158
+ m = VAR_PREFIX_REGEX.match(var)
159
+ prefix = m ? m[1][0, 2] : ''
160
+ var = var[prefix.length..-1]
161
+ end
162
+
163
+ [ var, prefix ]
164
+ end
165
+
166
+ # Returns the flow expression that owns a variable (or the one
167
+ # that should own it) and the var without its potential / prefixes.
168
+ #
169
+ def locate_var(var, prefix=nil)
170
+
171
+ var, prefix = split_prefix(var, prefix)
172
+
173
+ return nil if prefix.length >= 2 # engine variable
174
+ return parent.locate_var(var, prefix) if prefix.length == 1 && h.parent_id
175
+
176
+ # no prefix...
177
+
178
+ return [ self, var ] if h.variables
179
+
180
+ if par = parent
181
+ return parent.locate_var(var, prefix) rescue nil
182
+ end
183
+
184
+ #raise "uprooted var lookup, something went wrong"
185
+ [ nil, nil ]
186
+ end
187
+ end
188
+ end
189
+
@@ -0,0 +1,68 @@
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
+ # 're-opening' the FlowExpression class to add methods like set_vf and co.
30
+ #
31
+ class FlowExpression
32
+
33
+ protected
34
+
35
+ def set_v(key, value, unset=false)
36
+
37
+ if unset
38
+ unset_variable(key)
39
+ else
40
+ set_variable(key, value)
41
+ end
42
+ end
43
+
44
+ def set_f(key, value, unset=false)
45
+
46
+ if unset
47
+ h.applied_workitem['fields'].delete(key)
48
+ else
49
+ Ruote.set(h.applied_workitem['fields'], key, value)
50
+ end
51
+ end
52
+
53
+ PREFIX_REGEX = /^([^:]+):(.+)$/
54
+ F_PREFIX_REGEX = /^f/
55
+
56
+ def set_vf(key, value, unset=false)
57
+
58
+ field, key = if m = PREFIX_REGEX.match(key)
59
+ [ F_PREFIX_REGEX.match(m[1]), m[2] ]
60
+ else
61
+ [ true, key ]
62
+ end
63
+
64
+ field ? set_f(key, value, unset) : set_v(key, value, unset)
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,260 @@
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 'digest/md5'
26
+
27
+ require 'ruote/version'
28
+ require 'ruote/workitem'
29
+ require 'ruote/util/misc'
30
+ require 'ruote/util/hashdot'
31
+
32
+
33
+ module Ruote
34
+
35
+ # A shortcut for
36
+ #
37
+ # Ruote::FlowExpressionId.to_storage_id(fei)
38
+ #
39
+ def self.to_storage_id(fei)
40
+
41
+ Ruote::FlowExpressionId.to_storage_id(fei)
42
+ end
43
+
44
+ # A shorter shortcut for
45
+ #
46
+ # Ruote::FlowExpressionId.to_storage_id(fei)
47
+ #
48
+ def self.sid(fei)
49
+
50
+ Ruote::FlowExpressionId.to_storage_id(fei)
51
+ end
52
+
53
+ # A shortcut for
54
+ #
55
+ # Ruote::FlowExpressionId.is_a_fei?(o)
56
+ #
57
+ def self.is_a_fei?(o)
58
+
59
+ Ruote::FlowExpressionId.is_a_fei?(o)
60
+ end
61
+
62
+ # Will do its best to return a wfid (String) or a fei (Hash instance)
63
+ # extract from the given o argument.
64
+ #
65
+ def self.extract_id(o)
66
+
67
+ return o if o.is_a?(String) and o.index('!').nil? # wfid
68
+
69
+ Ruote::FlowExpressionId.extract_h(o)
70
+ end
71
+
72
+ # Given something, tries to return the fei (Ruote::FlowExpressionId) in it.
73
+ #
74
+ def self.extract_fei(o)
75
+
76
+ Ruote::FlowExpressionId.extract(o)
77
+ end
78
+
79
+ # This function is used to generate the subids. Each flow
80
+ # expression receives such an id (it's useful for cursors, loops and
81
+ # forgotten branches).
82
+ #
83
+ def self.generate_subid(salt)
84
+
85
+ Digest::MD5.hexdigest(
86
+ "#{rand}-#{salt}-#{$$}-#{Thread.current.object_id}#{Time.now.to_f}")
87
+ end
88
+
89
+ #
90
+ # The FlowExpressionId (fei for short) is an process expression identifier.
91
+ # Each expression when instantiated gets a unique fei.
92
+ #
93
+ # Feis are also used in workitems, where the fei is the fei of the
94
+ # [participant] expression that emitted the workitem.
95
+ #
96
+ # Feis can thus indicate the position of a workitem in a process tree.
97
+ #
98
+ # Feis contain four pieces of information :
99
+ #
100
+ # * wfid : workflow instance id, the identifier for the process instance
101
+ # * subid : a unique identifier for expressions (useful in loops)
102
+ # * expid : the expression id, where in the process tree
103
+ # * engine_id : only relevant in multi engine scenarii (defaults to 'engine')
104
+ #
105
+ class FlowExpressionId
106
+
107
+ CHILD_SEP = '_'
108
+
109
+ attr_reader :h
110
+
111
+ def initialize(h)
112
+
113
+ @h = h
114
+ class << h; include Ruote::HashDot; end
115
+
116
+ @h['subid'] = @h.delete('sub_wfid') if @h['sub_wfid']
117
+ # TODO : for 2.1.13, remove this
118
+ end
119
+
120
+ def expid; @h['expid']; end
121
+ def wfid; @h['wfid']; end
122
+ def engine_id; @h['engine_id']; end
123
+ def subid; @h['subid']; end
124
+
125
+ alias sub_wfid subid
126
+
127
+ def to_storage_id
128
+
129
+ "#{@h['expid']}!#{@h['subid']}!#{@h['wfid']}"
130
+ end
131
+ alias sid to_storage_id
132
+
133
+ def to_sortable_id
134
+
135
+ "#{@h['wfid']}!!#{@h['expid']}"
136
+ end
137
+
138
+ def self.to_storage_id(hfei)
139
+
140
+ hfei.respond_to?(:to_storage_id) ?
141
+ hfei.to_storage_id :
142
+ "#{hfei['expid']}!#{hfei['subid'] || hfei['sub_wfid']}!#{hfei['wfid']}"
143
+
144
+ # TODO : for 2.1.13, remove the subid || sub_wfid trick
145
+ end
146
+
147
+ # Turns the result of to_storage_id back to a FlowExpressionId instance.
148
+ #
149
+ def self.from_id(s, engine_id='engine')
150
+
151
+ extract("#{engine_id}!#{s}")
152
+ end
153
+
154
+ # Returns the last number in the expid. For instance, if the expid is
155
+ # '0_5_7', the child_id will be '7'.
156
+ #
157
+ def child_id
158
+
159
+ h.expid.split(CHILD_SEP).last.to_i
160
+ end
161
+
162
+ def hash
163
+
164
+ to_storage_id.hash
165
+ end
166
+
167
+ def <=>(other)
168
+
169
+ self.to_sortable_id <=> other.to_sortable_id
170
+ end
171
+
172
+ # Returns true if the other is a FlowExpressionId instance and it
173
+ # points to the same expression as this one.
174
+ #
175
+ def ==(other)
176
+
177
+ return false unless other.is_a?(Ruote::FlowExpressionId)
178
+
179
+ (hash == other.hash)
180
+ end
181
+
182
+ alias eql? ==
183
+
184
+ SUBS = %w[ subid sub_wfid ]
185
+ IDS = %w[ engine_id expid wfid ]
186
+
187
+ # Returns true if the h is a representation of a FlowExpressionId instance.
188
+ #
189
+ def self.is_a_fei?(h)
190
+
191
+ h.respond_to?(:keys) && (h.keys - SUBS).sort == IDS
192
+ end
193
+
194
+ # Returns child_id... For an expid of '0_1_4', this will be 4.
195
+ #
196
+ def self.child_id(h)
197
+
198
+ h['expid'].split(CHILD_SEP).last.to_i
199
+ end
200
+
201
+ def to_h
202
+
203
+ @h
204
+ end
205
+
206
+ # Returns true if other_fei is the fei of a child expression of
207
+ # parent_fei.
208
+ #
209
+ def self.direct_child?(parent_fei, other_fei)
210
+
211
+ %w[ wfid engine_id ].each do |k|
212
+ return false if parent_fei[k] != other_fei[k]
213
+ end
214
+
215
+ pei = other_fei['expid'].split(CHILD_SEP)[0..-2].join(CHILD_SEP)
216
+
217
+ (pei == parent_fei['expid'])
218
+ end
219
+
220
+ # Attempts at extracting a FlowExpressionId from the given argument
221
+ # (workitem, string, ...)
222
+ #
223
+ # Uses .extract_h
224
+ #
225
+ def self.extract(arg)
226
+
227
+ FlowExpressionId.new(extract_h(arg))
228
+ end
229
+
230
+ # Attempts at extracting a FlowExpressionId (as a Hash instance) from the
231
+ # given argument (workitem, string, ...)
232
+ #
233
+ def self.extract_h(arg)
234
+
235
+ if arg.is_a?(Hash)
236
+ return arg if arg['expid']
237
+ return arg['fei'] if arg['fei']
238
+ end
239
+
240
+ return extract_h(arg.fei) if arg.respond_to?(:fei)
241
+ return arg.h if arg.is_a?(Ruote::FlowExpressionId)
242
+ return arg.h['fei'] if arg.is_a?(Ruote::Workitem)
243
+
244
+ if arg.is_a?(String)
245
+
246
+ ss = arg.split('!')
247
+
248
+ return {
249
+ 'engine_id' => ss[-4] || 'engine',
250
+ 'expid' => ss[-3],
251
+ 'subid' => ss[-2],
252
+ 'wfid' => ss[-1] }
253
+ end
254
+
255
+ raise ArgumentError.new(
256
+ "couldn't extract fei out of instance of #{arg.class}")
257
+ end
258
+ end
259
+ end
260
+