ruote 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (305) hide show
  1. data/CHANGELOG.txt +166 -1
  2. data/CREDITS.txt +36 -17
  3. data/LICENSE.txt +1 -1
  4. data/README.rdoc +1 -7
  5. data/Rakefile +38 -29
  6. data/TODO.txt +93 -52
  7. data/lib/ruote-fs.rb +3 -0
  8. data/lib/ruote.rb +5 -1
  9. data/lib/ruote/context.rb +140 -35
  10. data/lib/ruote/dashboard.rb +1247 -0
  11. data/lib/ruote/{engine → dboard}/process_error.rb +22 -2
  12. data/lib/ruote/dboard/process_status.rb +587 -0
  13. data/lib/ruote/engine.rb +6 -871
  14. data/lib/ruote/exp/command.rb +7 -2
  15. data/lib/ruote/exp/commanded.rb +2 -2
  16. data/lib/ruote/exp/condition.rb +38 -13
  17. data/lib/ruote/exp/fe_add_branches.rb +1 -1
  18. data/lib/ruote/exp/fe_apply.rb +1 -1
  19. data/lib/ruote/exp/fe_await.rb +357 -0
  20. data/lib/ruote/exp/fe_cancel_process.rb +17 -3
  21. data/lib/ruote/exp/fe_command.rb +8 -4
  22. data/lib/ruote/exp/fe_concurrence.rb +218 -18
  23. data/lib/ruote/exp/fe_concurrent_iterator.rb +71 -10
  24. data/lib/ruote/exp/fe_cron.rb +3 -10
  25. data/lib/ruote/exp/fe_cursor.rb +14 -4
  26. data/lib/ruote/exp/fe_define.rb +3 -1
  27. data/lib/ruote/exp/fe_echo.rb +1 -1
  28. data/lib/ruote/exp/fe_equals.rb +1 -1
  29. data/lib/ruote/exp/fe_error.rb +1 -1
  30. data/lib/ruote/exp/fe_filter.rb +163 -4
  31. data/lib/ruote/exp/fe_forget.rb +21 -4
  32. data/lib/ruote/exp/fe_given.rb +1 -1
  33. data/lib/ruote/exp/fe_if.rb +1 -1
  34. data/lib/ruote/exp/fe_inc.rb +102 -35
  35. data/lib/ruote/exp/fe_iterator.rb +47 -12
  36. data/lib/ruote/exp/fe_listen.rb +96 -11
  37. data/lib/ruote/exp/fe_lose.rb +31 -4
  38. data/lib/ruote/exp/fe_noop.rb +1 -1
  39. data/lib/ruote/exp/fe_on_error.rb +109 -0
  40. data/lib/ruote/exp/fe_once.rb +10 -19
  41. data/lib/ruote/exp/fe_participant.rb +90 -28
  42. data/lib/ruote/exp/fe_read.rb +69 -0
  43. data/lib/ruote/exp/fe_redo.rb +3 -2
  44. data/lib/ruote/exp/fe_ref.rb +57 -27
  45. data/lib/ruote/exp/fe_registerp.rb +1 -3
  46. data/lib/ruote/exp/fe_reserve.rb +1 -1
  47. data/lib/ruote/exp/fe_restore.rb +6 -6
  48. data/lib/ruote/exp/fe_save.rb +12 -19
  49. data/lib/ruote/exp/fe_sequence.rb +38 -2
  50. data/lib/ruote/exp/fe_set.rb +143 -40
  51. data/lib/ruote/exp/{fe_let.rb → fe_stall.rb} +7 -38
  52. data/lib/ruote/exp/fe_subprocess.rb +8 -2
  53. data/lib/ruote/exp/fe_that.rb +1 -1
  54. data/lib/ruote/exp/fe_undo.rb +40 -4
  55. data/lib/ruote/exp/fe_unregisterp.rb +1 -3
  56. data/lib/ruote/exp/fe_wait.rb +12 -25
  57. data/lib/ruote/exp/{flowexpression.rb → flow_expression.rb} +375 -229
  58. data/lib/ruote/exp/iterator.rb +2 -2
  59. data/lib/ruote/exp/merge.rb +78 -17
  60. data/lib/ruote/exp/ro_attributes.rb +46 -36
  61. data/lib/ruote/exp/ro_filters.rb +34 -8
  62. data/lib/ruote/exp/ro_on_x.rb +431 -0
  63. data/lib/ruote/exp/ro_persist.rb +19 -7
  64. data/lib/ruote/exp/ro_timers.rb +123 -0
  65. data/lib/ruote/exp/ro_variables.rb +90 -29
  66. data/lib/ruote/fei.rb +57 -3
  67. data/lib/ruote/fs.rb +3 -0
  68. data/lib/ruote/id/mnemo_wfid_generator.rb +30 -7
  69. data/lib/ruote/id/wfid_generator.rb +17 -38
  70. data/lib/ruote/log/default_history.rb +23 -9
  71. data/lib/ruote/log/fancy_printing.rb +265 -0
  72. data/lib/ruote/log/storage_history.rb +23 -13
  73. data/lib/ruote/log/wait_logger.rb +224 -17
  74. data/lib/ruote/observer.rb +82 -0
  75. data/lib/ruote/part/block_participant.rb +65 -28
  76. data/lib/ruote/part/code_participant.rb +81 -0
  77. data/lib/ruote/part/engine_participant.rb +7 -2
  78. data/lib/ruote/part/local_participant.rb +221 -21
  79. data/lib/ruote/part/no_op_participant.rb +1 -1
  80. data/lib/ruote/part/null_participant.rb +1 -1
  81. data/lib/ruote/part/participant.rb +50 -0
  82. data/lib/ruote/part/rev_participant.rb +178 -0
  83. data/lib/ruote/part/smtp_participant.rb +2 -2
  84. data/lib/ruote/part/storage_participant.rb +228 -60
  85. data/lib/ruote/part/template.rb +1 -1
  86. data/lib/ruote/participant.rb +2 -0
  87. data/lib/ruote/reader.rb +205 -68
  88. data/lib/ruote/reader/json.rb +49 -0
  89. data/lib/ruote/reader/radial.rb +303 -0
  90. data/lib/ruote/reader/ruby_dsl.rb +44 -9
  91. data/lib/ruote/reader/xml.rb +11 -8
  92. data/lib/ruote/receiver/base.rb +98 -45
  93. data/lib/ruote/storage/base.rb +104 -35
  94. data/lib/ruote/storage/composite_storage.rb +50 -60
  95. data/lib/ruote/storage/fs_storage.rb +25 -34
  96. data/lib/ruote/storage/hash_storage.rb +38 -36
  97. data/lib/ruote/svc/dispatch_pool.rb +104 -35
  98. data/lib/ruote/svc/dollar_sub.rb +10 -8
  99. data/lib/ruote/svc/error_handler.rb +108 -52
  100. data/lib/ruote/svc/expression_map.rb +3 -3
  101. data/lib/ruote/svc/participant_list.rb +160 -55
  102. data/lib/ruote/svc/tracker.rb +31 -31
  103. data/lib/ruote/svc/treechecker.rb +28 -16
  104. data/lib/ruote/tree_dot.rb +1 -1
  105. data/lib/ruote/util/deep.rb +143 -0
  106. data/lib/ruote/util/filter.rb +125 -18
  107. data/lib/ruote/util/hashdot.rb +15 -13
  108. data/lib/ruote/util/look.rb +1 -1
  109. data/lib/ruote/util/lookup.rb +60 -22
  110. data/lib/ruote/util/misc.rb +63 -18
  111. data/lib/ruote/util/mpatch.rb +53 -0
  112. data/lib/ruote/util/ometa.rb +1 -2
  113. data/lib/ruote/util/process_observer.rb +177 -0
  114. data/lib/ruote/util/subprocess.rb +1 -1
  115. data/lib/ruote/util/time.rb +2 -2
  116. data/lib/ruote/util/tree.rb +64 -2
  117. data/lib/ruote/version.rb +3 -2
  118. data/lib/ruote/worker.rb +421 -92
  119. data/lib/ruote/workitem.rb +157 -22
  120. data/ruote.gemspec +15 -9
  121. data/test/bm/ci.rb +0 -2
  122. data/test/bm/ici.rb +0 -2
  123. data/test/bm/load_26c.rb +0 -3
  124. data/test/bm/mega.rb +0 -2
  125. data/test/functional/base.rb +57 -43
  126. data/test/functional/concurrent_base.rb +16 -13
  127. data/test/functional/ct_0_concurrence.rb +7 -11
  128. data/test/functional/ct_1_iterator.rb +9 -11
  129. data/test/functional/ct_2_cancel.rb +28 -17
  130. data/test/functional/eft_0_flow_expression.rb +35 -0
  131. data/test/functional/eft_10_cancel_process.rb +1 -1
  132. data/test/functional/eft_11_wait.rb +13 -13
  133. data/test/functional/eft_12_listen.rb +199 -66
  134. data/test/functional/eft_13_iterator.rb +95 -29
  135. data/test/functional/eft_14_cursor.rb +74 -24
  136. data/test/functional/eft_15_loop.rb +7 -7
  137. data/test/functional/eft_16_if.rb +1 -1
  138. data/test/functional/eft_17_equals.rb +1 -1
  139. data/test/functional/eft_18_concurrent_iterator.rb +156 -68
  140. data/test/functional/eft_19_reserve.rb +15 -15
  141. data/test/functional/eft_1_echo.rb +1 -1
  142. data/test/functional/eft_20_save.rb +51 -9
  143. data/test/functional/eft_21_restore.rb +1 -1
  144. data/test/functional/eft_22_noop.rb +1 -1
  145. data/test/functional/eft_23_apply.rb +1 -1
  146. data/test/functional/eft_24_add_branches.rb +7 -8
  147. data/test/functional/eft_25_command.rb +1 -1
  148. data/test/functional/eft_26_error.rb +11 -11
  149. data/test/functional/eft_27_inc.rb +111 -67
  150. data/test/functional/eft_28_once.rb +16 -16
  151. data/test/functional/eft_29_cron.rb +9 -9
  152. data/test/functional/eft_2_sequence.rb +23 -4
  153. data/test/functional/eft_30_ref.rb +36 -24
  154. data/test/functional/eft_31_registerp.rb +24 -24
  155. data/test/functional/eft_32_lose.rb +46 -20
  156. data/test/functional/eft_34_given.rb +1 -1
  157. data/test/functional/eft_35_filter.rb +161 -7
  158. data/test/functional/eft_36_read.rb +97 -0
  159. data/test/functional/{eft_0_process_definition.rb → eft_37_process_definition.rb} +4 -4
  160. data/test/functional/eft_38_on_error.rb +195 -0
  161. data/test/functional/eft_39_stall.rb +35 -0
  162. data/test/functional/eft_3_participant.rb +77 -22
  163. data/test/functional/eft_40_await.rb +297 -0
  164. data/test/functional/eft_4_set.rb +110 -11
  165. data/test/functional/eft_5_subprocess.rb +27 -5
  166. data/test/functional/eft_6_concurrence.rb +299 -60
  167. data/test/functional/eft_7_forget.rb +24 -22
  168. data/test/functional/eft_8_undo.rb +52 -15
  169. data/test/functional/eft_9_redo.rb +18 -20
  170. data/test/functional/ft_0_worker.rb +122 -13
  171. data/test/functional/ft_10_dollar.rb +77 -16
  172. data/test/functional/ft_11_recursion.rb +9 -9
  173. data/test/functional/ft_12_launchitem.rb +7 -9
  174. data/test/functional/ft_13_variables.rb +125 -22
  175. data/test/functional/ft_14_re_apply.rb +112 -56
  176. data/test/functional/ft_15_timeout.rb +64 -33
  177. data/test/functional/ft_16_participant_params.rb +59 -6
  178. data/test/functional/ft_17_conditional.rb +68 -2
  179. data/test/functional/ft_18_kill.rb +48 -30
  180. data/test/functional/ft_19_participant_code.rb +67 -0
  181. data/test/functional/ft_1_process_status.rb +222 -150
  182. data/test/functional/ft_20_storage_participant.rb +445 -44
  183. data/test/functional/ft_21_forget.rb +21 -26
  184. data/test/functional/ft_22_process_definitions.rb +8 -6
  185. data/test/functional/ft_23_load_defs.rb +29 -5
  186. data/test/functional/ft_24_block_participant.rb +199 -20
  187. data/test/functional/ft_25_receiver.rb +98 -46
  188. data/test/functional/ft_26_participant_rtimeout.rb +34 -26
  189. data/test/functional/ft_27_var_indirection.rb +40 -5
  190. data/test/functional/ft_28_null_noop_participants.rb +5 -5
  191. data/test/functional/ft_29_part_template.rb +2 -2
  192. data/test/functional/ft_2_errors.rb +106 -74
  193. data/test/functional/ft_30_smtp_participant.rb +7 -7
  194. data/test/functional/ft_31_part_blocking.rb +11 -11
  195. data/test/functional/ft_32_scope.rb +50 -0
  196. data/test/functional/ft_33_participant_subprocess_priority.rb +3 -3
  197. data/test/functional/ft_34_cursor_rewind.rb +14 -14
  198. data/test/functional/ft_35_add_service.rb +67 -9
  199. data/test/functional/ft_36_storage_history.rb +92 -24
  200. data/test/functional/ft_37_default_history.rb +35 -23
  201. data/test/functional/ft_38_participant_more.rb +189 -32
  202. data/test/functional/ft_39_wait_for.rb +25 -25
  203. data/test/functional/ft_3_participant_registration.rb +235 -107
  204. data/test/functional/ft_40_wait_logger.rb +105 -18
  205. data/test/functional/ft_41_participants.rb +13 -12
  206. data/test/functional/ft_42_storage_copy.rb +12 -12
  207. data/test/functional/ft_43_participant_on_reply.rb +85 -11
  208. data/test/functional/ft_44_var_participant.rb +5 -5
  209. data/test/functional/ft_45_participant_accept.rb +3 -3
  210. data/test/functional/ft_46_launch_single.rb +17 -17
  211. data/test/functional/ft_47_wfids.rb +41 -0
  212. data/test/functional/ft_48_lose.rb +19 -25
  213. data/test/functional/ft_49_engine_on_error.rb +54 -70
  214. data/test/functional/ft_4_cancel.rb +84 -26
  215. data/test/functional/ft_50_engine_config.rb +4 -4
  216. data/test/functional/ft_51_misc.rb +12 -12
  217. data/test/functional/ft_52_case.rb +17 -17
  218. data/test/functional/ft_53_engine_on_terminate.rb +18 -21
  219. data/test/functional/ft_54_patterns.rb +18 -16
  220. data/test/functional/ft_55_engine_participant.rb +55 -55
  221. data/test/functional/ft_56_filter_attribute.rb +90 -52
  222. data/test/functional/ft_57_rev_participant.rb +252 -0
  223. data/test/functional/ft_58_workitem.rb +150 -0
  224. data/test/functional/ft_59_pause.rb +329 -0
  225. data/test/functional/ft_5_on_error.rb +430 -77
  226. data/test/functional/ft_60_code_participant.rb +65 -0
  227. data/test/functional/ft_61_trailing_fields.rb +34 -0
  228. data/test/functional/ft_62_exp_name_and_dollar_substitution.rb +35 -0
  229. data/test/functional/ft_63_participants_221.rb +458 -0
  230. data/test/functional/ft_64_stash.rb +41 -0
  231. data/test/functional/ft_65_timers.rb +313 -0
  232. data/test/functional/ft_66_flank.rb +133 -0
  233. data/test/functional/ft_67_radial_misc.rb +34 -0
  234. data/test/functional/ft_68_reput.rb +72 -0
  235. data/test/functional/ft_69_worker_info.rb +56 -0
  236. data/test/functional/ft_6_on_cancel.rb +189 -36
  237. data/test/functional/ft_70_take_and_discard_attributes.rb +94 -0
  238. data/test/functional/ft_71_retries.rb +144 -0
  239. data/test/functional/ft_72_on_terminate.rb +60 -0
  240. data/test/functional/ft_73_raise_msg.rb +107 -0
  241. data/test/functional/ft_74_respark.rb +106 -0
  242. data/test/functional/ft_75_context.rb +66 -0
  243. data/test/functional/ft_76_observer.rb +53 -0
  244. data/test/functional/ft_77_process_observer.rb +157 -0
  245. data/test/functional/ft_78_part_participant.rb +37 -0
  246. data/test/functional/ft_7_tags.rb +238 -50
  247. data/test/functional/ft_8_participant_consumption.rb +27 -21
  248. data/test/functional/ft_9_subprocesses.rb +48 -18
  249. data/test/functional/restart_base.rb +4 -6
  250. data/test/functional/rt_0_wait.rb +10 -10
  251. data/test/functional/rt_1_listen.rb +6 -6
  252. data/test/functional/rt_2_errors.rb +12 -12
  253. data/test/functional/rt_3_once.rb +17 -12
  254. data/test/functional/rt_4_cron.rb +17 -17
  255. data/test/functional/rt_5_timeout.rb +13 -13
  256. data/test/functional/signals.rb +103 -0
  257. data/test/functional/storage.rb +730 -0
  258. data/test/functional/storage_helper.rb +48 -35
  259. data/test/functional/test.rb +6 -2
  260. data/test/misc/idle.rb +21 -0
  261. data/test/misc/light.rb +29 -0
  262. data/test/path_helper.rb +1 -1
  263. data/test/test.rb +2 -5
  264. data/test/test_helper.rb +13 -0
  265. data/test/unit/test.rb +1 -4
  266. data/test/unit/ut_0_ruby_reader.rb +25 -9
  267. data/test/unit/ut_10_participants.rb +47 -0
  268. data/test/unit/ut_11_lookup.rb +59 -2
  269. data/test/unit/ut_12_wait_logger.rb +123 -0
  270. data/test/unit/ut_14_is_uri.rb +1 -1
  271. data/test/unit/ut_15_util.rb +1 -1
  272. data/test/unit/ut_16_reader.rb +136 -14
  273. data/test/unit/ut_17_merge.rb +155 -0
  274. data/test/unit/ut_19_part_template.rb +1 -1
  275. data/test/unit/ut_1_fei.rb +11 -2
  276. data/test/unit/ut_20_composite_storage.rb +27 -1
  277. data/test/unit/{ut_21_participant_list.rb → ut_21_svc_participant_list.rb} +2 -3
  278. data/test/unit/ut_22_filter.rb +231 -10
  279. data/test/unit/ut_23_svc_tracker.rb +48 -0
  280. data/test/unit/ut_24_radial_reader.rb +458 -0
  281. data/test/unit/ut_25_process_status.rb +143 -0
  282. data/test/unit/ut_26_deep.rb +131 -0
  283. data/test/unit/ut_2_dashboard.rb +114 -0
  284. data/test/unit/ut_3_worker.rb +54 -0
  285. data/test/unit/ut_4_expmap.rb +1 -1
  286. data/test/unit/ut_5_tree.rb +23 -23
  287. data/test/unit/ut_6_condition.rb +71 -29
  288. data/test/unit/ut_7_workitem.rb +18 -4
  289. data/test/unit/ut_8_tree_to_dot.rb +1 -1
  290. data/test/unit/ut_9_xml_reader.rb +1 -1
  291. metadata +142 -63
  292. data/jruby_issue.txt +0 -32
  293. data/lib/ruote/engine/process_status.rb +0 -403
  294. data/lib/ruote/log/pretty.rb +0 -165
  295. data/lib/ruote/log/test_logger.rb +0 -204
  296. data/lib/ruote/util/serializer.rb +0 -103
  297. data/phil.txt +0 -14
  298. data/test/functional/eft_33_let.rb +0 -31
  299. data/test/functional/ft_19_alias.rb +0 -33
  300. data/test/functional/ft_47_wfid_generator.rb +0 -54
  301. data/test/unit/storage.rb +0 -403
  302. data/test/unit/storages.rb +0 -37
  303. data/test/unit/ut_13_serializer.rb +0 -65
  304. data/test/unit/ut_18_engine.rb +0 -47
  305. data/test/unit/ut_3_wait_logger.rb +0 -39
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -32,18 +32,14 @@ module Ruote
32
32
  m = m.to_s
