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.
- data/CHANGELOG.txt +166 -1
- data/CREDITS.txt +36 -17
- data/LICENSE.txt +1 -1
- data/README.rdoc +1 -7
- data/Rakefile +38 -29
- data/TODO.txt +93 -52
- data/lib/ruote-fs.rb +3 -0
- data/lib/ruote.rb +5 -1
- data/lib/ruote/context.rb +140 -35
- data/lib/ruote/dashboard.rb +1247 -0
- data/lib/ruote/{engine → dboard}/process_error.rb +22 -2
- data/lib/ruote/dboard/process_status.rb +587 -0
- data/lib/ruote/engine.rb +6 -871
- data/lib/ruote/exp/command.rb +7 -2
- data/lib/ruote/exp/commanded.rb +2 -2
- data/lib/ruote/exp/condition.rb +38 -13
- data/lib/ruote/exp/fe_add_branches.rb +1 -1
- data/lib/ruote/exp/fe_apply.rb +1 -1
- data/lib/ruote/exp/fe_await.rb +357 -0
- data/lib/ruote/exp/fe_cancel_process.rb +17 -3
- data/lib/ruote/exp/fe_command.rb +8 -4
- data/lib/ruote/exp/fe_concurrence.rb +218 -18
- data/lib/ruote/exp/fe_concurrent_iterator.rb +71 -10
- data/lib/ruote/exp/fe_cron.rb +3 -10
- data/lib/ruote/exp/fe_cursor.rb +14 -4
- data/lib/ruote/exp/fe_define.rb +3 -1
- data/lib/ruote/exp/fe_echo.rb +1 -1
- data/lib/ruote/exp/fe_equals.rb +1 -1
- data/lib/ruote/exp/fe_error.rb +1 -1
- data/lib/ruote/exp/fe_filter.rb +163 -4
- data/lib/ruote/exp/fe_forget.rb +21 -4
- data/lib/ruote/exp/fe_given.rb +1 -1
- data/lib/ruote/exp/fe_if.rb +1 -1
- data/lib/ruote/exp/fe_inc.rb +102 -35
- data/lib/ruote/exp/fe_iterator.rb +47 -12
- data/lib/ruote/exp/fe_listen.rb +96 -11
- data/lib/ruote/exp/fe_lose.rb +31 -4
- data/lib/ruote/exp/fe_noop.rb +1 -1
- data/lib/ruote/exp/fe_on_error.rb +109 -0
- data/lib/ruote/exp/fe_once.rb +10 -19
- data/lib/ruote/exp/fe_participant.rb +90 -28
- data/lib/ruote/exp/fe_read.rb +69 -0
- data/lib/ruote/exp/fe_redo.rb +3 -2
- data/lib/ruote/exp/fe_ref.rb +57 -27
- data/lib/ruote/exp/fe_registerp.rb +1 -3
- data/lib/ruote/exp/fe_reserve.rb +1 -1
- data/lib/ruote/exp/fe_restore.rb +6 -6
- data/lib/ruote/exp/fe_save.rb +12 -19
- data/lib/ruote/exp/fe_sequence.rb +38 -2
- data/lib/ruote/exp/fe_set.rb +143 -40
- data/lib/ruote/exp/{fe_let.rb → fe_stall.rb} +7 -38
- data/lib/ruote/exp/fe_subprocess.rb +8 -2
- data/lib/ruote/exp/fe_that.rb +1 -1
- data/lib/ruote/exp/fe_undo.rb +40 -4
- data/lib/ruote/exp/fe_unregisterp.rb +1 -3
- data/lib/ruote/exp/fe_wait.rb +12 -25
- data/lib/ruote/exp/{flowexpression.rb → flow_expression.rb} +375 -229
- data/lib/ruote/exp/iterator.rb +2 -2
- data/lib/ruote/exp/merge.rb +78 -17
- data/lib/ruote/exp/ro_attributes.rb +46 -36
- data/lib/ruote/exp/ro_filters.rb +34 -8
- data/lib/ruote/exp/ro_on_x.rb +431 -0
- data/lib/ruote/exp/ro_persist.rb +19 -7
- data/lib/ruote/exp/ro_timers.rb +123 -0
- data/lib/ruote/exp/ro_variables.rb +90 -29
- data/lib/ruote/fei.rb +57 -3
- data/lib/ruote/fs.rb +3 -0
- data/lib/ruote/id/mnemo_wfid_generator.rb +30 -7
- data/lib/ruote/id/wfid_generator.rb +17 -38
- data/lib/ruote/log/default_history.rb +23 -9
- data/lib/ruote/log/fancy_printing.rb +265 -0
- data/lib/ruote/log/storage_history.rb +23 -13
- data/lib/ruote/log/wait_logger.rb +224 -17
- data/lib/ruote/observer.rb +82 -0
- data/lib/ruote/part/block_participant.rb +65 -28
- data/lib/ruote/part/code_participant.rb +81 -0
- data/lib/ruote/part/engine_participant.rb +7 -2
- data/lib/ruote/part/local_participant.rb +221 -21
- data/lib/ruote/part/no_op_participant.rb +1 -1
- data/lib/ruote/part/null_participant.rb +1 -1
- data/lib/ruote/part/participant.rb +50 -0
- data/lib/ruote/part/rev_participant.rb +178 -0
- data/lib/ruote/part/smtp_participant.rb +2 -2
- data/lib/ruote/part/storage_participant.rb +228 -60
- data/lib/ruote/part/template.rb +1 -1
- data/lib/ruote/participant.rb +2 -0
- data/lib/ruote/reader.rb +205 -68
- data/lib/ruote/reader/json.rb +49 -0
- data/lib/ruote/reader/radial.rb +303 -0
- data/lib/ruote/reader/ruby_dsl.rb +44 -9
- data/lib/ruote/reader/xml.rb +11 -8
- data/lib/ruote/receiver/base.rb +98 -45
- data/lib/ruote/storage/base.rb +104 -35
- data/lib/ruote/storage/composite_storage.rb +50 -60
- data/lib/ruote/storage/fs_storage.rb +25 -34
- data/lib/ruote/storage/hash_storage.rb +38 -36
- data/lib/ruote/svc/dispatch_pool.rb +104 -35
- data/lib/ruote/svc/dollar_sub.rb +10 -8
- data/lib/ruote/svc/error_handler.rb +108 -52
- data/lib/ruote/svc/expression_map.rb +3 -3
- data/lib/ruote/svc/participant_list.rb +160 -55
- data/lib/ruote/svc/tracker.rb +31 -31
- data/lib/ruote/svc/treechecker.rb +28 -16
- data/lib/ruote/tree_dot.rb +1 -1
- data/lib/ruote/util/deep.rb +143 -0
- data/lib/ruote/util/filter.rb +125 -18
- data/lib/ruote/util/hashdot.rb +15 -13
- data/lib/ruote/util/look.rb +1 -1
- data/lib/ruote/util/lookup.rb +60 -22
- data/lib/ruote/util/misc.rb +63 -18
- data/lib/ruote/util/mpatch.rb +53 -0
- data/lib/ruote/util/ometa.rb +1 -2
- data/lib/ruote/util/process_observer.rb +177 -0
- data/lib/ruote/util/subprocess.rb +1 -1
- data/lib/ruote/util/time.rb +2 -2
- data/lib/ruote/util/tree.rb +64 -2
- data/lib/ruote/version.rb +3 -2
- data/lib/ruote/worker.rb +421 -92
- data/lib/ruote/workitem.rb +157 -22
- data/ruote.gemspec +15 -9
- data/test/bm/ci.rb +0 -2
- data/test/bm/ici.rb +0 -2
- data/test/bm/load_26c.rb +0 -3
- data/test/bm/mega.rb +0 -2
- data/test/functional/base.rb +57 -43
- data/test/functional/concurrent_base.rb +16 -13
- data/test/functional/ct_0_concurrence.rb +7 -11
- data/test/functional/ct_1_iterator.rb +9 -11
- data/test/functional/ct_2_cancel.rb +28 -17
- data/test/functional/eft_0_flow_expression.rb +35 -0
- data/test/functional/eft_10_cancel_process.rb +1 -1
- data/test/functional/eft_11_wait.rb +13 -13
- data/test/functional/eft_12_listen.rb +199 -66
- data/test/functional/eft_13_iterator.rb +95 -29
- data/test/functional/eft_14_cursor.rb +74 -24
- data/test/functional/eft_15_loop.rb +7 -7
- data/test/functional/eft_16_if.rb +1 -1
- data/test/functional/eft_17_equals.rb +1 -1
- data/test/functional/eft_18_concurrent_iterator.rb +156 -68
- data/test/functional/eft_19_reserve.rb +15 -15
- data/test/functional/eft_1_echo.rb +1 -1
- data/test/functional/eft_20_save.rb +51 -9
- data/test/functional/eft_21_restore.rb +1 -1
- data/test/functional/eft_22_noop.rb +1 -1
- data/test/functional/eft_23_apply.rb +1 -1
- data/test/functional/eft_24_add_branches.rb +7 -8
- data/test/functional/eft_25_command.rb +1 -1
- data/test/functional/eft_26_error.rb +11 -11
- data/test/functional/eft_27_inc.rb +111 -67
- data/test/functional/eft_28_once.rb +16 -16
- data/test/functional/eft_29_cron.rb +9 -9
- data/test/functional/eft_2_sequence.rb +23 -4
- data/test/functional/eft_30_ref.rb +36 -24
- data/test/functional/eft_31_registerp.rb +24 -24
- data/test/functional/eft_32_lose.rb +46 -20
- data/test/functional/eft_34_given.rb +1 -1
- data/test/functional/eft_35_filter.rb +161 -7
- data/test/functional/eft_36_read.rb +97 -0
- data/test/functional/{eft_0_process_definition.rb → eft_37_process_definition.rb} +4 -4
- data/test/functional/eft_38_on_error.rb +195 -0
- data/test/functional/eft_39_stall.rb +35 -0
- data/test/functional/eft_3_participant.rb +77 -22
- data/test/functional/eft_40_await.rb +297 -0
- data/test/functional/eft_4_set.rb +110 -11
- data/test/functional/eft_5_subprocess.rb +27 -5
- data/test/functional/eft_6_concurrence.rb +299 -60
- data/test/functional/eft_7_forget.rb +24 -22
- data/test/functional/eft_8_undo.rb +52 -15
- data/test/functional/eft_9_redo.rb +18 -20
- data/test/functional/ft_0_worker.rb +122 -13
- data/test/functional/ft_10_dollar.rb +77 -16
- data/test/functional/ft_11_recursion.rb +9 -9
- data/test/functional/ft_12_launchitem.rb +7 -9
- data/test/functional/ft_13_variables.rb +125 -22
- data/test/functional/ft_14_re_apply.rb +112 -56
- data/test/functional/ft_15_timeout.rb +64 -33
- data/test/functional/ft_16_participant_params.rb +59 -6
- data/test/functional/ft_17_conditional.rb +68 -2
- data/test/functional/ft_18_kill.rb +48 -30
- data/test/functional/ft_19_participant_code.rb +67 -0
- data/test/functional/ft_1_process_status.rb +222 -150
- data/test/functional/ft_20_storage_participant.rb +445 -44
- data/test/functional/ft_21_forget.rb +21 -26
- data/test/functional/ft_22_process_definitions.rb +8 -6
- data/test/functional/ft_23_load_defs.rb +29 -5
- data/test/functional/ft_24_block_participant.rb +199 -20
- data/test/functional/ft_25_receiver.rb +98 -46
- data/test/functional/ft_26_participant_rtimeout.rb +34 -26
- data/test/functional/ft_27_var_indirection.rb +40 -5
- data/test/functional/ft_28_null_noop_participants.rb +5 -5
- data/test/functional/ft_29_part_template.rb +2 -2
- data/test/functional/ft_2_errors.rb +106 -74
- data/test/functional/ft_30_smtp_participant.rb +7 -7
- data/test/functional/ft_31_part_blocking.rb +11 -11
- data/test/functional/ft_32_scope.rb +50 -0
- data/test/functional/ft_33_participant_subprocess_priority.rb +3 -3
- data/test/functional/ft_34_cursor_rewind.rb +14 -14
- data/test/functional/ft_35_add_service.rb +67 -9
- data/test/functional/ft_36_storage_history.rb +92 -24
- data/test/functional/ft_37_default_history.rb +35 -23
- data/test/functional/ft_38_participant_more.rb +189 -32
- data/test/functional/ft_39_wait_for.rb +25 -25
- data/test/functional/ft_3_participant_registration.rb +235 -107
- data/test/functional/ft_40_wait_logger.rb +105 -18
- data/test/functional/ft_41_participants.rb +13 -12
- data/test/functional/ft_42_storage_copy.rb +12 -12
- data/test/functional/ft_43_participant_on_reply.rb +85 -11
- data/test/functional/ft_44_var_participant.rb +5 -5
- data/test/functional/ft_45_participant_accept.rb +3 -3
- data/test/functional/ft_46_launch_single.rb +17 -17
- data/test/functional/ft_47_wfids.rb +41 -0
- data/test/functional/ft_48_lose.rb +19 -25
- data/test/functional/ft_49_engine_on_error.rb +54 -70
- data/test/functional/ft_4_cancel.rb +84 -26
- data/test/functional/ft_50_engine_config.rb +4 -4
- data/test/functional/ft_51_misc.rb +12 -12
- data/test/functional/ft_52_case.rb +17 -17
- data/test/functional/ft_53_engine_on_terminate.rb +18 -21
- data/test/functional/ft_54_patterns.rb +18 -16
- data/test/functional/ft_55_engine_participant.rb +55 -55
- data/test/functional/ft_56_filter_attribute.rb +90 -52
- data/test/functional/ft_57_rev_participant.rb +252 -0
- data/test/functional/ft_58_workitem.rb +150 -0
- data/test/functional/ft_59_pause.rb +329 -0
- data/test/functional/ft_5_on_error.rb +430 -77
- data/test/functional/ft_60_code_participant.rb +65 -0
- data/test/functional/ft_61_trailing_fields.rb +34 -0
- data/test/functional/ft_62_exp_name_and_dollar_substitution.rb +35 -0
- data/test/functional/ft_63_participants_221.rb +458 -0
- data/test/functional/ft_64_stash.rb +41 -0
- data/test/functional/ft_65_timers.rb +313 -0
- data/test/functional/ft_66_flank.rb +133 -0
- data/test/functional/ft_67_radial_misc.rb +34 -0
- data/test/functional/ft_68_reput.rb +72 -0
- data/test/functional/ft_69_worker_info.rb +56 -0
- data/test/functional/ft_6_on_cancel.rb +189 -36
- data/test/functional/ft_70_take_and_discard_attributes.rb +94 -0
- data/test/functional/ft_71_retries.rb +144 -0
- data/test/functional/ft_72_on_terminate.rb +60 -0
- data/test/functional/ft_73_raise_msg.rb +107 -0
- data/test/functional/ft_74_respark.rb +106 -0
- data/test/functional/ft_75_context.rb +66 -0
- data/test/functional/ft_76_observer.rb +53 -0
- data/test/functional/ft_77_process_observer.rb +157 -0
- data/test/functional/ft_78_part_participant.rb +37 -0
- data/test/functional/ft_7_tags.rb +238 -50
- data/test/functional/ft_8_participant_consumption.rb +27 -21
- data/test/functional/ft_9_subprocesses.rb +48 -18
- data/test/functional/restart_base.rb +4 -6
- data/test/functional/rt_0_wait.rb +10 -10
- data/test/functional/rt_1_listen.rb +6 -6
- data/test/functional/rt_2_errors.rb +12 -12
- data/test/functional/rt_3_once.rb +17 -12
- data/test/functional/rt_4_cron.rb +17 -17
- data/test/functional/rt_5_timeout.rb +13 -13
- data/test/functional/signals.rb +103 -0
- data/test/functional/storage.rb +730 -0
- data/test/functional/storage_helper.rb +48 -35
- data/test/functional/test.rb +6 -2
- data/test/misc/idle.rb +21 -0
- data/test/misc/light.rb +29 -0
- data/test/path_helper.rb +1 -1
- data/test/test.rb +2 -5
- data/test/test_helper.rb +13 -0
- data/test/unit/test.rb +1 -4
- data/test/unit/ut_0_ruby_reader.rb +25 -9
- data/test/unit/ut_10_participants.rb +47 -0
- data/test/unit/ut_11_lookup.rb +59 -2
- data/test/unit/ut_12_wait_logger.rb +123 -0
- data/test/unit/ut_14_is_uri.rb +1 -1
- data/test/unit/ut_15_util.rb +1 -1
- data/test/unit/ut_16_reader.rb +136 -14
- data/test/unit/ut_17_merge.rb +155 -0
- data/test/unit/ut_19_part_template.rb +1 -1
- data/test/unit/ut_1_fei.rb +11 -2
- data/test/unit/ut_20_composite_storage.rb +27 -1
- data/test/unit/{ut_21_participant_list.rb → ut_21_svc_participant_list.rb} +2 -3
- data/test/unit/ut_22_filter.rb +231 -10
- data/test/unit/ut_23_svc_tracker.rb +48 -0
- data/test/unit/ut_24_radial_reader.rb +458 -0
- data/test/unit/ut_25_process_status.rb +143 -0
- data/test/unit/ut_26_deep.rb +131 -0
- data/test/unit/ut_2_dashboard.rb +114 -0
- data/test/unit/ut_3_worker.rb +54 -0
- data/test/unit/ut_4_expmap.rb +1 -1
- data/test/unit/ut_5_tree.rb +23 -23
- data/test/unit/ut_6_condition.rb +71 -29
- data/test/unit/ut_7_workitem.rb +18 -4
- data/test/unit/ut_8_tree_to_dot.rb +1 -1
- data/test/unit/ut_9_xml_reader.rb +1 -1
- metadata +142 -63
- data/jruby_issue.txt +0 -32
- data/lib/ruote/engine/process_status.rb +0 -403
- data/lib/ruote/log/pretty.rb +0 -165
- data/lib/ruote/log/test_logger.rb +0 -204
- data/lib/ruote/util/serializer.rb +0 -103
- data/phil.txt +0 -14
- data/test/functional/eft_33_let.rb +0 -31
- data/test/functional/ft_19_alias.rb +0 -33
- data/test/functional/ft_47_wfid_generator.rb +0 -54
- data/test/unit/storage.rb +0 -403
- data/test/unit/storages.rb +0 -37
- data/test/unit/ut_13_serializer.rb +0 -65
- data/test/unit/ut_18_engine.rb +0 -47
- data/test/unit/ut_3_wait_logger.rb +0 -39
data/lib/ruote/svc/tracker.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
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
|
|
@@ -37,28 +37,18 @@ module Ruote
|
|
|
37
37
|
def initialize(context)
|
|
38
38
|
|
|
39
39
|
@context = context
|
|
40
|
-
|
|
41
|
-
if @context.worker
|
|
42
|
-
#
|
|
43
|
-
# this is a worker context, DO log
|
|
44
|
-
#
|
|
45
|
-
@context.worker.subscribe(:all, self)
|
|
46
|
-
#else
|
|
47
|
-
#
|
|
48
|
-
# this is not a worker context, no notifications. BUT
|
|
49
|
-
# honour calls to add_tracker/remove_tracker
|
|
50
|
-
#
|
|
51
|
-
end
|
|
52
40
|
end
|
|
53
41
|
|
|
54
|
-
# The
|
|
55
|
-
#
|
|
42
|
+
# The context calls this method for each successfully processed msg
|
|
43
|
+
# in the worker.
|
|
56
44
|
#
|
|
57
|
-
def
|
|
45
|
+
def on_msg(message)
|
|
46
|
+
|
|
47
|
+
m_error = message['error']
|
|
48
|
+
m_wfid = message['wfid'] || (message['fei']['wfid'] rescue nil)
|
|
49
|
+
m_action = message['action']
|
|
58
50
|
|
|
59
|
-
|
|
60
|
-
m_wfid = msg['wfid'] || (msg['fei']['wfid'] rescue nil)
|
|
61
|
-
m_action = msg['action']
|
|
51
|
+
msg = m_action == 'error_intercepted' ? message['msg'] : message
|
|
62
52
|
|
|
63
53
|
@context.storage.get_trackers['trackers'].each do |tracker_id, tracker|
|
|
64
54
|
|
|
@@ -70,9 +60,7 @@ module Ruote
|
|
|
70
60
|
next if t_wfid && t_wfid != m_wfid
|
|
71
61
|
next if t_action && t_action != m_action
|
|
72
62
|
|
|
73
|
-
next unless does_match?(
|
|
74
|
-
|
|
75
|
-
msg = msg['msg'] if m_action == 'error_intercepted'
|
|
63
|
+
next unless does_match?(message, tracker['conditions'])
|
|
76
64
|
|
|
77
65
|
if tracker_id == 'on_error' || tracker_id == 'on_terminate'
|
|
78
66
|
|
|
@@ -84,7 +72,7 @@ module Ruote
|
|
|
84
72
|
|
|
85
73
|
# prepare and emit/put 'reaction' message
|
|
86
74
|
|
|
87
|
-
m = tracker['msg']
|
|
75
|
+
m = Ruote.fulldup(tracker['msg'])
|
|
88
76
|
|
|
89
77
|
action = m.delete('action')
|
|
90
78
|
|
|
@@ -93,7 +81,9 @@ module Ruote
|
|
|
93
81
|
|
|
94
82
|
m['workitem'] = msg['workitem'] if m['workitem'] == 'replace'
|
|
95
83
|
|
|
96
|
-
if
|
|
84
|
+
if t_action == 'error_intercepted'
|
|
85
|
+
m['workitem']['fields']['__error__'] = m_error
|
|
86
|
+
elsif tracker_id == 'on_error' && m_action == 'error_intercepted'
|
|
97
87
|
m['workitem']['fields']['__error__'] = m_error
|
|
98
88
|
elsif tracker_id == 'on_terminate' && m_action == 'terminated'
|
|
99
89
|
m['workitem']['fields']['__terminate__'] = { 'wfid' => m_wfid }
|
|
@@ -112,6 +102,9 @@ module Ruote
|
|
|
112
102
|
#
|
|
113
103
|
def add_tracker(wfid, action, id, conditions, msg)
|
|
114
104
|
|
|
105
|
+
conditions =
|
|
106
|
+
conditions && conditions.remap { |(k, v), h| h[k] = Array(v) }
|
|
107
|
+
|
|
115
108
|
doc = @context.storage.get_trackers
|
|
116
109
|
|
|
117
110
|
doc['trackers'][id] =
|
|
@@ -123,7 +116,7 @@ module Ruote
|
|
|
123
116
|
|
|
124
117
|
r = @context.storage.put(doc)
|
|
125
118
|
|
|
126
|
-
add_tracker(wfid, action, id, msg) if r
|
|
119
|
+
add_tracker(wfid, action, id, conditions, msg) if r
|
|
127
120
|
# the put failed, have to redo the work
|
|
128
121
|
end
|
|
129
122
|
|
|
@@ -150,13 +143,20 @@ module Ruote
|
|
|
150
143
|
|
|
151
144
|
conditions.each do |k, v|
|
|
152
145
|
|
|
153
|
-
|
|
154
|
-
|
|
146
|
+
return false unless Array(v).find do |vv|
|
|
147
|
+
|
|
148
|
+
# the Array(v) is for backward compatibility, although newer
|
|
149
|
+
# track conditions are already stored as arrays.
|
|
150
|
+
|
|
151
|
+
vv = Ruote.regex_or_s(vv)
|
|
152
|
+
|
|
153
|
+
val = case k
|
|
154
|
+
when 'class' then msg['error']['class']
|
|
155
|
+
when 'message' then msg['error']['message']
|
|
156
|
+
else msg[k]
|
|
157
|
+
end
|
|
155
158
|
|
|
156
|
-
|
|
157
|
-
return false unless val && v == val
|
|
158
|
-
else
|
|
159
|
-
return false unless val && v.match(val)
|
|
159
|
+
val && (vv.is_a?(String) ? (vv == val) : vv.match(val))
|
|
160
160
|
end
|
|
161
161
|
end
|
|
162
162
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
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
|
|
@@ -37,7 +37,7 @@ module Ruote
|
|
|
37
37
|
|
|
38
38
|
def initialize(context)
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
return if context['use_ruby_treechecker'] == false
|
|
41
41
|
|
|
42
42
|
checker = Rufus::TreeChecker.new do
|
|
43
43
|
|
|
@@ -50,7 +50,6 @@ module Ruote
|
|
|
50
50
|
|
|
51
51
|
#exclude_raise # no raise or throw
|
|
52
52
|
|
|
53
|
-
exclude_def # no method definition
|
|
54
53
|
exclude_eval # no eval, module_eval or instance_eval
|
|
55
54
|
exclude_backquotes # no `rm -fR the/kitchen/sink`
|
|
56
55
|
exclude_alias # no alias or aliast_method
|
|
@@ -70,18 +69,16 @@ module Ruote
|
|
|
70
69
|
exclude_call_to :instance_variable_get, :instance_variable_set
|
|
71
70
|
end
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
exclude_raise # no raise or throw
|
|
72
|
+
stricter_checker = checker.clone
|
|
73
|
+
stricter_checker.add_rules do
|
|
74
|
+
exclude_def # no method definition
|
|
75
|
+
exclude_raise # no raise or throw
|
|
78
76
|
end
|
|
79
|
-
@def_checker.freeze
|
|
80
77
|
|
|
81
|
-
# the checker used when
|
|
78
|
+
# the checker used when reading process definitions
|
|
82
79
|
|
|
83
|
-
@
|
|
84
|
-
@
|
|
80
|
+
@def_checker = stricter_checker.clone # and not dup
|
|
81
|
+
@def_checker.freeze
|
|
85
82
|
|
|
86
83
|
## the checker used when dealing with conditionals
|
|
87
84
|
#
|
|
@@ -100,12 +97,22 @@ module Ruote
|
|
|
100
97
|
|
|
101
98
|
# the checker used when dealing with code in $(ruby:xxx}
|
|
102
99
|
|
|
103
|
-
@dol_checker =
|
|
104
|
-
@dol_checker.add_rules do
|
|
105
|
-
exclude_raise # no raise or throw
|
|
106
|
-
end
|
|
100
|
+
@dol_checker = stricter_checker.clone # and not dup
|
|
107
101
|
@dol_checker.freeze
|
|
108
102
|
|
|
103
|
+
# the checker used when dealing with BlockParticipant code
|
|
104
|
+
|
|
105
|
+
@blo_checker = checker.clone # and not dup
|
|
106
|
+
@blo_checker.add_rules do
|
|
107
|
+
exclude_def # no method definition
|
|
108
|
+
end
|
|
109
|
+
@blo_checker.freeze
|
|
110
|
+
|
|
111
|
+
# the checker used for CodeParticipant
|
|
112
|
+
|
|
113
|
+
@cod_checker = checker.clone # and not dup
|
|
114
|
+
@cod_checker.freeze
|
|
115
|
+
|
|
109
116
|
freeze
|
|
110
117
|
# preventing further modifications
|
|
111
118
|
end
|
|
@@ -124,6 +131,11 @@ module Ruote
|
|
|
124
131
|
|
|
125
132
|
@dol_checker.check(ruby_code) if @dol_checker
|
|
126
133
|
end
|
|
134
|
+
|
|
135
|
+
def code_check(ruby_code)
|
|
136
|
+
|
|
137
|
+
@cod_checker.check(ruby_code) if @cod_checker
|
|
138
|
+
end
|
|
127
139
|
end
|
|
128
140
|
end
|
|
129
141
|
|
data/lib/ruote/tree_dot.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
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
|
|
@@ -0,0 +1,143 @@
|
|
|
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
|
+
module Ruote
|
|
27
|
+
|
|
28
|
+
#--
|
|
29
|
+
# methods that go deep inside a nested structures of arrays and hashes
|
|
30
|
+
# (JSON output maybe).
|
|
31
|
+
#++
|
|
32
|
+
|
|
33
|
+
# Given a hash and a key, deletes all the entries with that key, in child
|
|
34
|
+
# hashes too.
|
|
35
|
+
#
|
|
36
|
+
# Note: this method is not related to the "dot notation" methods in this
|
|
37
|
+
# lookup.rb file.
|
|
38
|
+
#
|
|
39
|
+
# == example
|
|
40
|
+
#
|
|
41
|
+
# h = { 'a' => 1, 'b' => { 'a' => 2 } }
|
|
42
|
+
# Ruote.deep_delete(h, 'a')
|
|
43
|
+
# # => { 'b' => {} }
|
|
44
|
+
#
|
|
45
|
+
def self.deep_delete(h, key)
|
|
46
|
+
|
|
47
|
+
h.delete(key)
|
|
48
|
+
|
|
49
|
+
h.each { |k, v| deep_delete(v, key) if v.is_a?(Hash) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class << self
|
|
53
|
+
alias delete_all deep_delete
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Dives into a nested structure of hashes and arrays to find match hash keys.
|
|
57
|
+
#
|
|
58
|
+
# The method expects a block with 3 or 4 arguments.
|
|
59
|
+
#
|
|
60
|
+
# 3 arguments: collection, key and value
|
|
61
|
+
# 4 arguments: parent collection, collection, key and value
|
|
62
|
+
#
|
|
63
|
+
# Warning: .deep_mutate forces hash keys to be strings. It's a JSON world.
|
|
64
|
+
#
|
|
65
|
+
# == example
|
|
66
|
+
#
|
|
67
|
+
# h = {
|
|
68
|
+
# 'a' => 0,
|
|
69
|
+
# 'b' => 1,
|
|
70
|
+
# 'c' => { 'a' => 2, 'b' => { 'a' => 3 } },
|
|
71
|
+
# 'd' => [ { 'a' => 0 }, { 'b' => 4 } ] }
|
|
72
|
+
#
|
|
73
|
+
# Ruote.deep_mutate(h, 'a') do |coll, k, v|
|
|
74
|
+
# coll['a'] = 10
|
|
75
|
+
# end
|
|
76
|
+
#
|
|
77
|
+
# h # =>
|
|
78
|
+
# { 'a' => 10,
|
|
79
|
+
# 'b' => 1,
|
|
80
|
+
# 'c' => { 'a' => 10, 'b' => { 'a' => 10 } },
|
|
81
|
+
# 'd' => [ { 'a' => 10 }, { 'b' => 4 } ] }
|
|
82
|
+
#
|
|
83
|
+
# == variations
|
|
84
|
+
#
|
|
85
|
+
# Instead of a single key, it's OK to pass an array of keys:
|
|
86
|
+
#
|
|
87
|
+
# Ruote.deep_mutate(a, [ 'a', 'b' ]) do |coll, k, v|
|
|
88
|
+
# # ...
|
|
89
|
+
# end
|
|
90
|
+
#
|
|
91
|
+
# Regular expressions are made to match:
|
|
92
|
+
#
|
|
93
|
+
# Ruote.deep_mutate(a, [ 'a', /^a\./ ]) do |coll, k, v|
|
|
94
|
+
# # ...
|
|
95
|
+
# end
|
|
96
|
+
#
|
|
97
|
+
# A single regular expression is OK:
|
|
98
|
+
#
|
|
99
|
+
# Ruote.deep_mutate(a, /^user\./) do |coll, k, v|
|
|
100
|
+
# # ...
|
|
101
|
+
# end
|
|
102
|
+
#
|
|
103
|
+
def self.deep_mutate(coll, key_or_keys, parent=nil, &block)
|
|
104
|
+
|
|
105
|
+
keys = key_or_keys.is_a?(Array) ? key_or_keys : [ key_or_keys ]
|
|
106
|
+
|
|
107
|
+
if coll.is_a?(Hash)
|
|
108
|
+
|
|
109
|
+
coll.dup.each do |k, v|
|
|
110
|
+
|
|
111
|
+
# ensure that all keys are strings
|
|
112
|
+
|
|
113
|
+
unless k.is_a?(String)
|
|
114
|
+
coll.delete(k)
|
|
115
|
+
k = k.to_s
|
|
116
|
+
coll[k] = v
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# call the mutation blocks for each match
|
|
120
|
+
|
|
121
|
+
if keys.find { |kk| kk.is_a?(Regexp) ? kk.match(k) : kk == k }
|
|
122
|
+
|
|
123
|
+
if block.arity > 3
|
|
124
|
+
block.call(parent, coll, k, v)
|
|
125
|
+
else
|
|
126
|
+
block.call(coll, k, v)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
elsif v.is_a?(Array) || v.is_a?(Hash)
|
|
130
|
+
|
|
131
|
+
deep_mutate(v, keys, coll, &block)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
elsif coll.is_a?(Array)
|
|
136
|
+
|
|
137
|
+
coll.each { |e| deep_mutate(e, keys, coll, &block) }
|
|
138
|
+
|
|
139
|
+
#else # nothing
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
data/lib/ruote/util/filter.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
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
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
#++
|
|
24
24
|
|
|
25
25
|
require 'ruote/util/misc'
|
|
26
|
-
require 'ruote/util/lookup'
|
|
27
26
|
|
|
28
27
|
|
|
29
28
|
module Ruote
|
|
@@ -52,6 +51,50 @@ module Ruote
|
|
|
52
51
|
"not a filter : #{filter}"
|
|
53
52
|
) unless filter.is_a?(Array)
|
|
54
53
|
|
|
54
|
+
filters = or_split(filter)
|
|
55
|
+
|
|
56
|
+
result = nil
|
|
57
|
+
|
|
58
|
+
filters.each do |fl|
|
|
59
|
+
|
|
60
|
+
result = begin
|
|
61
|
+
do_filter(fl, hash, options)
|
|
62
|
+
rescue ValidationError => err
|
|
63
|
+
err
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
return result if result.is_a?(Hash)
|
|
67
|
+
# success
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
raise(result) if result.is_a?(ValidationError)
|
|
71
|
+
|
|
72
|
+
result
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Used by Ruote.filter
|
|
76
|
+
#
|
|
77
|
+
def self.or_split(filter)
|
|
78
|
+
|
|
79
|
+
return filter if filter.first.is_a?(Array)
|
|
80
|
+
return [ filter ] if filter.empty? or ( ! filter.include?('or'))
|
|
81
|
+
|
|
82
|
+
# [ {}, 'or', {}, {}, 'or', {} ]
|
|
83
|
+
|
|
84
|
+
filter.inject([ [] ]) do |result, fl|
|
|
85
|
+
if fl.is_a?(Hash)
|
|
86
|
+
result.last << fl
|
|
87
|
+
else
|
|
88
|
+
result << []
|
|
89
|
+
end
|
|
90
|
+
result
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Used by Ruote.filter
|
|
95
|
+
#
|
|
96
|
+
def self.do_filter(filter, hash, options)
|
|
97
|
+
|
|
55
98
|
hash = Rufus::Json.dup(hash)
|
|
56
99
|
|
|
57
100
|
hash['~'] = Rufus::Json.dup(hash)
|
|
@@ -64,6 +107,7 @@ module Ruote
|
|
|
64
107
|
|
|
65
108
|
hash.delete('~')
|
|
66
109
|
hash.delete('~~')
|
|
110
|
+
hash.delete('~~~')
|
|
67
111
|
# remove the 'originals'
|
|
68
112
|
|
|
69
113
|
if deviations.empty?
|
|
@@ -82,10 +126,13 @@ module Ruote
|
|
|
82
126
|
class RuleSession
|
|
83
127
|
|
|
84
128
|
SKIP = %w[ and or fields field f ]
|
|
129
|
+
BOOLEANS = %w[ and or ]
|
|
85
130
|
NUMBER_CLASSES = [ Fixnum, Float ]
|
|
86
131
|
BOOLEAN_CLASSES = [ TrueClass, FalseClass ]
|
|
87
132
|
TILDE = /^~/
|
|
88
133
|
RTILDE = /^\^~/
|
|
134
|
+
COMMA_SPLIT = / *, */
|
|
135
|
+
PIPE_SPLIT = / *\| */
|
|
89
136
|
|
|
90
137
|
def initialize(hash, rule)
|
|
91
138
|
|
|
@@ -112,17 +159,24 @@ module Ruote
|
|
|
112
159
|
|
|
113
160
|
# now only keep the keys that match our regexp
|
|
114
161
|
|
|
115
|
-
keys.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
end
|
|
119
|
-
a
|
|
162
|
+
keys.each_with_object([]) { |k, a|
|
|
163
|
+
m = fl.match(k)
|
|
164
|
+
a << [ k, Ruote.lookup(@hash, k), m[1..-1] ] if m
|
|
120
165
|
}
|
|
121
166
|
|
|
167
|
+
elsif fl.is_a?(String) and PIPE_SPLIT.match(fl)
|
|
168
|
+
|
|
169
|
+
fields = fl.split(PIPE_SPLIT).collect { |field|
|
|
170
|
+
val = Ruote.lookup(@hash, field)
|
|
171
|
+
val.nil? ? nil : [ field, val, nil ]
|
|
172
|
+
}.compact
|
|
173
|
+
|
|
174
|
+
fields.empty? ? [ [ fl, nil, nil ] ] : fields
|
|
175
|
+
# if no fields where found, place fake fl field to force failure
|
|
176
|
+
|
|
122
177
|
else
|
|
123
178
|
|
|
124
|
-
(fl.is_a?(Array) ? fl : fl.to_s.split(
|
|
125
|
-
field = field.strip
|
|
179
|
+
(fl.is_a?(Array) ? fl : fl.to_s.split(COMMA_SPLIT)).collect { |field|
|
|
126
180
|
[ field, Ruote.lookup(@hash, field), nil ]
|
|
127
181
|
}
|
|
128
182
|
end
|
|
@@ -130,20 +184,35 @@ module Ruote
|
|
|
130
184
|
|
|
131
185
|
def run
|
|
132
186
|
|
|
187
|
+
keys = @rule.keys - SKIP
|
|
188
|
+
validation = (@rule.keys & BOOLEANS).empty?
|
|
189
|
+
|
|
190
|
+
if validation and @fields.empty? and keys.empty?
|
|
191
|
+
fl = @rule['fields'] || @rule['field'] || @rule['f']
|
|
192
|
+
return [ [ @rule, fl, nil ] ] # validation break
|
|
193
|
+
end
|
|
194
|
+
|
|
133
195
|
@fields.collect { |field, value, matches|
|
|
134
196
|
|
|
135
197
|
valid = nil
|
|
136
198
|
|
|
137
|
-
|
|
199
|
+
if keys.empty?
|
|
200
|
+
|
|
201
|
+
valid = (value != nil)
|
|
202
|
+
|
|
203
|
+
else
|
|
138
204
|
|
|
139
|
-
|
|
205
|
+
keys.each do |k|
|
|
140
206
|
|
|
141
|
-
|
|
142
|
-
next unless self.respond_to?(m)
|
|
207
|
+
v = @rule[k]
|
|
143
208
|
|
|
144
|
-
|
|
209
|
+
m = "_#{k}"
|
|
210
|
+
next unless self.respond_to?(m)
|
|
145
211
|
|
|
146
|
-
|
|
212
|
+
r = self.send(m, field, value, matches, k, v)
|
|
213
|
+
|
|
214
|
+
valid = false if r == false
|
|
215
|
+
end
|
|
147
216
|
end
|
|
148
217
|
|
|
149
218
|
raise_or_and(valid, field, value)
|
|
@@ -264,6 +333,30 @@ module Ruote
|
|
|
264
333
|
alias _restore_from _restore
|
|
265
334
|
alias _rs _restore
|
|
266
335
|
|
|
336
|
+
def _take(field, value, matches, m, v)
|
|
337
|
+
|
|
338
|
+
unless @hash.has_key?('~~~')
|
|
339
|
+
|
|
340
|
+
@hash['~~~'] = @hash.keys.select { |k|
|
|
341
|
+
! k.match(/^\~+$/)
|
|
342
|
+
}.each_with_object({}) { |k, h|
|
|
343
|
+
h[k] = @hash.delete(k)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
@hash.merge!(@hash['~~'])
|
|
347
|
+
@hash.merge!(@hash['~~~']) if m == 'discard' && v != 'all'
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
if m == 'take'
|
|
351
|
+
@hash[field] = @hash['~~~'][field]
|
|
352
|
+
elsif v != 'all'
|
|
353
|
+
@hash.delete(field)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
nil
|
|
357
|
+
end
|
|
358
|
+
alias _discard _take
|
|
359
|
+
|
|
267
360
|
def _size(field, value, matches, m, v)
|
|
268
361
|
|
|
269
362
|
v = v.is_a?(String) ? v.split(',').collect { |i| i.to_i } : Array(v)
|
|
@@ -279,7 +372,9 @@ module Ruote
|
|
|
279
372
|
|
|
280
373
|
def _empty(field, value, matches, m, v)
|
|
281
374
|
|
|
282
|
-
|
|
375
|
+
# 'empty' => '30%' could be fun ;-)
|
|
376
|
+
|
|
377
|
+
(value.respond_to?(:empty?) ? value.empty? : false) == v
|
|
283
378
|
end
|
|
284
379
|
alias _e _empty
|
|
285
380
|
|
|
@@ -306,6 +401,15 @@ module Ruote
|
|
|
306
401
|
end
|
|
307
402
|
alias _h _has
|
|
308
403
|
|
|
404
|
+
def _includes(field, value, matches, m, v)
|
|
405
|
+
|
|
406
|
+
case value
|
|
407
|
+
when Array then value.include?(v)
|
|
408
|
+
when Hash then value.values.include?(v)
|
|
409
|
+
else false
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
309
413
|
def _type(field, value, matches, m, v)
|
|
310
414
|
|
|
311
415
|
of_type?(value, v)
|
|
@@ -352,8 +456,6 @@ module Ruote
|
|
|
352
456
|
else
|
|
353
457
|
raise ArgumentError.new("unknown type '#{type}'")
|
|
354
458
|
end
|
|
355
|
-
|
|
356
|
-
valid
|
|
357
459
|
end
|
|
358
460
|
end
|
|
359
461
|
|
|
@@ -380,6 +482,11 @@ module Ruote
|
|
|
380
482
|
end
|
|
381
483
|
alias _sm _smatch
|
|
382
484
|
|
|
485
|
+
def _is(field, value, matches, m, v)
|
|
486
|
+
|
|
487
|
+
value == v
|
|
488
|
+
end
|
|
489
|
+
|
|
383
490
|
def _valid(field, value, matches, m, v)
|
|
384
491
|
|
|
385
492
|
v.to_s == 'true'
|