ruote 2.1.11 → 2.2.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 (217) hide show
  1. data/CHANGELOG.txt +60 -0
  2. data/CREDITS.txt +22 -4
  3. data/LICENSE.txt +1 -1
  4. data/README.rdoc +6 -7
  5. data/Rakefile +58 -59
  6. data/TODO.txt +137 -65
  7. data/couch_url.txt +1 -0
  8. data/jruby_issue.txt +32 -0
  9. data/lib/ruote.rb +1 -1
  10. data/lib/ruote/context.rb +12 -10
  11. data/lib/ruote/engine.rb +280 -145
  12. data/lib/ruote/engine/process_error.rb +5 -5
  13. data/lib/ruote/engine/process_status.rb +47 -28
  14. data/lib/ruote/exp/command.rb +7 -10
  15. data/lib/ruote/exp/commanded.rb +2 -2
  16. data/lib/ruote/exp/condition.rb +130 -43
  17. data/lib/ruote/exp/fe_add_branches.rb +2 -2
  18. data/lib/ruote/exp/fe_apply.rb +1 -1
  19. data/lib/ruote/exp/fe_cancel_process.rb +3 -3
  20. data/lib/ruote/exp/fe_command.rb +3 -3
  21. data/lib/ruote/exp/fe_concurrence.rb +4 -4
  22. data/lib/ruote/exp/fe_concurrent_iterator.rb +17 -5
  23. data/lib/ruote/exp/fe_cron.rb +3 -3
  24. data/lib/ruote/exp/fe_cursor.rb +5 -5
  25. data/lib/ruote/exp/fe_define.rb +3 -3
  26. data/lib/ruote/exp/fe_echo.rb +3 -3
  27. data/lib/ruote/exp/fe_equals.rb +2 -2
  28. data/lib/ruote/exp/fe_error.rb +2 -2
  29. data/lib/ruote/exp/fe_filter.rb +519 -0
  30. data/lib/ruote/exp/fe_forget.rb +9 -2
  31. data/lib/ruote/exp/fe_given.rb +154 -0
  32. data/lib/ruote/exp/fe_if.rb +16 -13
  33. data/lib/ruote/exp/fe_inc.rb +3 -3
  34. data/lib/ruote/exp/fe_iterator.rb +4 -4
  35. data/lib/ruote/exp/fe_let.rb +75 -0
  36. data/lib/ruote/exp/fe_listen.rb +68 -12
  37. data/lib/ruote/exp/fe_lose.rb +110 -0
  38. data/lib/ruote/exp/fe_noop.rb +1 -1
  39. data/lib/ruote/exp/{fe_when.rb → fe_once.rb} +25 -21
  40. data/lib/ruote/exp/fe_participant.rb +14 -17
  41. data/lib/ruote/exp/fe_redo.rb +10 -6
  42. data/lib/ruote/exp/fe_ref.rb +1 -1
  43. data/lib/ruote/exp/fe_registerp.rb +112 -0
  44. data/lib/ruote/exp/fe_reserve.rb +3 -3
  45. data/lib/ruote/exp/fe_restore.rb +2 -2
  46. data/lib/ruote/exp/fe_save.rb +2 -2
  47. data/lib/ruote/exp/fe_sequence.rb +3 -4
  48. data/lib/ruote/exp/fe_set.rb +16 -7
  49. data/lib/ruote/exp/fe_subprocess.rb +23 -1
  50. data/lib/ruote/exp/fe_that.rb +92 -0
  51. data/lib/ruote/exp/fe_undo.rb +3 -3
  52. data/lib/ruote/exp/fe_unregisterp.rb +71 -0
  53. data/lib/ruote/exp/fe_wait.rb +2 -2
  54. data/lib/ruote/exp/flowexpression.rb +153 -78
  55. data/lib/ruote/exp/iterator.rb +2 -2
  56. data/lib/ruote/exp/merge.rb +2 -2
  57. data/lib/ruote/exp/ro_attributes.rb +14 -12
  58. data/lib/ruote/exp/ro_filters.rb +136 -0
  59. data/lib/ruote/exp/ro_persist.rb +51 -35
  60. data/lib/ruote/exp/ro_variables.rb +18 -27
  61. data/lib/ruote/fei.rb +73 -33
  62. data/lib/ruote/id/mnemo_wfid_generator.rb +1 -1
  63. data/lib/ruote/id/wfid_generator.rb +11 -4
  64. data/lib/ruote/log/default_history.rb +122 -0
  65. data/lib/ruote/log/pretty.rb +36 -8
  66. data/lib/ruote/log/storage_history.rb +37 -5
  67. data/lib/ruote/log/test_logger.rb +26 -24
  68. data/lib/ruote/log/wait_logger.rb +5 -3
  69. data/lib/ruote/part/block_participant.rb +22 -11
  70. data/lib/ruote/part/engine_participant.rb +6 -7
  71. data/lib/ruote/part/local_participant.rb +6 -12
  72. data/lib/ruote/part/no_op_participant.rb +4 -4
  73. data/lib/ruote/part/null_participant.rb +4 -4
  74. data/lib/ruote/part/smtp_participant.rb +4 -4
  75. data/lib/ruote/part/storage_participant.rb +40 -20
  76. data/lib/ruote/part/template.rb +4 -4
  77. data/lib/ruote/participant.rb +0 -1
  78. data/lib/ruote/{parser.rb → reader.rb} +30 -25
  79. data/lib/ruote/{parser → reader}/ruby_dsl.rb +28 -11
  80. data/lib/ruote/{parser → reader}/xml.rb +6 -5
  81. data/lib/ruote/receiver/base.rb +35 -13
  82. data/lib/ruote/storage/base.rb +20 -18
  83. data/lib/ruote/storage/composite_storage.rb +10 -10
  84. data/lib/ruote/storage/fs_storage.rb +17 -10
  85. data/lib/ruote/storage/hash_storage.rb +29 -18
  86. data/lib/ruote/svc/dispatch_pool.rb +41 -14
  87. data/lib/ruote/svc/dollar_sub.rb +50 -17
  88. data/lib/ruote/svc/error_handler.rb +19 -11
  89. data/lib/ruote/svc/expression_map.rb +4 -4
  90. data/lib/ruote/svc/participant_list.rb +105 -100
  91. data/lib/ruote/svc/tracker.rb +58 -18
  92. data/lib/ruote/svc/treechecker.rb +51 -24
  93. data/lib/ruote/tree_dot.rb +4 -4
  94. data/lib/ruote/util/filter.rb +440 -0
  95. data/lib/ruote/util/hashdot.rb +4 -4
  96. data/lib/ruote/util/look.rb +2 -6
  97. data/lib/ruote/util/lookup.rb +9 -7
  98. data/lib/ruote/util/misc.rb +40 -8
  99. data/lib/ruote/util/ometa.rb +1 -1
  100. data/lib/ruote/util/serializer.rb +4 -4
  101. data/lib/ruote/util/subprocess.rb +29 -9
  102. data/lib/ruote/util/time.rb +4 -4
  103. data/lib/ruote/util/tree.rb +3 -3
  104. data/lib/ruote/version.rb +2 -2
  105. data/lib/ruote/worker.rb +55 -32
  106. data/lib/ruote/workitem.rb +64 -11
  107. data/ruote.gemspec +31 -302
  108. data/test/bm/launch_bench.rb +37 -0
  109. data/test/functional/base.rb +60 -18
  110. data/test/functional/concurrent_base.rb +2 -2
  111. data/test/functional/ct_0_concurrence.rb +1 -1
  112. data/test/functional/ct_1_iterator.rb +1 -1
  113. data/test/functional/ct_2_cancel.rb +1 -1
  114. data/test/functional/eft_0_process_definition.rb +2 -2
  115. data/test/functional/eft_10_cancel_process.rb +1 -1
  116. data/test/functional/eft_11_wait.rb +19 -11
  117. data/test/functional/eft_12_listen.rb +79 -13
  118. data/test/functional/eft_13_iterator.rb +13 -10
  119. data/test/functional/eft_14_cursor.rb +98 -9
  120. data/test/functional/eft_15_loop.rb +6 -4
  121. data/test/functional/eft_16_if.rb +12 -0
  122. data/test/functional/eft_18_concurrent_iterator.rb +31 -32
  123. data/test/functional/eft_19_reserve.rb +4 -4
  124. data/test/functional/eft_1_echo.rb +9 -0
  125. data/test/functional/eft_20_save.rb +4 -4
  126. data/test/functional/{eft_28_when.rb → eft_28_once.rb} +33 -7
  127. data/test/functional/eft_30_ref.rb +17 -2
  128. data/test/functional/eft_31_registerp.rb +130 -0
  129. data/test/functional/eft_32_lose.rb +93 -0
  130. data/test/functional/eft_33_let.rb +31 -0
  131. data/test/functional/eft_34_given.rb +123 -0
  132. data/test/functional/eft_35_filter.rb +269 -0
  133. data/test/functional/eft_3_participant.rb +4 -6
  134. data/test/functional/eft_4_set.rb +16 -2
  135. data/test/functional/eft_5_subprocess.rb +2 -4
  136. data/test/functional/eft_6_concurrence.rb +29 -29
  137. data/test/functional/eft_8_undo.rb +39 -3
  138. data/test/functional/eft_9_redo.rb +94 -2
  139. data/test/functional/ft_10_dollar.rb +81 -2
  140. data/test/functional/ft_11_recursion.rb +13 -17
  141. data/test/functional/ft_12_launchitem.rb +9 -5
  142. data/test/functional/ft_13_variables.rb +7 -9
  143. data/test/functional/ft_14_re_apply.rb +6 -9
  144. data/test/functional/ft_15_timeout.rb +18 -18
  145. data/test/functional/ft_16_participant_params.rb +1 -3
  146. data/test/functional/ft_17_conditional.rb +25 -2
  147. data/test/functional/ft_18_kill.rb +65 -12
  148. data/test/functional/ft_1_process_status.rb +147 -71
  149. data/test/functional/ft_20_storage_participant.rb +0 -1
  150. data/test/functional/ft_21_forget.rb +82 -1
  151. data/test/functional/{ft_24_block_participants.rb → ft_24_block_participant.rb} +42 -11
  152. data/test/functional/ft_25_receiver.rb +47 -17
  153. data/test/functional/{ft_26_participant_timeout.rb → ft_26_participant_rtimeout.rb} +56 -19
  154. data/test/functional/ft_29_part_template.rb +6 -5
  155. data/test/functional/ft_2_errors.rb +21 -37
  156. data/test/functional/ft_30_smtp_participant.rb +1 -1
  157. data/test/functional/ft_31_part_blocking.rb +8 -6
  158. data/test/functional/ft_34_cursor_rewind.rb +13 -10
  159. data/test/functional/ft_35_add_service.rb +1 -1
  160. data/test/functional/ft_36_storage_history.rb +24 -1
  161. data/test/functional/ft_37_default_history.rb +109 -0
  162. data/test/functional/ft_38_participant_more.rb +10 -10
  163. data/test/functional/ft_39_wait_for.rb +12 -9
  164. data/test/functional/ft_3_participant_registration.rb +111 -32
  165. data/test/functional/ft_40_wait_logger.rb +2 -1
  166. data/test/functional/ft_41_participants.rb +30 -4
  167. data/test/functional/ft_43_participant_on_reply.rb +6 -23
  168. data/test/functional/ft_45_participant_accept.rb +4 -4
  169. data/test/functional/ft_46_launch_single.rb +36 -2
  170. data/test/functional/ft_47_wfid_generator.rb +54 -0
  171. data/test/functional/ft_48_lose.rb +112 -0
  172. data/test/functional/ft_49_engine_on_error.rb +201 -0
  173. data/test/functional/ft_4_cancel.rb +66 -6
  174. data/test/functional/ft_50_engine_config.rb +22 -0
  175. data/test/functional/ft_51_misc.rb +67 -0
  176. data/test/functional/ft_52_case.rb +134 -0
  177. data/test/functional/ft_53_engine_on_terminate.rb +95 -0
  178. data/test/functional/ft_54_patterns.rb +104 -0
  179. data/test/functional/{ft_37_engine_participant.rb → ft_55_engine_participant.rb} +4 -5
  180. data/test/functional/ft_56_filter_attribute.rb +259 -0
  181. data/test/functional/ft_5_on_error.rb +77 -30
  182. data/test/functional/ft_6_on_cancel.rb +66 -11
  183. data/test/functional/ft_7_tags.rb +94 -5
  184. data/test/functional/ft_8_participant_consumption.rb +36 -5
  185. data/test/functional/ft_9_subprocesses.rb +10 -10
  186. data/test/functional/rt_1_listen.rb +3 -3
  187. data/test/functional/{rt_3_when.rb → rt_3_once.rb} +4 -4
  188. data/test/functional/storage_helper.rb +15 -13
  189. data/test/functional/test.rb +1 -3
  190. data/test/test_helper.rb +0 -8
  191. data/test/unit/storage.rb +154 -10
  192. data/test/unit/{ut_0_ruby_parser.rb → ut_0_ruby_reader.rb} +61 -11
  193. data/test/unit/ut_11_lookup.rb +7 -0
  194. data/test/unit/ut_13_serializer.rb +1 -1
  195. data/test/unit/ut_15_util.rb +23 -0
  196. data/test/unit/{ut_16_parser.rb → ut_16_reader.rb} +11 -13
  197. data/test/unit/ut_1_fei.rb +57 -10
  198. data/test/unit/ut_20_composite_storage.rb +25 -11
  199. data/test/unit/ut_21_participant_list.rb +47 -0
  200. data/test/unit/ut_22_filter.rb +903 -0
  201. data/test/unit/ut_3_wait_logger.rb +2 -6
  202. data/test/unit/ut_6_condition.rb +164 -17
  203. data/test/unit/ut_7_workitem.rb +28 -0
  204. data/test/unit/ut_8_tree_to_dot.rb +1 -1
  205. data/test/unit/{ut_9_xml_parser.rb → ut_9_xml_reader.rb} +5 -5
  206. metadata +108 -84
  207. data/.gitignore +0 -4
  208. data/examples/barley.rb +0 -391
  209. data/examples/flickr_report.rb +0 -107
  210. data/examples/pong.rb +0 -37
  211. data/examples/ruote_quickstart.rb +0 -43
  212. data/examples/web_first_page.rb +0 -68
  213. data/lib/ruote/part/hash_participant.rb +0 -91
  214. data/test/README.rdoc +0 -15
  215. data/test/functional/crunner.sh +0 -19
  216. data/test/pdef.xml +0 -7
  217. data/test/unit/ut_2_wfidgen.rb +0 -21
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, Alain Hoang and John Mettraux.
2
+ # Copyright (c) 2005-2011, Alain Hoang and John Mettraux.
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
@@ -80,12 +80,12 @@ module Ruote
80
80
  include LocalParticipant