33
33
 
34
34
  if m[-1, 1] == '='
35
-
36
- val = args.first
37
- self[m[0..-2]] = val
38
-
39
- return val
40
-
35
+ if args.first.nil?
36
+ self.delete(m[0..-2]); nil
37
+ else
38
+ self[m[0..-2]] = args.first
39
+ end
41
40
  else
42
-
43
- return self[m] #if self.has_key?(m)
41
+ self[m]
44
42
  end
45
-
46
- #super
47
43
  end
48
44
 
49
45
  def dump
@@ -55,9 +51,15 @@ module Ruote
55
51
  s << "\n"
56
52
  end
57
53
  s << "~~ . ~~"
58
-
59
- s
60
54
  end
55
+
56
+ #--
57
+ # Useful when debugging some 'stack too deep' issue
58
+ #
59
+ #def self.included(target)
60
+ # raise target.to_s unless target.to_s.match(/\bHash\b/)
61
+ #end
62
+ #++
61
63
  end
62
64
 
63
65
  module WithH
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -25,23 +25,49 @@
25
25
 
26
26
  module Ruote
27
27
 
28
+ #--
29
+ # methods that accept a small "dot notation" for looking up
30
+ # into nested hashes and arrays
31
+ #++
32
+
28
33
  # h = { 'a' => { 'b' => [ 1, 3, 4 ] } }
