jcrvalidator 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jcr/check_groups.rb +4 -14
- data/lib/jcr/evaluate_array_rules.rb +41 -26
- data/lib/jcr/evaluate_group_rules.rb +6 -6
- data/lib/jcr/evaluate_member_rules.rb +7 -6
- data/lib/jcr/evaluate_object_rules.rb +37 -25
- data/lib/jcr/evaluate_rules.rb +83 -32
- data/lib/jcr/evaluate_value_rules.rb +4 -3
- data/lib/jcr/jcr.rb +58 -21
- data/lib/jcr/jcr_validator_error.rb +21 -0
- data/lib/jcr/map_rule_names.rb +6 -4
- data/lib/jcr/parts.rb +16 -2
- data/lib/jcr/process_directives.rb +1 -1
- data/lib/jcr/version.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e15f3d872870b687c53a8cf98ab6668afec8c3c5
|
4
|
+
data.tar.gz: 01250f5fe01fe29a8025f6aac9da8c83766df494
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6218f0d7f612b32759383f0869e39bbaf04850cdaf12cd4400796b164e745da40ffc371d9f564abd4e0135417805b5794c0c94af68f7282cb5c8284d3910e3fb
|
7
|
+
data.tar.gz: 4c1aebcccc76bd2806ca98d9d7e582e3353eda4c07a2fc1fb915a5ffcf192172b2ce04015046bfca5f566e0fa67a789164aa68421b90b3f3aee8df28e41fcc8d
|
data/lib/jcr/check_groups.rb
CHANGED
@@ -78,8 +78,6 @@ module JCR
|
|
78
78
|
disallowed_group_in_member?( trule, mapping )
|
79
79
|
elsif node[:group_rule]
|
80
80
|
disallowed_group_in_member?( node[:group_rule], mapping )
|
81
|
-
else
|
82
|
-
check_groups( node, mapping )
|
83
81
|
end
|
84
82
|
end
|
85
83
|
|
@@ -117,8 +115,6 @@ module JCR
|
|
117
115
|
disallowed_group_in_array?(trule, mapping)
|
118
116
|
elsif node[:group_rule]
|
119
117
|
disallowed_group_in_array?(node[:group_rule], mapping)
|
120
|
-
else
|
121
|
-
check_groups(node, mapping)
|
122
118
|
end
|
123
119
|
end
|
124
120
|
end
|
@@ -132,9 +128,7 @@ module JCR
|
|
132
128
|
disallowed_group_in_array?( groupee[:group_rule], mapping )
|
133
129
|
elsif groupee[:target_rule_name]
|
134
130
|
trule = get_name_mapping( groupee[:target_rule_name][:rule_name], mapping )
|
135
|
-
|
136
|
-
disallowed_group_in_array?( trule[:group_rule], mapping )
|
137
|
-
end
|
131
|
+
disallowed_group_in_array?( trule, mapping )
|
138
132
|
elsif groupee[:member_rule]
|
139
133
|
raise_group_error( "groups in array rules cannot have member rules", groupee[:member_rule] )
|
140
134
|
else
|
@@ -154,8 +148,6 @@ module JCR
|
|
154
148
|
disallowed_group_in_object?(trule, mapping)
|
155
149
|
elsif node[:group_rule]
|
156
150
|
disallowed_group_in_object?(node[:group_rule], mapping)
|
157
|
-
else
|
158
|
-
check_groups(node, mapping)
|
159
151
|
end
|
160
152
|
end
|
161
153
|
end
|
@@ -169,9 +161,7 @@ module JCR
|
|
169
161
|
disallowed_group_in_object?( groupee[:group_rule], mapping )
|
170
162
|
elsif groupee[:target_rule_name]
|
171
163
|
trule = get_name_mapping( groupee[:target_rule_name][:rule_name], mapping )
|
172
|
-
|
173
|
-
disallowed_group_in_object?( trule[:group_rule], mapping )
|
174
|
-
end
|
164
|
+
disallowed_group_in_object?( trule, mapping )
|
175
165
|
elsif groupee[:array_rule]
|
176
166
|
raise_group_error( "groups in object rules cannot have array rules", groupee[:member_rule] )
|
177
167
|
elsif groupee[:object_rule]
|
@@ -188,9 +178,9 @@ module JCR
|
|
188
178
|
if node.is_a?( Parslet::Slice )
|
189
179
|
pos = node.line_and_column
|
190
180
|
name = node.to_str
|
191
|
-
raise "group rule error at line " + pos[0].to_s + " column " + pos[1].to_s + " name '" + name + "' :" + str
|
181
|
+
raise JCR::JcrValidatorError, "group rule error at line " + pos[0].to_s + " column " + pos[1].to_s + " name '" + name + "' :" + str
|
192
182
|
else
|
193
|
-
raise "group rule error with '" + node.to_s + "' :" + str
|
183
|
+
raise JCR::JcrValidatorError, "group rule error with '" + node.to_s + "' :" + str
|
194
184
|
end
|
195
185
|
end
|
196
186
|
|
@@ -45,19 +45,28 @@ module JCR
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
def self.evaluate_array_rule jcr, rule_atom, data, econs, behavior = nil
|
48
|
+
def self.evaluate_array_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil
|
49
49
|
|
50
50
|
push_trace_stack( econs, jcr )
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
if behavior
|
52
|
+
trace( econs, "Evaluating group in array rule starting at #{slice_to_s(jcr)} against", data )
|
53
|
+
trace_def( econs, "array group", jcr, data )
|
54
|
+
else
|
55
|
+
trace( econs, "Evaluating array rule starting at #{slice_to_s(jcr)} against", data )
|
56
|
+
trace_def( econs, "array", jcr, data )
|
57
|
+
end
|
58
|
+
retval = evaluate_array( jcr, rule_atom, data, econs, behavior, target_annotations )
|
59
|
+
if behavior
|
60
|
+
trace_eval( econs, "Array group", retval, jcr, data, "array" )
|
61
|
+
else
|
62
|
+
trace_eval( econs, "Array", retval, jcr, data, "array" )
|
63
|
+
end
|
55
64
|
pop_trace_stack( econs )
|
56
65
|
return retval
|
57
66
|
|
58
67
|
end
|
59
68
|
|
60
|
-
def self.evaluate_array jcr, rule_atom, data, econs, behavior = nil
|
69
|
+
def self.evaluate_array jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil
|
61
70
|
|
62
71
|
rules, annotations = get_rules_and_annotations( jcr )
|
63
72
|
|
@@ -76,20 +85,24 @@ module JCR
|
|
76
85
|
|
77
86
|
# if the data is not an array
|
78
87
|
return evaluate_not( annotations,
|
79
|
-
Evaluation.new( false, "#{data} is not an array #{raised_rule(jcr,rule_atom)}"),
|
88
|
+
Evaluation.new( false, "#{data} is not an array #{raised_rule(jcr,rule_atom)}"),
|
89
|
+
econs, target_annotations ) unless data.is_a? Array
|
80
90
|
|
81
91
|
# if the array is zero length and there are zero sub-rules (it is suppose to be empty)
|
82
92
|
return evaluate_not( annotations,
|
83
|
-
Evaluation.new( true, nil ), econs ) if rules.empty? && data.empty?
|
93
|
+
Evaluation.new( true, nil ), econs, target_annotations ) if rules.empty? && data.empty?
|
84
94
|
|
85
95
|
# if the array is not empty and there are zero sub-rules (it is suppose to be empty)
|
86
96
|
return evaluate_not( annotations,
|
87
|
-
Evaluation.new( false, "Non-empty array for #{raised_rule(jcr,rule_atom)}" ),
|
97
|
+
Evaluation.new( false, "Non-empty array for #{raised_rule(jcr,rule_atom)}" ),
|
98
|
+
econs, target_annotations ) if rules.empty? && data.length != 0
|
88
99
|
|
89
100
|
if ordered
|
90
|
-
return evaluate_not( annotations, evaluate_array_rule_ordered( rules, rule_atom, data, econs, behavior ),
|
101
|
+
return evaluate_not( annotations, evaluate_array_rule_ordered( rules, rule_atom, data, econs, behavior ),
|
102
|
+
econs, target_annotations )
|
91
103
|
else
|
92
|
-
return evaluate_not( annotations, evaluate_array_rule_unordered( rules, rule_atom, data, econs, behavior ),
|
104
|
+
return evaluate_not( annotations, evaluate_array_rule_unordered( rules, rule_atom, data, econs, behavior ),
|
105
|
+
econs, target_annotations )
|
93
106
|
end
|
94
107
|
end
|
95
108
|
|
@@ -115,7 +128,8 @@ module JCR
|
|
115
128
|
# groups require the effects of the evaluation to be discarded if they are false
|
116
129
|
# groups must also be given the entire array
|
117
130
|
|
118
|
-
|
131
|
+
grule, target_annotations = get_group( rule, econs )
|
132
|
+
if grule
|
119
133
|
|
120
134
|
if repeat_min == 0
|
121
135
|
retval = Evaluation.new( true, nil )
|
@@ -126,7 +140,7 @@ module JCR
|
|
126
140
|
else
|
127
141
|
group_behavior = ArrayBehavior.new( behavior )
|
128
142
|
group_behavior.last_index = array_index
|
129
|
-
retval = evaluate_rule( grule, rule_atom, data, econs, group_behavior )
|
143
|
+
retval = evaluate_rule( grule, rule_atom, data, econs, group_behavior, target_annotations )
|
130
144
|
if retval.success
|
131
145
|
behavior.checked_hash.merge!( group_behavior.checked_hash )
|
132
146
|
array_index = group_behavior.last_index
|
@@ -141,7 +155,7 @@ module JCR
|
|
141
155
|
break if array_index == data.length
|
142
156
|
group_behavior = ArrayBehavior.new( behavior )
|
143
157
|
group_behavior.last_index = array_index
|
144
|
-
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior )
|
158
|
+
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior, target_annotations )
|
145
159
|
if e.success
|
146
160
|
behavior.checked_hash.merge!( group_behavior.checked_hash )
|
147
161
|
array_index = group_behavior.last_index
|
@@ -187,7 +201,7 @@ module JCR
|
|
187
201
|
behavior.last_index = array_index
|
188
202
|
|
189
203
|
if data.length > array_index && behavior.extra_prohibited
|
190
|
-
retval = Evaluation.new( false, "More
|
204
|
+
retval = Evaluation.new( false, "More items in array (#{data.length}) than specified (#{array_index}) for #{raised_rule(jcr,rule_atom)}" )
|
191
205
|
end
|
192
206
|
|
193
207
|
return retval
|
@@ -218,14 +232,15 @@ module JCR
|
|
218
232
|
# groups require the effects of the evaluation to be discarded if they are false
|
219
233
|
# groups must also be given the entire array
|
220
234
|
|
221
|
-
|
235
|
+
grule,target_annotations = get_group(rule, econs)
|
236
|
+
if grule
|
222
237
|
|
223
238
|
successes = 0
|
224
239
|
for i in 0..repeat_max-1
|
225
240
|
group_behavior = ArrayBehavior.new( behavior )
|
226
241
|
group_behavior.last_index = highest_index
|
227
242
|
group_behavior.ordered = false
|
228
|
-
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior )
|
243
|
+
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior, target_annotations )
|
229
244
|
if e.success
|
230
245
|
highest_index = group_behavior.last_index
|
231
246
|
behavior.checked_hash.merge!( group_behavior.checked_hash )
|
@@ -236,13 +251,13 @@ module JCR
|
|
236
251
|
end
|
237
252
|
|
238
253
|
if successes == 0 && repeat_min > 0
|
239
|
-
retval = Evaluation.new( false, "array does not contain #{rule} for #{raised_rule(jcr,rule_atom)}")
|
254
|
+
retval = Evaluation.new( false, "array does not contain #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
240
255
|
elsif successes < repeat_min
|
241
|
-
retval = Evaluation.new( false, "array does not have enough #{rule} for #{raised_rule(jcr,rule_atom)}")
|
256
|
+
retval = Evaluation.new( false, "array does not have enough #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
242
257
|
elsif successes > repeat_max
|
243
|
-
retval = Evaluation.new( false, "array has too many #{rule} for #{raised_rule(jcr,rule_atom)}")
|
258
|
+
retval = Evaluation.new( false, "array has too many #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
244
259
|
elsif repeat_step && ( successes - repeat_min ) % repeat_step != 0
|
245
|
-
retval = Evaluation.new( false, "array matches (#{successes}) do not meet repetition step of #{repeat_max} % #{repeat_step} with #{rule} for #{raised_rule(jcr,rule_atom)}")
|
260
|
+
retval = Evaluation.new( false, "array matches (#{successes}) do not meet repetition step of #{repeat_max} % #{repeat_step} with #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
246
261
|
else
|
247
262
|
retval = Evaluation.new( true, nil )
|
248
263
|
end
|
@@ -263,13 +278,13 @@ module JCR
|
|
263
278
|
end
|
264
279
|
|
265
280
|
if successes == 0 && repeat_min > 0
|
266
|
-
retval = Evaluation.new( false, "array does not contain #{rule} for #{raised_rule(jcr,rule_atom)}")
|
281
|
+
retval = Evaluation.new( false, "array does not contain #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
267
282
|
elsif successes < repeat_min
|
268
|
-
retval = Evaluation.new( false, "array does not have enough #{rule} for #{raised_rule(jcr,rule_atom)}")
|
283
|
+
retval = Evaluation.new( false, "array does not have enough #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
269
284
|
elsif successes > repeat_max
|
270
|
-
retval = Evaluation.new( false, "array has too many #{rule} for #{raised_rule(jcr,rule_atom)}")
|
285
|
+
retval = Evaluation.new( false, "array has too many #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
271
286
|
elsif repeat_step && ( successes - repeat_min ) % repeat_step != 0
|
272
|
-
retval = Evaluation.new( false, "array matches (#{successes}) do not meet repetition step of #{repeat_max} % #{repeat_step} with #{rule} for #{raised_rule(jcr,rule_atom)}")
|
287
|
+
retval = Evaluation.new( false, "array matches (#{successes}) do not meet repetition step of #{repeat_max} % #{repeat_step} with #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
273
288
|
else
|
274
289
|
retval = Evaluation.new( true, nil)
|
275
290
|
end
|
@@ -281,7 +296,7 @@ module JCR
|
|
281
296
|
behavior.last_index = highest_index
|
282
297
|
|
283
298
|
if data.length > behavior.checked_hash.length && behavior.extra_prohibited
|
284
|
-
retval = Evaluation.new( false, "More
|
299
|
+
retval = Evaluation.new( false, "More items in array than specified for #{raised_rule(jcr,rule_atom)}" )
|
285
300
|
end
|
286
301
|
|
287
302
|
return retval
|
@@ -26,19 +26,19 @@ require 'jcr/evaluate_rules'
|
|
26
26
|
|
27
27
|
module JCR
|
28
28
|
|
29
|
-
def self.evaluate_group_rule jcr, rule_atom, data, econs, behavior = nil
|
29
|
+
def self.evaluate_group_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil
|
30
30
|
|
31
31
|
push_trace_stack( econs, jcr )
|
32
32
|
trace( econs, "Evaluating group rule against ", data )
|
33
33
|
trace_def( econs, "group", jcr, data )
|
34
|
-
retval = evaluate_group( jcr, rule_atom, data, econs, behavior )
|
34
|
+
retval = evaluate_group( jcr, rule_atom, data, econs, behavior, target_annotations )
|
35
35
|
trace_eval( econs, "Group", retval, jcr, data, "group" )
|
36
36
|
pop_trace_stack( econs )
|
37
37
|
return retval
|
38
38
|
|
39
39
|
end
|
40
40
|
|
41
|
-
def self.evaluate_group jcr, rule_atom, data, econs, behavior = nil
|
41
|
+
def self.evaluate_group jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil
|
42
42
|
|
43
43
|
rules, annotations = get_rules_and_annotations( jcr )
|
44
44
|
|
@@ -46,14 +46,14 @@ module JCR
|
|
46
46
|
|
47
47
|
rules.each do |rule|
|
48
48
|
if rule[:choice_combiner] && retval && retval.success
|
49
|
-
return evaluate_not( annotations, retval, econs ) # short circuit
|
49
|
+
return evaluate_not( annotations, retval, econs, target_annotations ) # short circuit
|
50
50
|
elsif rule[:sequence_combiner] && retval && !retval.success
|
51
|
-
return evaluate_not( annotations, retval, econs ) # short circuit
|
51
|
+
return evaluate_not( annotations, retval, econs, target_annotations ) # short circuit
|
52
52
|
end
|
53
53
|
retval = evaluate_rule( rule, rule_atom, data, econs, behavior )
|
54
54
|
end
|
55
55
|
|
56
|
-
return evaluate_not( annotations, retval, econs )
|
56
|
+
return evaluate_not( annotations, retval, econs, target_annotations )
|
57
57
|
end
|
58
58
|
|
59
59
|
def self.group_to_s( jcr, shallow=true)
|
@@ -25,19 +25,19 @@ require 'jcr/check_groups'
|
|
25
25
|
|
26
26
|
module JCR
|
27
27
|
|
28
|
-
def self.evaluate_member_rule jcr, rule_atom, data, econs
|
28
|
+
def self.evaluate_member_rule jcr, rule_atom, data, econs, behavior, target_annotations
|
29
29
|
|
30
30
|
push_trace_stack( econs, jcr )
|
31
31
|
trace( econs, "Evaluating member rule for key '#{data[0]}' starting at #{slice_to_s(jcr)} against ", data[1])
|
32
32
|
trace_def( econs, "member", jcr, data )
|
33
|
-
retval = evaluate_member( jcr, rule_atom, data, econs )
|
33
|
+
retval = evaluate_member( jcr, rule_atom, data, econs, behavior, target_annotations )
|
34
34
|
trace_eval( econs, "Member", retval, jcr, data, "member" )
|
35
35
|
pop_trace_stack( econs )
|
36
36
|
return retval
|
37
37
|
|
38
38
|
end
|
39
39
|
|
40
|
-
def self.evaluate_member jcr, rule_atom, data, econs
|
40
|
+
def self.evaluate_member jcr, rule_atom, data, econs, behavior, target_annotations
|
41
41
|
|
42
42
|
# unlike the other evaluate functions, here data is not just the json data.
|
43
43
|
# it is an array, the first element being the member name or regex and the
|
@@ -68,13 +68,14 @@ module JCR
|
|
68
68
|
end
|
69
69
|
|
70
70
|
if member_match
|
71
|
-
e = evaluate_rule( rule, rule_atom, data[ 1 ], econs )
|
71
|
+
e = evaluate_rule( rule, rule_atom, data[ 1 ], econs, nil, target_annotations )
|
72
72
|
e.member_found = true
|
73
|
-
return evaluate_not( annotations, e, econs )
|
73
|
+
return evaluate_not( annotations, e, econs, target_annotations )
|
74
74
|
end
|
75
75
|
|
76
76
|
return evaluate_not( annotations,
|
77
|
-
Evaluation.new( false, "#{match_spec} does not match #{data[0]} for #{raised_rule( jcr, rule_atom)}" ),
|
77
|
+
Evaluation.new( false, "#{match_spec} does not match #{data[0]} for #{raised_rule( jcr, rule_atom)}" ),
|
78
|
+
econs, target_annotations )
|
78
79
|
|
79
80
|
end
|
80
81
|
|
@@ -27,33 +27,44 @@ module JCR
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def self.evaluate_object_rule jcr, rule_atom, data, econs, behavior = nil
|
30
|
+
def self.evaluate_object_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil
|
31
31
|
|
32
32
|
push_trace_stack( econs, jcr )
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
if behavior
|
34
|
+
trace( econs, "Evaluating group in object rule starting at #{slice_to_s(jcr)} against", data )
|
35
|
+
trace_def( econs, "object group", jcr, data )
|
36
|
+
else
|
37
|
+
trace( econs, "Evaluating object rule starting at #{slice_to_s(jcr)} against", data )
|
38
|
+
trace_def( econs, "object", jcr, data )
|
39
|
+
end
|
40
|
+
retval = evaluate_object( jcr, rule_atom, data, econs, behavior, target_annotations )
|
41
|
+
if behavior
|
42
|
+
trace_eval( econs, "Object group", retval, jcr, data, "object" )
|
43
|
+
else
|
44
|
+
trace_eval( econs, "Object", retval, jcr, data, "object" )
|
45
|
+
end
|
37
46
|
pop_trace_stack( econs )
|
38
47
|
return retval
|
39
48
|
|
40
49
|
end
|
41
50
|
|
42
|
-
def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil
|
51
|
+
def self.evaluate_object jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil
|
43
52
|
|
44
53
|
rules, annotations = get_rules_and_annotations( jcr )
|
45
54
|
|
46
55
|
# if the data is not an object (Hash)
|
47
56
|
return evaluate_not( annotations,
|
48
|
-
Evaluation.new( false, "#{data} is not an object for #{raised_rule(jcr,rule_atom)}"),
|
57
|
+
Evaluation.new( false, "#{data} is not an object for #{raised_rule(jcr,rule_atom)}"),
|
58
|
+
econs, target_annotations ) unless data.is_a? Hash
|
49
59
|
|
50
60
|
# if the object has no members and there are zero sub-rules (it is suppose to be empty)
|
51
61
|
return evaluate_not( annotations,
|
52
|
-
Evaluation.new( true, nil ), econs ) if rules.empty? && data.length == 0
|
62
|
+
Evaluation.new( true, nil ), econs, target_annotations ) if rules.empty? && data.length == 0
|
53
63
|
|
54
64
|
# if the object has members and there are zero sub-rules (it is suppose to be empty)
|
55
65
|
return evaluate_not( annotations,
|
56
|
-
Evaluation.new( false, "Non-empty object for #{raised_rule(jcr,rule_atom)}" ),
|
66
|
+
Evaluation.new( false, "Non-empty object for #{raised_rule(jcr,rule_atom)}" ),
|
67
|
+
econs, target_annotations ) if rules.empty? && data.length != 0
|
57
68
|
|
58
69
|
retval = nil
|
59
70
|
behavior = ObjectBehavior.new unless behavior
|
@@ -64,7 +75,7 @@ module JCR
|
|
64
75
|
if rule[:choice_combiner] && retval && retval.success
|
65
76
|
next
|
66
77
|
elsif rule[:sequence_combiner] && retval && !retval.success
|
67
|
-
return evaluate_not( annotations, retval, econs ) # short circuit
|
78
|
+
return evaluate_not( annotations, retval, econs, target_annotations ) # short circuit
|
68
79
|
end
|
69
80
|
|
70
81
|
repeat_min, repeat_max, repeat_step = get_repetitions( rule, econs )
|
@@ -76,13 +87,14 @@ module JCR
|
|
76
87
|
# Also, groups must be handed the entire object, not key/values
|
77
88
|
# as member rules use.
|
78
89
|
|
79
|
-
|
90
|
+
grule,gtarget_annotations = get_group(rule, econs)
|
91
|
+
if grule
|
80
92
|
|
81
93
|
successes = 0
|
82
94
|
for i in 0..repeat_max-1
|
83
95
|
group_behavior = ObjectBehavior.new
|
84
96
|
group_behavior.checked_hash.merge!( behavior.checked_hash )
|
85
|
-
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior )
|
97
|
+
e = evaluate_rule( grule, rule_atom, data, econs, group_behavior, gtarget_annotations )
|
86
98
|
if e.success
|
87
99
|
behavior.checked_hash.merge!( group_behavior.checked_hash )
|
88
100
|
successes = successes + 1
|
@@ -92,11 +104,11 @@ module JCR
|
|
92
104
|
end
|
93
105
|
|
94
106
|
if successes == 0 && repeat_min > 0
|
95
|
-
retval = Evaluation.new( false, "object does not contain group #{rule} for #{raised_rule(jcr,rule_atom)}")
|
107
|
+
retval = Evaluation.new( false, "object does not contain group #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
96
108
|
elsif successes < repeat_min
|
97
|
-
retval = Evaluation.new( false, "object does not have contain necessary number of group #{rule} for #{raised_rule(jcr,rule_atom)}")
|
109
|
+
retval = Evaluation.new( false, "object does not have contain necessary number of group #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
98
110
|
elsif repeat_step && ( successes - repeat_min ) % repeat_step != 0
|
99
|
-
retval = Evaluation.new( false, "object matches (#{successes}) do not have contain repetition #{repeat_max} % #{repeat_step} of group #{rule} for #{raised_rule(jcr,rule_atom)}")
|
111
|
+
retval = Evaluation.new( false, "object matches (#{successes}) do not have contain repetition #{repeat_max} % #{repeat_step} of group #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
100
112
|
else
|
101
113
|
retval = Evaluation.new( true, nil )
|
102
114
|
end
|
@@ -109,7 +121,7 @@ module JCR
|
|
109
121
|
# if defined by a name, and not a regex, just pluck it from the object
|
110
122
|
# and short-circuit the enumeration
|
111
123
|
|
112
|
-
lookahead = get_leaf_rule( rule, econs )
|
124
|
+
lookahead, ltarget_annotations = get_leaf_rule( rule, econs )
|
113
125
|
lrules, lannotations = get_rules_and_annotations( lookahead[:member_rule] )
|
114
126
|
if lrules[0][:member_name]
|
115
127
|
|
@@ -118,13 +130,13 @@ module JCR
|
|
118
130
|
v = data[k]
|
119
131
|
if v
|
120
132
|
unless behavior.checked_hash[k]
|
121
|
-
e = evaluate_rule(rule, rule_atom, [k, v], econs, nil)
|
133
|
+
e = evaluate_rule(rule, rule_atom, [k, v], econs, nil, nil)
|
122
134
|
behavior.checked_hash[k] = e.success
|
123
135
|
repeat_results[ k ] = v if e.success
|
124
136
|
end
|
125
137
|
else
|
126
138
|
trace( econs, "No member '#{k}' found in object.")
|
127
|
-
e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil)
|
139
|
+
e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil, nil)
|
128
140
|
repeat_results[ nil ] = nil if e.success
|
129
141
|
end
|
130
142
|
|
@@ -137,7 +149,7 @@ module JCR
|
|
137
149
|
repeat_results = data.select do |k,v|
|
138
150
|
unless behavior.checked_hash[k]
|
139
151
|
if i < repeat_max
|
140
|
-
e = evaluate_rule(rule, rule_atom, [k, v], econs, nil)
|
152
|
+
e = evaluate_rule(rule, rule_atom, [k, v], econs, nil, nil)
|
141
153
|
behavior.checked_hash[k] = e.success
|
142
154
|
i = i + 1 if e.success
|
143
155
|
found = true if e.member_found
|
@@ -147,7 +159,7 @@ module JCR
|
|
147
159
|
end
|
148
160
|
unless found
|
149
161
|
trace( econs, "No member matching #{regex} found in object.")
|
150
|
-
e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil)
|
162
|
+
e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil, nil)
|
151
163
|
repeat_results[ nil ] = nil if e.success
|
152
164
|
end
|
153
165
|
|
@@ -155,13 +167,13 @@ module JCR
|
|
155
167
|
|
156
168
|
trace( econs, "Found #{repeat_results.length} matching members repetitions in object with min #{repeat_min} and max #{repeat_max}" )
|
157
169
|
if repeat_results.length == 0 && repeat_min > 0
|
158
|
-
retval = Evaluation.new( false, "object does not contain #{rule} for #{raised_rule(jcr,rule_atom)}")
|
170
|
+
retval = Evaluation.new( false, "object does not contain #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
159
171
|
elsif repeat_results.length < repeat_min
|
160
|
-
retval = Evaluation.new( false, "object does not have enough #{rule} for #{raised_rule(jcr,rule_atom)}")
|
172
|
+
retval = Evaluation.new( false, "object does not have enough #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
161
173
|
elsif repeat_results.length > repeat_max
|
162
|
-
retval = Evaluation.new( false, "object has too many #{rule} for #{raised_rule(jcr,rule_atom)}")
|
174
|
+
retval = Evaluation.new( false, "object has too many #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
163
175
|
elsif repeat_step && ( repeat_results.length - repeat_min ) % repeat_step != 0
|
164
|
-
retval = Evaluation.new( false, "object matches (#{repeat_results.length}) does not match repetition step of #{repeat_max} & #{repeat_step} for #{rule} for #{raised_rule(jcr,rule_atom)}")
|
176
|
+
retval = Evaluation.new( false, "object matches (#{repeat_results.length}) does not match repetition step of #{repeat_max} & #{repeat_step} for #{jcr_to_s(rule)} for #{raised_rule(jcr,rule_atom)}")
|
165
177
|
else
|
166
178
|
retval = Evaluation.new( true, nil)
|
167
179
|
end
|
@@ -169,7 +181,7 @@ module JCR
|
|
169
181
|
|
170
182
|
end # end if grule else
|
171
183
|
|
172
|
-
return evaluate_not( annotations, retval, econs )
|
184
|
+
return evaluate_not( annotations, retval, econs, target_annotations )
|
173
185
|
end
|
174
186
|
|
175
187
|
def self.object_to_s( jcr, shallow=true )
|
data/lib/jcr/evaluate_rules.rb
CHANGED
@@ -68,8 +68,14 @@ module JCR
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def report_failure failure
|
71
|
-
|
72
|
-
@failures[
|
71
|
+
coord = JCR::trace_coord( self )
|
72
|
+
@failures[ coord ] = Array.new unless @failures[ coord ]
|
73
|
+
@failures[ coord ] << failure
|
74
|
+
end
|
75
|
+
|
76
|
+
def report_success
|
77
|
+
coord = JCR::trace_coord( self )
|
78
|
+
@failures.delete( coord )
|
73
79
|
end
|
74
80
|
end
|
75
81
|
|
@@ -91,7 +97,7 @@ module JCR
|
|
91
97
|
end
|
92
98
|
end
|
93
99
|
|
94
|
-
def self.evaluate_rule jcr, rule_atom, data, econs, behavior = nil
|
100
|
+
def self.evaluate_rule jcr, rule_atom, data, econs, behavior = nil, target_annotations = nil
|
95
101
|
if jcr.is_a?( Hash )
|
96
102
|
if jcr[:rule_name]
|
97
103
|
rn = slice_to_s( jcr[:rule_name] )
|
@@ -102,26 +108,24 @@ module JCR
|
|
102
108
|
retval = Evaluation.new( false, "failed to evaluate rule properly" )
|
103
109
|
case
|
104
110
|
when behavior.is_a?( ArrayBehavior )
|
105
|
-
retval = evaluate_array_rule( jcr, rule_atom, data, econs, behavior)
|
111
|
+
retval = evaluate_array_rule( jcr, rule_atom, data, econs, behavior, target_annotations )
|
106
112
|
when behavior.is_a?( ObjectBehavior )
|
107
|
-
retval = evaluate_object_rule( jcr, rule_atom, data, econs, behavior)
|
113
|
+
retval = evaluate_object_rule( jcr, rule_atom, data, econs, behavior, target_annotations )
|
108
114
|
when jcr[:rule]
|
109
|
-
retval = evaluate_rule( jcr[:rule], rule_atom, data, econs, behavior)
|
115
|
+
retval = evaluate_rule( jcr[:rule], rule_atom, data, econs, behavior, target_annotations)
|
110
116
|
when jcr[:target_rule_name]
|
111
|
-
target =
|
112
|
-
|
113
|
-
trace( econs, "Referencing target rule #{slice_to_s(target)} from #{slice_to_s( jcr[:target_rule_name][:rule_name] )}" )
|
114
|
-
retval = evaluate_rule( target, target, data, econs, behavior )
|
117
|
+
target, target_annotations = get_target_rule( jcr, econs )
|
118
|
+
retval = evaluate_rule( target, target, data, econs, behavior, target_annotations )
|
115
119
|
when jcr[:primitive_rule]
|
116
|
-
retval = evaluate_value_rule( jcr[:primitive_rule], rule_atom, data, econs)
|
120
|
+
retval = evaluate_value_rule( jcr[:primitive_rule], rule_atom, data, econs, nil, target_annotations )
|
117
121
|
when jcr[:group_rule]
|
118
|
-
retval = evaluate_group_rule( jcr[:group_rule], rule_atom, data, econs, behavior)
|
122
|
+
retval = evaluate_group_rule( jcr[:group_rule], rule_atom, data, econs, behavior, target_annotations)
|
119
123
|
when jcr[:array_rule]
|
120
|
-
retval = evaluate_array_rule( jcr[:array_rule], rule_atom, data, econs, behavior)
|
124
|
+
retval = evaluate_array_rule( jcr[:array_rule], rule_atom, data, econs, behavior, target_annotations )
|
121
125
|
when jcr[:object_rule]
|
122
|
-
retval = evaluate_object_rule( jcr[:object_rule], rule_atom, data, econs, behavior)
|
126
|
+
retval = evaluate_object_rule( jcr[:object_rule], rule_atom, data, econs, behavior, target_annotations)
|
123
127
|
when jcr[:member_rule]
|
124
|
-
retval = evaluate_member_rule( jcr[:member_rule], rule_atom, data, econs)
|
128
|
+
retval = evaluate_member_rule( jcr[:member_rule], rule_atom, data, econs, nil, target_annotations)
|
125
129
|
else
|
126
130
|
retval = Evaluation.new( true, nil )
|
127
131
|
end
|
@@ -153,6 +157,13 @@ module JCR
|
|
153
157
|
return retval
|
154
158
|
end
|
155
159
|
|
160
|
+
def self.get_target_rule jcr, econs
|
161
|
+
target = econs.mapping[ jcr[:target_rule_name][:rule_name].to_s ]
|
162
|
+
raise "Target rule not in mapping. This should have been checked earlier." unless target
|
163
|
+
trace( econs, "Referencing target rule #{slice_to_s(target)} from #{slice_to_s( jcr[:target_rule_name][:rule_name] )}" )
|
164
|
+
return target,jcr[:target_rule_name][:annotations]
|
165
|
+
end
|
166
|
+
|
156
167
|
def self.get_repetitions rule, econs
|
157
168
|
|
158
169
|
repeat_min = 1
|
@@ -245,11 +256,20 @@ module JCR
|
|
245
256
|
return new_rule
|
246
257
|
end
|
247
258
|
|
248
|
-
def self.evaluate_not annotations, evaluation, econs
|
259
|
+
def self.evaluate_not annotations, evaluation, econs, target_annotations = nil
|
249
260
|
is_not = false
|
261
|
+
|
262
|
+
target_annotations.each do |a|
|
263
|
+
if a[:not_annotation]
|
264
|
+
trace( econs, "Not annotation found on reference to rule.")
|
265
|
+
is_not = !is_not
|
266
|
+
break
|
267
|
+
end
|
268
|
+
end if target_annotations
|
269
|
+
|
250
270
|
annotations.each do |a|
|
251
271
|
if a[:not_annotation]
|
252
|
-
is_not =
|
272
|
+
is_not = !is_not
|
253
273
|
break
|
254
274
|
end
|
255
275
|
end
|
@@ -262,27 +282,23 @@ module JCR
|
|
262
282
|
end
|
263
283
|
|
264
284
|
def self.get_group rule, econs
|
265
|
-
return rule[:group_rule] if rule[:group_rule]
|
285
|
+
return rule[:group_rule], nil if rule[:group_rule]
|
266
286
|
#else
|
267
287
|
if rule[:target_rule_name]
|
268
|
-
target =
|
269
|
-
|
270
|
-
trace( econs, "Referencing target rule #{slice_to_s(target)} from #{slice_to_s( rule[:target_rule_name][:rule_name] )}" )
|
271
|
-
return get_group( target, econs )
|
288
|
+
target, target_annotations = get_target_rule( rule, econs )
|
289
|
+
return get_group( target, econs )[0], target_annotations
|
272
290
|
end
|
273
291
|
#else
|
274
|
-
return false
|
292
|
+
return false, nil
|
275
293
|
end
|
276
294
|
|
277
295
|
def self.get_leaf_rule rule, econs
|
278
296
|
if rule[:target_rule_name ]
|
279
|
-
target =
|
280
|
-
|
281
|
-
trace( econs, "Referencing target rule #{slice_to_s(target)} from #{slice_to_s( rule[:target_rule_name][:rule_name] )}" )
|
282
|
-
return target
|
297
|
+
target, target_annotations = get_target_rule( rule, econs )
|
298
|
+
return target, target_annotations
|
283
299
|
end
|
284
300
|
#else
|
285
|
-
return rule
|
301
|
+
return rule, nil
|
286
302
|
end
|
287
303
|
|
288
304
|
def self.push_trace_stack econs, jcr
|
@@ -320,11 +336,16 @@ module JCR
|
|
320
336
|
message = "#{message} data: #{rule_data( data )}"
|
321
337
|
end
|
322
338
|
last = econs.trace_stack.last
|
323
|
-
|
324
|
-
puts "[ #{econs.trace_stack.length}:#{pos} ] #{message}"
|
339
|
+
puts "[ depth=#{econs.trace_stack.length}:#{trace_coord(econs)} ] #{message}"
|
325
340
|
end
|
326
341
|
end
|
327
342
|
|
343
|
+
def self.trace_coord econs
|
344
|
+
last = econs.trace_stack.last
|
345
|
+
pos = "#{last.line_and_column}" if last
|
346
|
+
return "pos=#{pos}"
|
347
|
+
end
|
348
|
+
|
328
349
|
def self.rule_def type, jcr
|
329
350
|
s = ""
|
330
351
|
case type
|
@@ -334,14 +355,18 @@ module JCR
|
|
334
355
|
s = elide(member_to_s(jcr))
|
335
356
|
when "object"
|
336
357
|
s = elide(object_to_s(jcr))
|
358
|
+
when "object group"
|
359
|
+
s = elide(group_to_s(jcr))
|
337
360
|
when "array"
|
338
361
|
s = elide(array_to_s(jcr))
|
362
|
+
when "array group"
|
363
|
+
s = elide(array_to_s(jcr))
|
339
364
|
when "group"
|
340
365
|
s = elide(group_to_s(jcr))
|
341
366
|
else
|
342
367
|
s = "** unknown rule **"
|
343
368
|
end
|
344
|
-
return "#{type} definition
|
369
|
+
return "#{type} definition << #{s} >>"
|
345
370
|
end
|
346
371
|
|
347
372
|
def self.trace_def econs, type, jcr, data
|
@@ -354,8 +379,12 @@ module JCR
|
|
354
379
|
s = elide( member_to_s( jcr ) )
|
355
380
|
when "object"
|
356
381
|
s = elide( object_to_s( jcr ) )
|
382
|
+
when "object group"
|
383
|
+
s = elide( group_to_s( jcr ) )
|
357
384
|
when "array"
|
358
385
|
s = elide( array_to_s( jcr ) )
|
386
|
+
when "array group"
|
387
|
+
s = elide( array_to_s( jcr ) )
|
359
388
|
when "group"
|
360
389
|
s = elide( group_to_s( jcr ) )
|
361
390
|
else
|
@@ -367,6 +396,7 @@ module JCR
|
|
367
396
|
|
368
397
|
def self.trace_eval econs, message, evaluation, jcr, data, type
|
369
398
|
if evaluation.success
|
399
|
+
econs.report_success
|
370
400
|
trace( econs, "#{message} evaluation is true" )
|
371
401
|
else
|
372
402
|
failure = Failure.new( data, jcr, type, evaluation, econs.trace_stack.length )
|
@@ -409,7 +439,28 @@ module JCR
|
|
409
439
|
end
|
410
440
|
|
411
441
|
def self.raised_rule jcr, rule_atom
|
412
|
-
" rule at #{slice_to_s(jcr)}
|
442
|
+
" rule at #{slice_to_s(jcr)} #{jcr_to_s(jcr)} from rule at #{slice_to_s(rule_atom)}"
|
443
|
+
end
|
444
|
+
|
445
|
+
def self.jcr_to_s( jcr, shallow=true )
|
446
|
+
if jcr.is_a? Array
|
447
|
+
retval = ""
|
448
|
+
jcr.each_with_index do |item,idx|
|
449
|
+
if idx > 1
|
450
|
+
retval = retval + " , "
|
451
|
+
end
|
452
|
+
retval = retval + jcr_to_s( item, shallow )
|
453
|
+
end
|
454
|
+
elsif jcr.is_a? Parslet::Slice
|
455
|
+
retval = slice_to_s( jcr )
|
456
|
+
else
|
457
|
+
if jcr[:q_string]
|
458
|
+
retval = value_to_s( jcr )
|
459
|
+
else
|
460
|
+
retval = rule_to_s( jcr, shallow )
|
461
|
+
end
|
462
|
+
end
|
463
|
+
return "<< " + retval + " >>"
|
413
464
|
end
|
414
465
|
|
415
466
|
def self.rule_to_s( rule, shallow=true)
|
@@ -25,14 +25,15 @@ require 'jcr/check_groups'
|
|
25
25
|
|
26
26
|
module JCR
|
27
27
|
|
28
|
-
def self.evaluate_value_rule jcr, rule_atom, data, econs
|
28
|
+
def self.evaluate_value_rule jcr, rule_atom, data, econs, behavior, target_annotations
|
29
29
|
|
30
30
|
push_trace_stack( econs, jcr )
|
31
31
|
trace( econs, "Evaluating value rule starting at #{slice_to_s(jcr)}" )
|
32
32
|
trace_def( econs, "value", jcr, data )
|
33
33
|
rules, annotations = get_rules_and_annotations( jcr )
|
34
34
|
|
35
|
-
retval = evaluate_not( annotations, evaluate_values( rules[0], rule_atom, data, econs ),
|
35
|
+
retval = evaluate_not( annotations, evaluate_values( rules[0], rule_atom, data, econs ),
|
36
|
+
econs, target_annotations )
|
36
37
|
trace_eval( econs, "Value", retval, jcr, data, "value")
|
37
38
|
pop_trace_stack( econs )
|
38
39
|
return retval
|
@@ -401,7 +402,7 @@ module JCR
|
|
401
402
|
end
|
402
403
|
|
403
404
|
def self.bad_value jcr, rule_atom, expected, actual
|
404
|
-
Evaluation.new( false, "expected #{expected} but got #{actual} for #{raised_rule(jcr,rule_atom)}" )
|
405
|
+
Evaluation.new( false, "expected << #{expected} >> but got << #{actual} >> for #{raised_rule(jcr,rule_atom)}" )
|
405
406
|
end
|
406
407
|
|
407
408
|
def self.value_to_s( jcr, shallow=true )
|
data/lib/jcr/jcr.rb
CHANGED
@@ -17,6 +17,7 @@ require 'rubygems'
|
|
17
17
|
require 'json'
|
18
18
|
require 'pp'
|
19
19
|
|
20
|
+
require 'jcr/jcr_validator_error'
|
20
21
|
require 'jcr/parser'
|
21
22
|
require 'jcr/evaluate_rules'
|
22
23
|
require 'jcr/check_groups'
|
@@ -63,7 +64,7 @@ module JCR
|
|
63
64
|
@trace = trace
|
64
65
|
@failed_roots = []
|
65
66
|
if ruleset
|
66
|
-
ingested = JCR.ingest_ruleset( ruleset,
|
67
|
+
ingested = JCR.ingest_ruleset( ruleset, nil, nil )
|
67
68
|
@mapping = ingested.mapping
|
68
69
|
@callbacks = ingested.callbacks
|
69
70
|
@id = ingested.id
|
@@ -73,7 +74,7 @@ module JCR
|
|
73
74
|
end
|
74
75
|
|
75
76
|
def override( ruleset )
|
76
|
-
overridden = JCR.ingest_ruleset( ruleset,
|
77
|
+
overridden = JCR.ingest_ruleset( ruleset, @mapping, nil )
|
77
78
|
mapping = {}
|
78
79
|
mapping.merge!( @mapping )
|
79
80
|
mapping.merge!( overridden.mapping )
|
@@ -87,7 +88,7 @@ module JCR
|
|
87
88
|
end
|
88
89
|
|
89
90
|
def override!( ruleset )
|
90
|
-
overridden = JCR.ingest_ruleset( ruleset,
|
91
|
+
overridden = JCR.ingest_ruleset( ruleset, @mapping, nil )
|
91
92
|
@mapping.merge!( overridden.mapping )
|
92
93
|
@callbacks.merge!( overridden.callbacks )
|
93
94
|
@roots.concat( overridden.roots )
|
@@ -95,11 +96,14 @@ module JCR
|
|
95
96
|
|
96
97
|
end
|
97
98
|
|
98
|
-
def self.ingest_ruleset( ruleset,
|
99
|
+
def self.ingest_ruleset( ruleset, existing_mapping = nil, ruleset_alias=nil )
|
99
100
|
tree = JCR.parse( ruleset )
|
100
|
-
mapping = JCR.map_rule_names( tree,
|
101
|
-
|
102
|
-
|
101
|
+
mapping = JCR.map_rule_names( tree, ruleset_alias )
|
102
|
+
combined_mapping = {}
|
103
|
+
combined_mapping.merge!( existing_mapping ) if existing_mapping
|
104
|
+
combined_mapping.merge!( mapping )
|
105
|
+
JCR.check_rule_target_names( tree, combined_mapping )
|
106
|
+
JCR.check_groups( tree, combined_mapping )
|
103
107
|
roots = JCR.find_roots( tree )
|
104
108
|
ctx = Context.new
|
105
109
|
ctx.tree = tree
|
@@ -114,19 +118,19 @@ module JCR
|
|
114
118
|
roots = []
|
115
119
|
if root_name
|
116
120
|
root_rule = ctx.mapping[root_name]
|
117
|
-
raise "No rule by the name of #{root_name} for a root rule has been found" unless root_rule
|
121
|
+
raise JcrValidatorError, "No rule by the name of #{root_name} for a root rule has been found" unless root_rule
|
118
122
|
root = JCR::Root.new( root_rule, root_name )
|
119
123
|
roots << root
|
120
124
|
else
|
121
125
|
roots = ctx.roots
|
122
126
|
end
|
123
127
|
|
124
|
-
raise "No root rule defined. Specify a root rule name" if roots.empty?
|
128
|
+
raise JcrValidatorError, "No root rule defined. Specify a root rule name" if roots.empty?
|
125
129
|
|
126
130
|
retval = nil
|
127
131
|
roots.each do |r|
|
128
132
|
pp "Evaluating Root:", rule_to_s( r.rule, false ) if ctx.trace
|
129
|
-
raise "Root rules cannot be member rules" if r.rule[:member_rule]
|
133
|
+
raise JcrValidatorError, "Root rules cannot be member rules" if r.rule[:member_rule]
|
130
134
|
econs = EvalConditions.new( ctx.mapping, ctx.callbacks, ctx.trace )
|
131
135
|
retval = JCR.evaluate_rule( r.rule, r.rule, data, econs )
|
132
136
|
break if retval.success
|
@@ -143,24 +147,40 @@ module JCR
|
|
143
147
|
report = []
|
144
148
|
ctx.failed_roots.each do |failed_root|
|
145
149
|
if failed_root.name
|
146
|
-
report << "-
|
150
|
+
report << "- Failures for root rule named '#{failed_root.name}'"
|
147
151
|
else
|
148
|
-
report << "-
|
152
|
+
report << "- Failures for root rule at line #{failed_root.pos[0]}"
|
149
153
|
end
|
150
154
|
failed_root.failures.sort.map do |stack_level, failures|
|
151
155
|
if failures.length > 1
|
152
|
-
report << " - failure at rule
|
156
|
+
report << " - failure at rule #{stack_level} caused by one of the following #{failures.length} reasons"
|
153
157
|
else
|
154
|
-
report << " - failure at rule
|
158
|
+
report << " - failure at rule #{stack_level} caused by"
|
155
159
|
end
|
156
160
|
failures.each_with_index do |failure, index|
|
157
|
-
|
161
|
+
lines = breakup_message( "<< #{failure.json_elided} >> failed rule #{failure.definition} at #{failure.pos} because #{failure.evaluation.reason}", 75 )
|
162
|
+
lines.each_with_index do |l,i|
|
163
|
+
if i == 0
|
164
|
+
report << " - #{l}"
|
165
|
+
else
|
166
|
+
report << " #{l}"
|
167
|
+
end
|
168
|
+
end
|
158
169
|
end
|
159
170
|
end
|
160
171
|
end
|
161
172
|
return report
|
162
173
|
end
|
163
174
|
|
175
|
+
def self.breakup_message( message, line_length )
|
176
|
+
line = message.gsub(/(.{1,#{line_length}})(\s+|\Z)/, "\\1\n")
|
177
|
+
lines = []
|
178
|
+
line.each_line do |l|
|
179
|
+
lines << l.strip
|
180
|
+
end
|
181
|
+
return lines
|
182
|
+
end
|
183
|
+
|
164
184
|
def self.main my_argv=nil
|
165
185
|
|
166
186
|
my_argv = ARGV unless my_argv
|
@@ -199,8 +219,9 @@ module JCR
|
|
199
219
|
options[:testjcr] = true
|
200
220
|
end
|
201
221
|
|
202
|
-
opt.on("--process-parts", "creates smaller files for specification writing" ) do |
|
222
|
+
opt.on("--process-parts [DIRECTORY]", "creates smaller files for specification writing" ) do |directory|
|
203
223
|
options[:process_parts] = true
|
224
|
+
options[:process_parts_directory] = directory
|
204
225
|
end
|
205
226
|
|
206
227
|
opt.on("-S STRING","name of root rule. All roots will be tried if none is specified") do |root_name|
|
@@ -248,15 +269,22 @@ module JCR
|
|
248
269
|
opt.separator ""
|
249
270
|
opt.separator "Return codes:"
|
250
271
|
opt.separator " 0 = success"
|
251
|
-
opt.separator " 1 = parsing or other bad condition"
|
252
|
-
opt.separator " 2 =
|
272
|
+
opt.separator " 1 = bad JCR parsing or other bad condition"
|
273
|
+
opt.separator " 2 = invalid option or bad use of command"
|
253
274
|
opt.separator " 3 = unsuccessful evaluation of JSON"
|
254
275
|
|
255
276
|
opt.separator ""
|
256
277
|
opt.separator "JCR Version " + JCR::VERSION
|
257
278
|
end
|
258
279
|
|
259
|
-
|
280
|
+
begin
|
281
|
+
opt_parser.parse! my_argv
|
282
|
+
rescue OptionParser::InvalidOption => e
|
283
|
+
puts "Unable to interpret command or options"
|
284
|
+
puts e.message
|
285
|
+
puts "", "Use -h for help"
|
286
|
+
return 2
|
287
|
+
end
|
260
288
|
|
261
289
|
if options[:help]
|
262
290
|
puts "HELP","----",""
|
@@ -264,7 +292,7 @@ module JCR
|
|
264
292
|
return 2
|
265
293
|
elsif !options[:ruleset]
|
266
294
|
puts "No ruleset passed! Use -R or -r options.", ""
|
267
|
-
puts
|
295
|
+
puts "Use -h for help"
|
268
296
|
return 2
|
269
297
|
else
|
270
298
|
|
@@ -290,7 +318,13 @@ module JCR
|
|
290
318
|
|
291
319
|
if options[:process_parts]
|
292
320
|
parts = JCR::JcrParts.new
|
293
|
-
parts.process_ruleset( options[:ruleset] )
|
321
|
+
parts.process_ruleset( options[:ruleset], options[:process_parts_directory] )
|
322
|
+
if options[:overrides ]
|
323
|
+
options[:overrides].each do |ov|
|
324
|
+
parts = JCR::JcrParts.new
|
325
|
+
parts.process_ruleset( ov, options[:process_parts_directory] )
|
326
|
+
end
|
327
|
+
end
|
294
328
|
end
|
295
329
|
|
296
330
|
if options[:testjcr]
|
@@ -328,6 +362,9 @@ module JCR
|
|
328
362
|
return ec
|
329
363
|
end
|
330
364
|
|
365
|
+
rescue JCR::JcrValidatorError => jcr_error
|
366
|
+
puts jcr_error.message
|
367
|
+
return 1
|
331
368
|
rescue Parslet::ParseFailed => failure
|
332
369
|
puts failure.parse_failure_cause.ascii_tree unless options[:quiet]
|
333
370
|
return 1
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Copyright (c) 2017 American Registry for Internet Numbers
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
13
|
+
# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
module JCR
|
16
|
+
|
17
|
+
class JcrValidatorError < StandardError
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/jcr/map_rule_names.rb
CHANGED
@@ -12,11 +12,12 @@
|
|
12
12
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
13
13
|
# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
14
|
|
15
|
+
require 'jcr/jcr_validator_error'
|
15
16
|
require 'jcr/parser'
|
16
17
|
|
17
18
|
module JCR
|
18
19
|
|
19
|
-
def self.map_rule_names( tree,
|
20
|
+
def self.map_rule_names( tree, ruleset_alias = nil )
|
20
21
|
prefix = ""
|
21
22
|
if ruleset_alias
|
22
23
|
prefix = ruleset_alias
|
@@ -31,8 +32,8 @@ module JCR
|
|
31
32
|
tree.each do |node|
|
32
33
|
if node[:rule]
|
33
34
|
rn = prefix + node[:rule][:rule_name].to_str
|
34
|
-
if rule_name_maping[ rn ]
|
35
|
-
raise "Rule #{rn} already exists and is defined more than once"
|
35
|
+
if rule_name_maping[ rn ]
|
36
|
+
raise JCR::JcrValidatorError, "Rule #{rn} already exists and is defined more than once"
|
36
37
|
else
|
37
38
|
rule_name_maping[ rn ] = node[:rule]
|
38
39
|
end
|
@@ -76,7 +77,8 @@ module JCR
|
|
76
77
|
def self.raise_rule_name_missing rule_name
|
77
78
|
pos = rule_name.line_and_column
|
78
79
|
name = rule_name.to_str
|
79
|
-
raise
|
80
|
+
raise JCR::JcrValidatorError,
|
81
|
+
"rule '" + name + "' at line " + pos[0].to_s + " column " + pos[1].to_s + " does not exist"
|
80
82
|
end
|
81
83
|
|
82
84
|
end
|
data/lib/jcr/parts.rb
CHANGED
@@ -68,19 +68,23 @@ module JCR
|
|
68
68
|
|
69
69
|
# processes the lines
|
70
70
|
# ruleset is to be a string read in using File.read
|
71
|
-
def process_ruleset( ruleset )
|
71
|
+
def process_ruleset( ruleset, dirname = nil )
|
72
|
+
all_file_names = []
|
72
73
|
all_parts = []
|
73
74
|
all_parts_name = nil
|
74
75
|
current_part = nil
|
75
76
|
current_part_name = nil
|
76
77
|
ruleset.lines do |line|
|
77
78
|
if !all_parts_name && ( all_parts_name = get_all( line ) )
|
78
|
-
|
79
|
+
all_parts_name = File.join( dirname, all_parts_name ) if dirname
|
80
|
+
all_file_names << all_parts_name
|
79
81
|
elsif ( current_part_name = get_start( line ) )
|
82
|
+
current_part_name = File.join( dirname, current_part_name ) if dirname
|
80
83
|
if current_part
|
81
84
|
current_part.close
|
82
85
|
end
|
83
86
|
current_part = File.open( current_part_name, "w" )
|
87
|
+
all_file_names << current_part_name
|
84
88
|
elsif get_end( line ) && current_part
|
85
89
|
current_part.close
|
86
90
|
current_part = nil
|
@@ -101,6 +105,16 @@ module JCR
|
|
101
105
|
end
|
102
106
|
f.close
|
103
107
|
end
|
108
|
+
if all_file_names.length
|
109
|
+
xml_fn = File.basename( all_file_names[0],".*" ) + "_xml_entity_refs"
|
110
|
+
xml_fn = File.join( File.dirname( all_file_names[0] ), xml_fn )
|
111
|
+
xml = File.open( xml_fn, "w" )
|
112
|
+
all_file_names.each do |fn|
|
113
|
+
bn = File.basename( fn, ".*" )
|
114
|
+
xml.puts( "<!ENTITY #{bn} PUBLIC '' '#{fn}'>")
|
115
|
+
end
|
116
|
+
xml.close
|
117
|
+
end
|
104
118
|
end
|
105
119
|
|
106
120
|
end
|
@@ -74,7 +74,7 @@ module JCR
|
|
74
74
|
ruleset = File.open( uri.path )
|
75
75
|
end
|
76
76
|
|
77
|
-
import_ctx = JCR.ingest_ruleset( ruleset,
|
77
|
+
import_ctx = JCR.ingest_ruleset( ruleset, nil, ruleset_alias )
|
78
78
|
ctx.mapping.merge!( import_ctx.mapping )
|
79
79
|
ctx.roots.concat( import_ctx.roots )
|
80
80
|
|
data/lib/jcr/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2016 American Registry for Internet Numbers
|
1
|
+
# Copyright (c) 2016-2017 American Registry for Internet Numbers
|
2
2
|
#
|
3
3
|
# Permission to use, copy, modify, and/or distribute this software for any
|
4
4
|
# purpose with or without fee is hereby granted, provided that the above
|
@@ -15,6 +15,6 @@
|
|
15
15
|
|
16
16
|
module JCR
|
17
17
|
|
18
|
-
VERSION = "0.8.
|
18
|
+
VERSION = "0.8.1"
|
19
19
|
|
20
20
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jcrvalidator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Newton
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-12-
|
12
|
+
date: 2017-12-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parslet
|
@@ -85,6 +85,7 @@ files:
|
|
85
85
|
- lib/jcr/evaluate_value_rules.rb
|
86
86
|
- lib/jcr/find_roots.rb
|
87
87
|
- lib/jcr/jcr.rb
|
88
|
+
- lib/jcr/jcr_validator_error.rb
|
88
89
|
- lib/jcr/map_rule_names.rb
|
89
90
|
- lib/jcr/parser.rb
|
90
91
|
- lib/jcr/parts.rb
|