81
81
  include TemplateMixin
82
82
 
83
- def initialize (opts)
83
+ def initialize(opts)
84
84
 
85
85
  @opts = opts.inject({}) { |h, (k, v)| h[k.to_s] = v; h }
86
86
  end
87
87
 
88
- def consume (workitem)
88
+ def consume(workitem)
89
89
 
90
90
  to = workitem.fields['email_target'] || @opts['to']
91
91
  to = Array(to)
@@ -105,7 +105,7 @@ module Ruote
105
105
  reply_to_engine(workitem) if @opts['notification']
106
106
  end
107
107
 
108
- def cancel (fei, flavour)
108
+ def cancel(fei, flavour)
109
109
 
110
110
  # does nothing
111
111
  #
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2011, 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
@@ -57,26 +57,26 @@ module Ruote
57
57
 
58
58
  attr_accessor :context
59
59
 
60
- def initialize (engine_or_options={}, options=nil)
60
+ def initialize(engine_or_options={}, options=nil)
61
61
 
62
62
  if engine_or_options.respond_to?(:context)
63
63
  @context = engine_or_options.context
64
64
  elsif engine_or_options.is_a?(Ruote::Context)
65
65
  @context = engine_or_options
66
66
  else
67
- options = engine_or_options
67
+ @options = engine_or_options
68
68
  end