29
34
  #
30
35
  # p Ruote.lookup(h, 'a.b.1') # => 3
31
36
  #
32
- def Ruote.lookup(collection, key, container_lookup=false)
37
+ def self.lookup(collection, key, container_lookup=false)
33
38
 
34
39
  return collection if key == '.'
35
40
 
36
41
  key, rest = pop_key(key)
37
- value = flookup(collection, key)
42
+ value = fetch(collection, key)
38
43
 
39
44
  return [ key, collection ] if container_lookup && rest.size == 0
40
45
  return [ rest.first, value ] if container_lookup && rest.size == 1
41
46
  return value if rest.size == 0
42
47
  return nil if value == nil
43
48
 
44
- lookup(value, rest)
49
+ lookup(value, rest, container_lookup)
50
+ end
51
+
52
+ # h = { 'a' => { 'b' => [ 1, 3, 4 ] } }
53
+ #
54
+ # p Ruote.lookup(h, 'a.b.1') # => true
55
+ #
56
+ def self.has_key?(collection, key)
57
+
58
+ return collection if key == '.'
59
+
60
+ key, rest = pop_key(key)
61
+
62
+ return has_key?(fetch(collection, key), rest) if rest.any?
63
+
64
+ if collection.respond_to?(:has_key?)
65
+ collection.has_key?(key)
66
+ elsif collection.respond_to?(:[])
67
+ key.to_i < collection.size
68
+ else
69
+ false
70
+ end
45
71
  end
