jcrvalidator 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|