69
69
 
70
- options ||= {}
70
+ @options ||= {}
71
71
 
72
- @store_name = options['store_name']
72
+ @store_name = @options['store_name']
73
73
  end
74
74
 
75
75
  # No need for a separate thread when delivering to this participant.
76
76
  #
77
77
  def do_not_thread; true; end
78
78
 
79
- def consume (workitem)
79
+ def consume(workitem)
80
80
 
81
81
  doc = workitem.to_h
82
82
 
@@ -94,7 +94,7 @@ module Ruote
94
94
 
95
95
  # Removes the document/workitem from the storage
96
96
  #
97
- def cancel (fei, flavour)
97
+ def cancel(fei, flavour)
98
98
 
99
99
  doc = fetch(fei)
100
100
 
@@ -103,14 +103,14 @@ module Ruote
103
103
  cancel(fei, flavour) if r != nil
104
104
  end
105
105
 
106
- def [] (fei)
106
+ def [](fei)
107
107
 
108
108
  doc = fetch(fei)
109
109
 
110
110
  doc ? Ruote::Workitem.new(doc) : nil
111
111
  end
112
112
 
113
- def fetch (fei)
113
+ def fetch(fei)
114
114
 
115
115
  hfei = Ruote::FlowExpressionId.extract_h(fei)