46
72
 
47
73
  # h = { 'customer' => { 'name' => 'alpha' } }
@@ -50,7 +76,7 @@ module Ruote
50
76
  #
51
77
  # h #=> { 'customer' => { 'name' => 'bravo' } }
52
78
  #
53
- def Ruote.set(collection, key, value)
79
+ def self.set(collection, key, value)
54
80
 
55
81
  k, c = lookup(collection, key, true)
56
82
 
@@ -68,47 +94,59 @@ module Ruote
68
94
  # h # => { 'customer' => { 'name' => 'alpha' } }
69
95
  # r # => '1st'
70
96
  #
71
- def Ruote.unset(collection, key)
97
+ def self.unset(collection, key)
72
98
 
73
99
  k, c = lookup(collection, key, true)
74
100
 
75
- return collection.delete(key) unless c
76
-
77
- if c.is_a?(Array)
101
+ if c.nil?
102
+ collection.delete(key)
103
+ elsif c.is_a?(Array)
78
104
  c.delete_at(Integer(k)) rescue nil
79
- else
105
+ elsif c.is_a?(Hash)
80
106
  c.delete(k)
107
+ else
108
+ nil
81
109
  end
82
110
  end
83
111
 
84
112
  protected # well...
85
113
 
86
- def Ruote.pop_key(key)
114
+ # Pops the first key in a path key.
115
+ #
116
+ # Ruote.pop_key('a.b.c') # => 'a'
117
+ # Ruote.pop_key('1.2.3') # => 1
118
+ #
119
+ # (note the narrowing to an int that happens)
120
+ #
121
+ def self.pop_key(key)
87
122
 