116
116
 
@@ -119,7 +119,10 @@ module Ruote
119
119
 
120
120
  # Removes the workitem from the in-memory hash and replies to the engine.
121
121
  #
122
- def reply (workitem)
122
+ # TODO : should it raise if the workitem can't be found ?
123
+ # TODO : should it accept just the fei ?
124
+ #
125
+ def reply(workitem)
123
126
 
124
127
  # TODO: change method name (receiver mess cleanup)
125
128
 
@@ -143,14 +146,14 @@ module Ruote
143
146
 
144
147
  # Iterates over the workitems stored in here.
145
148
  #
146
- def each (&block)
149
+ def each(&block)
147
150
 
148
151
  all.each { |wi| block.call(wi) }
149
152
  end
150
153
 
151
154
  # Returns all the workitems stored in here.
152
155
  #
153
- def all (opts={})
156
+ def all(opts={})
154
157
 
155
158
  fetch_all(opts).map { |hwi| Ruote::Workitem.new(hwi) }
156
159
  end
@@ -167,7 +170,7 @@ module Ruote
167
170
 
168
171
  # Return all workitems for the specified wfid
169
172
  #
170
- def by_wfid (wfid)
173
+ def by_wfid(wfid)
171
174
 
172
175
  @context.storage.get_many('workitems', wfid).collect { |hwi|
173
176
  Ruote::Workitem.new(hwi)
@@ -176,7 +179,7 @@ module Ruote
176
179
 
177
180
  # Returns all workitems for the specified participant name
178
181
  #
179
- def by_participant (participant_name, opts={})
182
+ def by_participant(participant_name, opts={})
180
183
 
181
184
  hwis = if @context.storage.respond_to?(:by_participant)
182
185
 
@@ -201,7 +204,7 @@ module Ruote
201
204
  # CouchStorage), the others will load all the workitems and then filter
202
205
  # them.
203
206
  #
204
- def by_field (field, value=nil)
207
+ def by_field(field, value=nil)
205
208
 
206
209
  hwis = if @context.storage.respond_to?(:by_field)
207
210
 
@@ -237,7 +240,7 @@ module Ruote
237
240
  # Note : the criteria is AND only, you'll have to do ORs (aggregation)
238
241
  # by yourself.
239
242
  #
240
- def query (criteria)
243
+ def query(criteria)
241
244
 
242
245
  cr = criteria.inject({}) { |h, (k, v)| h[k.to_s] = v; h }
243
246
 
@@ -269,12 +272,12 @@ module Ruote
269
272
  #
270
273
  def purge!
271
274
 
272
- fetch_all.each { |hwi| @context.storage.delete( hwi ) }
275
+ fetch_all.each { |hwi| @context.storage.delete(hwi) }
273
276
  end
274
277
 
275
278
  # Used by #query when filtering workitems.
276
279
  #
277
- def self.matches? (hwi, pname, criteria)
280
+ def self.matches?(hwi, pname, criteria)
278
281
 
279
282
  return false if pname && hwi['participant_name'] != pname
280
283
 
@@ -287,12 +290,29 @@ module Ruote
287
290
  true
288
291
  end
289
292
 
293
+ # Mostly a test method. Returns a Hash were keys are participant names
294
+ # and values are lists of workitems.
295
+ #
296
+ def per_participant
297
+
298
+ inject({}) { |h, wi| (h[wi.participant_name] ||= []) << wi; h }
299
+ end
300
+
301
+ # Mostly a test method. Returns a Hash were keys are participant names
302
+ # and values are integers, the count of workitems for a given participant
303
+ # name.
304
+ #
305
+ def per_participant_count
306
+
307
+ per_participant.inject({}) { |h, (k, v)| h[k] = v.size; h }
308
+ end
309
+
290
310
  protected
291
311
 
292
312
  # Fetches all the workitems. If there is a @store_name, will only fetch
293
313
  # the workitems in that store.
294
314
  #
295
- def fetch_all (opts={})
315
+ def fetch_all(opts={})
296
316
 
297
317
  @context.storage.get_many(
298
318
  'workitems',
@@ -302,7 +322,7 @@ module Ruote
302
322
 
303
323
  # Computes the id for the document representing the document in the storage.
304
324
  #
305
- def to_id (fei)
325
+ def to_id(fei)
306
326
 
307
327
  a = [ Ruote.to_storage_id(fei) ]
308
328
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2011, 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
@@ -41,7 +41,7 @@ module Ruote
41
41
 
42
42
  # Do the rendering.
43
43
  #
44
- def render_template (template, flow_expression, workitem)
44
+ def render_template(template, flow_expression, workitem)
45
45
 
46
46
  template = (File.read(template) rescue nil) if is_a_file?(template)
47
47
 
@@ -55,7 +55,7 @@ module Ruote
55
55
 
56
56
  # Simply returns a pretty-printed view of the workitem
57
57
  #
58
- def render_default_template (workitem)
58
+ def render_default_template(workitem)
59
59
 
60
60
  workitem = workitem.to_h if workitem.respond_to?(:to_h)
61
61
 
@@ -72,7 +72,7 @@ module Ruote
72
72
 
73
73
  protected
74
74
 
75
- def is_a_file? (s)
75
+ def is_a_file?(s)
76
76
 
77
77
  return false unless s
78
78
  return false if s.index("\n")
@@ -1,5 +1,4 @@
1
1
 
2
- require 'ruote/part/hash_participant'
3
2
  require 'ruote/part/storage_participant'
4
3
  require 'ruote/part/no_op_participant'
5
4
  require 'ruote/part/null_participant'
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2011, 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,20 +26,21 @@
26
26
  require 'uri'
27
27
  require 'open-uri'
28
28
  require 'rufus/json'
29
- require 'ruote/parser/ruby_dsl' # just making sure it's loaded
30
- require 'ruote/parser/xml'
29
+ require 'ruote/reader/ruby_dsl' # just making sure it's loaded
30
+ require 'ruote/reader/xml'
31
+ require 'ruote/util/subprocess'
31
32
 
32
33
 
33
34
  module Ruote
34
35
 
35
36
  #
36
- # A process definition parser.
37
+ # A process definition reader.
37
38
  #
38
- # Can parse XML, JSON, Ruby (and more) process definition representations.
39
+ # Can reader XML, JSON, Ruby (and more) process definition representations.
39
40
  #
40
- class Parser
41
+ class Reader
41
42
 
42
- def initialize (context)
43
+ def initialize(context)
43
44
 
44
45
  @context = context
45
46
  end
@@ -47,11 +48,11 @@ module Ruote
47
48
  # Turns the input into a ruote syntax tree (raw process definition).
48
49
  # This method is used by engine.launch(x) for example.
49
50
  #
50
- def parse (definition)
51
+ def read(definition)
51
52
 
52
- return definition if definition.is_a?(Array) and definition.size == 3
53
+ return definition if Ruote.is_tree?(definition)
53
54
 
54
- (return XmlParser.parse(definition)) rescue nil
55
+ (return XmlReader.read(definition)) rescue nil
55
56
  (return Rufus::Json.decode(definition)) rescue nil
56
57
  (return ruby_eval(definition)) rescue nil
57
58
 
@@ -59,31 +60,31 @@ module Ruote
59
60
 
60
61
  raise ArgumentError.new(
61
62
  "remote process definitions are not allowed"
62
- ) if Ruote::Parser.remote?(definition) && @context['remote_definition_allowed'] != true
63
+ ) if Ruote::Reader.remote?(definition) && @context['remote_definition_allowed'] != true
63
64
 
64
- return parse(open(definition).read)
65
+ return read(open(definition).read)
65
66
  end
66
67
 
67
68
  raise ArgumentError.new(
68
- "doesn't know how to parse definition (#{definition.class}) " +
69
+ "doesn't know how to read definition (#{definition.class}) " +
69
70
  "or error in process definition")
70
71
  end
71
72
 
72
73
  # Class method for parsing process definition (XML, Ruby, from file or
73
74
  # from a string, ...) to syntax trees. Used by ruote-fluo for example.
74
75
  #
75
- def self.parse (d)
76
+ def self.read(d)
76
77
 
77
- unless @parser
78
+ unless @reader
78
79
 
79
80
  require 'ostruct'
80
81
  require 'ruote/svc/treechecker'
81
82
 
82
- @parser = Ruote::Parser.new(
83
+ @reader = Ruote::Reader.new(
83
84
  OpenStruct.new('treechecker' => Ruote::TreeChecker.new({})))
84
85
  end
85
86
 
86
- @parser.parse(d)
87
+ @reader.read(d)
87
88
  end
88
89
 
89
90
  # Turns the given process definition tree (ruote syntax tree) to an XML
@@ -91,7 +92,7 @@ module Ruote
91
92
  #
92
93
  # Mainly used by ruote-fluo.
93
94
  #
94
- def self.to_xml (tree, options={})
95
+ def self.to_xml(tree, options={})
95
96
 
96
97
  require 'builder'
97
98
 
@@ -125,7 +126,7 @@ module Ruote
125
126
  #
126
127
  # Mainly used by ruote-fluo.
127
128
  #
128
- def self.to_ruby (tree, level=0)
129
+ def self.to_ruby(tree, level=0)
129
130
 
130
131
  expname = tree[0]
131
132
 
@@ -144,14 +145,14 @@ module Ruote
144
145
 
145
146
  # Turns the process definition tree (ruote syntax tree) to a JSON String.
146
147
  #
147
- def self.to_json (tree)
148
+ def self.to_json(tree)
148
149
 
149
150
  tree.to_json
150
151
  end
151
152
 
152
153
  # Returns true if the defintion is a remote URI
153
154
  #
154
- def self.remote? (definition)
155
+ def self.remote?(definition)
155
156
 
156
157
  u = URI.parse(definition)
157
158
 
@@ -164,23 +165,27 @@ module Ruote
164
165
  # treechecker, makes sure it doesn't code malicious ruby code (at least
165
166
  # tries very hard).
166
167
  #
167
- def ruby_eval (s)
168
+ def ruby_eval(s)
168
169
 
169
- @context.treechecker.check(s)
170
+ @context.treechecker.definition_check(s)
170
171
  eval(s)
171
172
 
172
173
  rescue Exception => e
174
+ #
175
+ # have to catch everything (SyntaxError included)
176
+
173
177
  #puts '=' * 80
174
178
  #p s
175
179
  #puts '-' * 80
176
180
  #puts e
177
181
  #e.backtrace.each { |l| puts l }
182
+
178
183
  raise ArgumentError.new('probably not ruby')
179
184
  end
180
185
 
181
186
  # A convenience method when building XML
182
187
  #
183
- def self.builder (options={}, &block)
188
+ def self.builder(options={}, &block)
184
189
 
185
190
  if b = options[:builder]
186
191
  block.call(b)
@@ -195,7 +200,7 @@ module Ruote
195
200
 
196
201
  # As used by to_ruby.
197
202
  #
198
- def self.atts_to_ruby (atts)
203
+ def self.atts_to_ruby(atts)
199
204
 
200
205
  return '' if atts.empty?
201
206
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2005-2011, 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
@@ -27,7 +27,7 @@ require 'ruote/util/ometa'
27
27
 
28
28
  module Ruote
29
29
 
30
- # Not really a parser, more an AST builder.
30
+ # Not really a reader, more an AST builder.
31
31
  #
32
32
  # pdef = Ruote.define :name => 'take_out_garbage' do
33
33
  # sequence do
@@ -39,7 +39,7 @@ module Ruote
39
39
  #
40
40
  # engine.launch(pdef)
41
41
  #
42
- def self.define (*attributes, &block)
42
+ def self.define(*attributes, &block)
43
43
 
44
44
  RubyDsl.create_branch('define', attributes, &block)
45
45
  end
@@ -55,7 +55,7 @@ module Ruote
55
55
  #
56
56
  # engine.launch(pdef)
57
57
  #
58
- def self.process_definition (*attributes, &block)
58
+ def self.process_definition(*attributes, &block)
59
59
 
60
60
  define(*attributes, &block)
61
61
  end
@@ -87,7 +87,7 @@ module Ruote
87
87
  # # cancels the segment of process at fei and replaces it with
88
88
  # # a simple alfred-bob sequence.
89
89
  #
90
- def self.to_tree (&block)
90
+ def self.to_tree(&block)
91
91
 
92
92
  RubyDsl.create_branch('x', {}, &block).last.first
93
93
  end
@@ -98,17 +98,16 @@ module Ruote
98
98
 
99
99
  class BranchContext < Ruote::BlankSlate
100
100
 
101
- def initialize (name, attributes)
101
+ def initialize(name, attributes)
102
102
 
103
103
  @name = name
104
104
  @attributes = attributes
105
105
  @children = []
106
106
  end
107
107
 
108
- def method_missing (m, *args, &block)
108
+ def method_missing(m, *args, &block)
109
109
 
110
- @children.push(
111
- Ruote::RubyDsl.create_branch(m.to_s, args, &block))
110
+ @children.push(Ruote::RubyDsl.create_branch(m.to_s, args, &block))
112
111
  end
113
112
 
114
113
  def to_a
@@ -117,22 +116,40 @@ module Ruote
117
116
  end
118
117
  end
119
118
 
120
- def self.create_branch (name, attributes, &block)
119
+ def self.create_branch(name, attributes, &block)
121
120
 
122
121
  name = name[1..-1] while name[0, 1] == '_'
123
122
 
124
123
  h = attributes.inject({}) { |h1, a|
124
+
125
125
  a.is_a?(Hash) ? h1.merge!(a) : h1[a] = nil
126
+
126
127
  h1
128
+
127
129
  }.inject({}) { |h1, (k, v)|
128
- h1[k.to_s] = v.is_a?(Symbol) ? v.to_s : v
130
+
131
+ k = k.is_a?(Regexp) ? k.inspect : k.to_s
132
+ h1[k] = to_json(v)
133
+
129
134
  h1
130
135
  }
131
136
 
132
137
  c = BranchContext.new(name, h)
133
138
  c.instance_eval(&block) if block
139
+
134
140
  c.to_a
135
141
  end
142
+
143
+ def self.to_json(v)
144
+
145
+ case v
146
+ when Symbol; v.to_s
147
+ when Regexp; v.inspect
148
+ when Array; v.collect { |e| to_json(e) }
149
+ when Hash; v.inject({}) { |h, (k, v)| h[k.to_s] = to_json(v); h }
150
+ else v
151
+ end
152
+ end
136
153
  end
137
154
  end
138
155