88
123
  ks = key.is_a?(String) ? key.split('.') : key
89
124
 
90
125
  [ narrow_key(ks.first), ks[1..-1] ]
91
126
  end
92
127
 
93
- def Ruote.narrow_key(key)
94
-
95
- return 0 if key == '0'
96
-
97
- i = key.to_i
98
- return i if i != 0
128
+ # If the key holds an integer returns it, else return the key as is.
129
+ #
130
+ def self.narrow_key(key)
99
131
 
100
- key
132
+ key.match(/^-?\d+$/) ? key.to_i : key
101
133
  end
102
134
 
103
- def Ruote.flookup(collection, key)
135
+ # Given a collection and a key returns the corresponding value
136
+ #
137
+ # Ruote.fetch([ 12, 13, 24 ], 1) # => 13
138
+ # Ruote.fetch({ '1' => 13 }, 1) # => 13
139
+ # Ruote.fetch({ 1 => 13 }, 1) # => 13
140
+ #
141
+ def self.fetch(collection, key)
104
142
 
105
143
  value = (collection[key] rescue nil)
106
144
 
107
145
  if value == nil and key.is_a?(Fixnum)
108
- value = (collection[key.to_s] rescue nil)
146
+ (collection[key.to_s] rescue nil)
147
+ else
148
+ value
109
149
  end
110
-
111
- value
112
150
  end
113
151
  end
114
152
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,8 @@
22
22
  # Made in Japan.
23
23
  #++
24
24
 
25
+ require 'socket'
26
+
25
27
 
26
28
  module Ruote
27
29
 
@@ -82,7 +84,7 @@ module Ruote
82
84
  value = fulldup(value)
83
85
  begin
84
86
  o.instance_variable_set(v, value)
85
- rescue => e
87
+ rescue
86
88
  # ignore, must be readonly
87
89
  end
88
90
  end
@@ -124,22 +126,23 @@ module Ruote
124
126
  s.split('::').inject(Object) { |c, n| n == '' ? c : c.const_get(n) }
125
127
  end
126
128
 
127
- # # Upon receiving something like
128
- # #
129
- # # "(?-mix:nada)"
130
- # #
131
- # # will return
132
- # #
133
- # # /nada/
134
- # #
135
- # def self.regex_from_s(s)
136
- #
137
- # if s.is_a?(String) && m = s.match(/^\(\?-mix:(.+)\)$/)
138
- # Regexp.new(m[1])
139
- # else
140
- # nil
141
- # end
142
- # end
129
+ # Makes sure all they keys in the given hash are turned into strings
130
+ # in the resulting hash.
131
+ #
132
+ def self.keys_to_s(h)
133
+
134
+ h.remap { |(k, v), h| h[k.to_s] = v }
135
+ end
136
+
137
+ # Makes sure all they keys in the given hash are turned into symbols
138
+ # in the resulting hash.
139
+ #
140
+ # Mostly used in ruote-amqp.
141
+ #
142
+ def self.keys_to_sym(h)
143
+
144
+ h.remap { |(k, v), h| h[k.to_sym] = v }
145
+ end
143
146
 
144
147
  REGEX_IN_STRING = /^\s*\/(.*)\/\s*$/
145
148
 
@@ -155,5 +158,47 @@ module Ruote
155
158
  s
156
159
  end
157
160
  end
161
+
162
+ # From http://coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/
163
+ #
164
+ # Returns the (one of the) local IP address.
165
+ #
166
+ def self.local_ip
167
+
168
+ orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
169
+ # turn off reverse DNS resolution temporarily
170
+
171
+ UDPSocket.open do |s|
172
+ s.connect('64.233.187.99', 1)
173
+ s.addr.last
174
+ end
175
+
176
+ rescue
177
+
178
+ nil
179
+
180
+ ensure
181
+ Socket.do_not_reverse_lookup = orig
182
+ end
183
+
184
+ # Attempts to parse a string of Ruby code (and return the AST).
185
+ #
186
+ def self.parse_ruby(ruby_string)
187
+
188
+ Rufus::TreeChecker.parse(ruby_string)
189
+
190
+ rescue NoMethodError
191
+
192
+ raise NoMethodError.new(
193
+ "/!\\ please upgrade your rufus-treechecker gem /!\\")
194
+ end
195
+
196
+ # Returns an array. If the argument is an array, return it as is. Else
197
+ # turns the argument into a string and "comma splits" it.
198
+ #
199
+ def self.comma_split(o)
200
+
201
+ o.is_a?(Array) ? o : o.to_s.split(/\s*,\s*/).collect { |e| e.strip }
202
+ end
158
203
  end
159
204
 
@@ -0,0 +1,53 @@
1
+ #--
2
+ # Copyright (c) 2005-2012, 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
+ # Adding some 1.9 methods to 1.8 Rubies.
27
+ #
28
+ unless {}.respond_to?(:each_with_object)
29
+
30
+ module Enumerable
31
+
32
+ def each_with_object(o, &block)
33
+
34
+ self.inject(o) do |oo, e|
35
+ block.call(e, oo)
36
+ oo
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ class Hash
43
+
44
+ # A shortcut for
45
+ #
46
+ # hash.each_with_object({}) { |(k, v), h)| ... }
47
+ #
48
+ def remap(&block)
49
+
50
+ each_with_object({}, &block)
51
+ end
52
+ end
53
+
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -26,7 +26,6 @@
26
26
  # note, it's ometa, not omerta.
27
27
  #++
28
28
 
29
-
30
29
  module Ruote
31
30
 
32
31
  # meta a la lucky stiff
@@ -0,0 +1,177 @@
1
+ #--
2
+ # Copyright (c) 2012, Hartog de Mik <hartog@organisedminds.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 Germany.
23
+ #++
24
+
25
+ module Ruote
26
+
27
+ # A base class for process observers, just to provide convenience. It
28
+ # (heavily) sugar coats the Ruote::Observer and translate the messages into
29
+ # actions. Each such action is provided with pre-distilled information
30
+ # relevant for processes.
31
+ #
32
+ # == Example implementation
33
+ # class WebsocketSubscriber < Ruote::ProcessObserver
34
+ # # override initialize to warm-up a websocket client
35
+ # def initialize(context, options={})
36
+ # super
37
+ # @client = WebsocketClient.new()
38
+ # end
39
+ #
40
+ # # tell the listeners that a new process launched
41
+ # def on_launch(wfid, opts)
42
+ # @client.publish(
43
+ # "/process/launch",
44
+ # { :name => opts[:workitem].wf_name,
45
+ # :wfid => wfid,
46
+ # :definition => opts[:pdef],
47
+ # }
48
+ # )
49
+ # end
50
+ #
51
+ # # tell the listeners that a new process ended
52
+ # def on_end(wfid)
53
+ # @client.publish("/process/#{wfid}", { :end => true })
54
+ # end
55
+ # end
56
+ #
57
+ # == Actions
58
+ # The ProcessObserver adheres closely to the message actions, it calls the
59
+ # following methods:
60
+ #
61
+ # on_launch:: When a process or sub-process starts
62
+ # on_terminated:: When a process ends
63
+ # on_error_intercepted:: When an error was intercepted
64
+ # on_cancel:: When a process or sub-process was canceled
65
+ # on_dispatch:: When a participant is dispatched
66
+ # on_receive:: Whenever a workitem is received
67
+ #
68
+ # And others, but if you are interested in those; you might be better of
69
+ # using the more low-level Ruote::Observer
70
+ #
71
+ # == Arguments
72
+ # The methods are called with (wfid[, options])
73
+ #
74
+ # You can provide a method-signature like:
75
+ #
76
+ # def on_launch(wfid, options)
77
+ # def on_launch(wfid)
78
+ #
79
+ # If the ProcessObserver cannot call the method with the options, it tries
80
+ # to call without options
81
+ #
82
+ # === Options
83
+ # The following options are provided:
84
+ #
85
+ # :workitem:: The workitem, if available
86
+ # :action:: The original name of the action
87
+ # :child:: Boolean; This is an event of a child, or sub-flow
88
+ # :error:: The intercepted error (only provided with
89
+ # #on_error_intercepted)
90
+ # :pdef:: The (sub-)process definition (only provided with #on_launch)
91
+ # :variables:: The process variables, if available
92
+ # :flavour:: The flavour of canceling (only on_cancel)
93
+ #
94
+ # == Error handling
95
+ #
96
+ # If anywhere in your implementation an action raises an error, it is caught
97
+ # by the ProcessObserver and silently ignored.
98
+ #
99
+ class ProcessObserver
100
+
101
+ attr_reader :context, :options, :filtered_actions
102
+
103
+ def initialize(context, options={})
104
+ @filtered_actions = options.delete(:filtered_actions)
105
+ @filtered_actions ||= []
106
+ @filtered_actions |= %w[dispatched participant_registered variable_set]
107
+
108
+ @context = context
109
+ @options = options
110
+ end
111
+
112
+ def on_msg(msg) # :nodoc:
113
+
114
+ return if @filtered_actions.include? msg['action']
115
+
116
+ wfid = msg['wfid']
117
+ child = false
118
+
119
+ if !wfid && msg['parent_id']
120
+ wfid = msg['parent_id']['wfid']
121
+ child = true
122
+ end
123
+
124
+ wfid ||= Ruote.extract_wfid(msg)
125
+ return if !wfid
126
+
127
+ workitem = begin
128
+ if msg['workitem']
129
+ Ruote::Workitem.new(Rufus::Json.dup(msg['workitem']))
130
+ else
131
+ Ruote::Workitem.new({})
132
+ end
133
+ rescue
134
+ Ruote::Workitem.new({})
135
+ end
136
+
137
+ data = {
138
+ :workitem => workitem,
139
+ :action => msg['action'],
140
+ :child => child,
141
+ :variables => msg['variables'],
142
+ }
143
+
144
+ # the prelimenary method name
145
+ method = msg['action'].split('_').first
146
+
147
+ # change method or fields based on the action
148
+ case msg['action']
149
+ when 'launch'
150
+ data[:pdef] = msg['tree']
151
+
152
+ when 'cancel'
153
+ data[:flavour] = msg['flavour']
154
+
155
+ when 'error_intercepted'
156
+ error = Kernel.const_get(msg['error']['class']).new(msg['error']['message'])
157
+ error.set_backtrace msg['error']['trace']
158
+
159
+ data[:error] = error
160
+ method = msg['action']
161
+ end
162
+
163
+ callback = "on_#{method}"
164
+ if self.respond_to?(callback)
165
+ args = [ wfid ]
166
+ args << data if self.method(callback).arity.abs == 2
167
+
168
+ self.send(callback, *args)
169
+ end
170
+
171
+ return
172
+ rescue
173
+ return
174
+ end
175
+
176
+ end
177
+ end