jcrvalidator 0.6.5 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jcr/evaluate_array_rules.rb +1 -1
- data/lib/jcr/evaluate_group_rules.rb +1 -1
- data/lib/jcr/evaluate_object_rules.rb +1 -1
- data/lib/jcr/evaluate_rules.rb +128 -30
- data/lib/jcr/evaluate_value_rules.rb +8 -8
- data/lib/jcr/find_roots.rb +34 -8
- data/lib/jcr/jcr.rb +73 -22
- data/lib/jcr/parser.rb +34 -31
- data/lib/jcr/version.rb +1 -1
- metadata +9 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1092c1613500ed477ee3eb26367ed73fee3a940f
|
4
|
+
data.tar.gz: 824cdfcc22c6dc6a03d55bc10ad75857c881c627
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f6f55143125ef7cf87457a53bb66edb4c3b353fb710e8513cf85e893f969d7cb3b95a78d98429fef5c55b8b25fb4306455ecb1cf9c77c449c71d1ad2dedba84
|
7
|
+
data.tar.gz: 9539a3d5ad7577a119f30bb69596c8cb279d1d45818574b26f22c1f71613cac0ba785268a56797f57266b5533de8cc159fa42f9055643d8272a141642b024813
|
@@ -289,6 +289,6 @@ module JCR
|
|
289
289
|
|
290
290
|
def self.array_to_s( jcr, shallow=true )
|
291
291
|
rules, annotations = get_rules_and_annotations( jcr )
|
292
|
-
return "#{annotations_to_s( annotations)}
|
292
|
+
return "#{annotations_to_s( annotations)}[ #{rules_to_s( rules, shallow )} ]"
|
293
293
|
end
|
294
294
|
end
|
@@ -58,7 +58,7 @@ module JCR
|
|
58
58
|
|
59
59
|
def self.group_to_s( jcr, shallow=true)
|
60
60
|
rules, annotations = get_rules_and_annotations( jcr )
|
61
|
-
return "#{annotations_to_s( annotations)}
|
61
|
+
return "#{annotations_to_s( annotations)}( #{rules_to_s(rules,shallow)} )"
|
62
62
|
end
|
63
63
|
|
64
64
|
end
|
@@ -174,6 +174,6 @@ module JCR
|
|
174
174
|
|
175
175
|
def self.object_to_s( jcr, shallow=true )
|
176
176
|
rules, annotations = get_rules_and_annotations( jcr )
|
177
|
-
return "#{annotations_to_s( annotations)}
|
177
|
+
return "#{annotations_to_s( annotations)}{ #{rules_to_s(rules,shallow)} }"
|
178
178
|
end
|
179
179
|
end
|
data/lib/jcr/evaluate_rules.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2015-
|
1
|
+
# Copyright (c) 2015-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
|
@@ -54,9 +54,9 @@ module JCR
|
|
54
54
|
end
|
55
55
|
|
56
56
|
class EvalConditions
|
57
|
-
attr_accessor :mapping, :callbacks, :trace, :trace_stack, :
|
57
|
+
attr_accessor :mapping, :callbacks, :trace, :trace_stack, :failures
|
58
58
|
def initialize mapping, callbacks, trace = false
|
59
|
-
@
|
59
|
+
@failures = {}
|
60
60
|
@mapping = mapping
|
61
61
|
@trace = trace
|
62
62
|
@trace_stack = []
|
@@ -66,6 +66,29 @@ module JCR
|
|
66
66
|
@callbacks = {}
|
67
67
|
end
|
68
68
|
end
|
69
|
+
|
70
|
+
def report_failure failure
|
71
|
+
@failures[ failure.stack_level ] = Array.new unless @failures[ failure.stack_level ]
|
72
|
+
@failures[ failure.stack_level ] << failure
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Failure
|
77
|
+
attr_accessor :data, :json, :json_elided, :evaluation, :rule, :pos, :offset, :type, :definition, :stack_level, :reason_elided
|
78
|
+
def initialize data, jcr, type, evaluation, stack_level
|
79
|
+
@json = data.to_json
|
80
|
+
@json_elided = JCR::elide(@json)
|
81
|
+
@data = JCR::rule_data( data )
|
82
|
+
@rule = JCR::find_first_slice( jcr )
|
83
|
+
@pos = @rule.line_and_column
|
84
|
+
@offset = @rule.offset
|
85
|
+
@type = type
|
86
|
+
@evaluation = evaluation
|
87
|
+
@reason_elided = "unknown reason"
|
88
|
+
@reason_elided = JCR::elide( @evaluation.reason ) if @evaluation.reason
|
89
|
+
@definition = JCR::rule_def( type, jcr )
|
90
|
+
@stack_level = stack_level
|
91
|
+
end
|
69
92
|
end
|
70
93
|
|
71
94
|
def self.evaluate_rule jcr, rule_atom, data, econs, behavior = nil
|
@@ -271,22 +294,30 @@ module JCR
|
|
271
294
|
end
|
272
295
|
|
273
296
|
def self.elide s
|
274
|
-
if s.length >
|
275
|
-
s = s[0..
|
297
|
+
if s.length > 45
|
298
|
+
s = s[0..41]
|
276
299
|
s = s + " ..."
|
277
300
|
end
|
278
301
|
return s
|
279
302
|
end
|
280
303
|
|
304
|
+
def self.rule_data data=nil
|
305
|
+
if data
|
306
|
+
if data.is_a? String
|
307
|
+
s = '"' + data + '"'
|
308
|
+
else
|
309
|
+
s = data.pretty_print_inspect
|
310
|
+
end
|
311
|
+
return elide(s)
|
312
|
+
end
|
313
|
+
#else
|
314
|
+
return nil
|
315
|
+
end
|
316
|
+
|
281
317
|
def self.trace econs, message, data = nil
|
282
318
|
if econs.trace
|
283
319
|
if data
|
284
|
-
|
285
|
-
s = '"' + data + '"'
|
286
|
-
else
|
287
|
-
s = data.pretty_print_inspect
|
288
|
-
end
|
289
|
-
message = "#{message} data: #{elide(s)}"
|
320
|
+
message = "#{message} data: #{rule_data( data )}"
|
290
321
|
end
|
291
322
|
last = econs.trace_stack.last
|
292
323
|
pos = "#{last.line_and_column}@#{last.offset}" if last
|
@@ -294,6 +325,25 @@ module JCR
|
|
294
325
|
end
|
295
326
|
end
|
296
327
|
|
328
|
+
def self.rule_def type, jcr
|
329
|
+
s = ""
|
330
|
+
case type
|
331
|
+
when "value"
|
332
|
+
s = elide(value_to_s(jcr))
|
333
|
+
when "member"
|
334
|
+
s = elide(member_to_s(jcr))
|
335
|
+
when "object"
|
336
|
+
s = elide(object_to_s(jcr))
|
337
|
+
when "array"
|
338
|
+
s = elide(array_to_s(jcr))
|
339
|
+
when "group"
|
340
|
+
s = elide(group_to_s(jcr))
|
341
|
+
else
|
342
|
+
s = "** unknown rule **"
|
343
|
+
end
|
344
|
+
return "#{type} definition: #{s}"
|
345
|
+
end
|
346
|
+
|
297
347
|
def self.trace_def econs, type, jcr, data
|
298
348
|
if econs.trace
|
299
349
|
s = ""
|
@@ -311,7 +361,7 @@ module JCR
|
|
311
361
|
else
|
312
362
|
s = "** unknown rule **"
|
313
363
|
end
|
314
|
-
trace( econs,
|
364
|
+
trace( econs, rule_def( type, jcr ) )
|
315
365
|
end
|
316
366
|
end
|
317
367
|
|
@@ -319,19 +369,9 @@ module JCR
|
|
319
369
|
if evaluation.success
|
320
370
|
trace( econs, "#{message} evaluation is true" )
|
321
371
|
else
|
372
|
+
failure = Failure.new( data, jcr, type, evaluation, econs.trace_stack.length )
|
373
|
+
econs.report_failure( failure )
|
322
374
|
trace( econs, "#{message} evaluation failed: #{evaluation.reason}")
|
323
|
-
unless econs.first_failure
|
324
|
-
econs.first_failure = evaluation
|
325
|
-
trace( econs, "** LIKELY ROOT CAUSE FOR FAILURE **" )
|
326
|
-
trace( econs, "***********************************" )
|
327
|
-
rule = find_first_slice( jcr )
|
328
|
-
pos = "Failed rule at line,column: #{rule.line_and_column} file position offset: #{rule.offset}"
|
329
|
-
trace( econs, pos )
|
330
|
-
trace_def( econs, type, jcr, data )
|
331
|
-
data_s = "JSON that failed to validate: #{data.to_json}"
|
332
|
-
trace( econs, data_s )
|
333
|
-
trace( econs, "***********************************" )
|
334
|
-
end
|
335
375
|
end
|
336
376
|
end
|
337
377
|
|
@@ -373,6 +413,20 @@ module JCR
|
|
373
413
|
end
|
374
414
|
|
375
415
|
def self.rule_to_s( rule, shallow=true)
|
416
|
+
if rule[:rule_name]
|
417
|
+
if rule[:primitive_rule]
|
418
|
+
retval = "$#{rule[:rule_name].to_s} =: #{ruletype_to_s( rule, shallow )}"
|
419
|
+
else
|
420
|
+
retval = "$#{rule[:rule_name].to_s} = #{ruletype_to_s( rule, shallow )}"
|
421
|
+
end
|
422
|
+
else
|
423
|
+
retval = ruletype_to_s( rule, shallow )
|
424
|
+
end
|
425
|
+
return retval
|
426
|
+
end
|
427
|
+
|
428
|
+
def self.ruletype_to_s( rule, shallow=true )
|
429
|
+
|
376
430
|
if rule[:primitive_rule]
|
377
431
|
retval = value_to_s( rule[:primitive_rule] )
|
378
432
|
elsif rule[:member_rule]
|
@@ -393,6 +447,7 @@ module JCR
|
|
393
447
|
retval = "** unknown rule definition ** #{rule}"
|
394
448
|
end
|
395
449
|
return retval
|
450
|
+
|
396
451
|
end
|
397
452
|
|
398
453
|
def self.rules_to_s( rules, shallow=true)
|
@@ -405,7 +460,7 @@ module JCR
|
|
405
460
|
elsif rule[:sequence_combiner]
|
406
461
|
retval = retval + " , "
|
407
462
|
end
|
408
|
-
retval = retval + rule_to_s( rule, shallow )
|
463
|
+
retval = retval + rule_to_s( rule, shallow ) + repetitions_to_s( rule )
|
409
464
|
end
|
410
465
|
return retval
|
411
466
|
end
|
@@ -415,13 +470,13 @@ module JCR
|
|
415
470
|
annotations.each do |a|
|
416
471
|
case
|
417
472
|
when a[:unordered_annotation]
|
418
|
-
retval = retval + "
|
473
|
+
retval = retval + "@{unordered}"
|
419
474
|
when a[:not_annotation]
|
420
|
-
retval = retval + "
|
475
|
+
retval = retval + "@{not}"
|
421
476
|
when a[:root_annotation]
|
422
|
-
retval = retval + "
|
477
|
+
retval = retval + "@{root}"
|
423
478
|
else
|
424
|
-
retval = retval + "
|
479
|
+
retval = retval + "@{ ** unknown annotation ** }"
|
425
480
|
end
|
426
481
|
end if annotations
|
427
482
|
retval = retval + " " if retval.length != 0
|
@@ -429,7 +484,50 @@ module JCR
|
|
429
484
|
end
|
430
485
|
|
431
486
|
def self.target_to_s( jcr )
|
432
|
-
return annotations_to_s( jcr[:annotations] ) + "
|
487
|
+
return annotations_to_s( jcr[:annotations] ) + "$" + jcr[:rule_name].to_s
|
488
|
+
end
|
489
|
+
|
490
|
+
def self.repetitions_to_s rule
|
491
|
+
retval = ""
|
492
|
+
if rule[:optional]
|
493
|
+
retval = "?"
|
494
|
+
elsif rule[:one_or_more]
|
495
|
+
retval = "+"
|
496
|
+
if rule[:repetition_step]
|
497
|
+
retval = "%" + rule[:repetition_step].to_s
|
498
|
+
end
|
499
|
+
elsif rule[:zero_or_more]
|
500
|
+
retval = "*"
|
501
|
+
retval = retval + "%" + rule[:repetition_step].to_s if rule[:repetition_step]
|
502
|
+
elsif rule[:specific_repetition] && rule[:specific_repetition].is_a?( Parslet::Slice )
|
503
|
+
retval = "*" + rule[:specific_repetition].to_s
|
504
|
+
else
|
505
|
+
if rule[:repetition_interval]
|
506
|
+
min = "0"
|
507
|
+
max = "INF"
|
508
|
+
o = rule[:repetition_min]
|
509
|
+
if o
|
510
|
+
if o.is_a?(Parslet::Slice)
|
511
|
+
min = o.to_s
|
512
|
+
end
|
513
|
+
end
|
514
|
+
o = rule[:repetition_max]
|
515
|
+
if o
|
516
|
+
if o.is_a?(Parslet::Slice)
|
517
|
+
max = o.to_s
|
518
|
+
end
|
519
|
+
end
|
520
|
+
retval = "*"+min+".."+max
|
521
|
+
end
|
522
|
+
o = rule[:repetition_step]
|
523
|
+
if o
|
524
|
+
if o.is_a?( Parslet::Slice )
|
525
|
+
retval = retval + "%" + o.to_s
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
retval = " " + retval if retval.length != 0
|
530
|
+
return retval
|
433
531
|
end
|
434
532
|
|
435
533
|
end
|
@@ -55,35 +55,35 @@ module JCR
|
|
55
55
|
when jcr[:integer_v]
|
56
56
|
si = jcr[:integer_v].to_s
|
57
57
|
if si == "integer"
|
58
|
-
return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?(
|
58
|
+
return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer )
|
59
59
|
end
|
60
60
|
when jcr[:integer]
|
61
61
|
i = jcr[:integer].to_s.to_i
|
62
62
|
return bad_value( jcr, rule_atom, i, data ) unless data == i
|
63
63
|
when jcr[:integer_min] != nil && jcr[:integer_max] == nil
|
64
|
-
return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?(
|
64
|
+
return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer )
|
65
65
|
min = jcr[:integer_min].to_s.to_i
|
66
66
|
return bad_value( jcr, rule_atom, min, data ) unless data >= min
|
67
67
|
when jcr[:integer_min] == nil && jcr[:integer_max] != nil
|
68
|
-
return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?(
|
68
|
+
return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer )
|
69
69
|
max = jcr[:integer_max].to_s.to_i
|
70
70
|
return bad_value( jcr, rule_atom, max, data ) unless data <= max
|
71
71
|
when jcr[:integer_min],jcr[:integer_max]
|
72
|
-
return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?(
|
72
|
+
return bad_value( jcr, rule_atom, "integer", data ) unless data.is_a?( Integer )
|
73
73
|
min = jcr[:integer_min].to_s.to_i
|
74
74
|
return bad_value( jcr, rule_atom, min, data ) unless data >= min
|
75
75
|
max = jcr[:integer_max].to_s.to_i
|
76
76
|
return bad_value( jcr, rule_atom, max, data ) unless data <= max
|
77
77
|
when jcr[:sized_int_v]
|
78
78
|
bits = jcr[:sized_int_v][:bits].to_i
|
79
|
-
return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?(
|
79
|
+
return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?( Integer )
|
80
80
|
min = -(2**(bits-1))
|
81
81
|
return bad_value( jcr, rule_atom, min, data ) unless data >= min
|
82
82
|
max = 2**(bits-1)-1
|
83
83
|
return bad_value( jcr, rule_atom, max, data ) unless data <= max
|
84
84
|
when jcr[:sized_uint_v]
|
85
85
|
bits = jcr[:sized_uint_v][:bits].to_i
|
86
|
-
return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?(
|
86
|
+
return bad_value( jcr, rule_atom, "int" + bits.to_s, data ) unless data.is_a?( Integer )
|
87
87
|
min = 0
|
88
88
|
return bad_value( jcr, rule_atom, min, data ) unless data >= min
|
89
89
|
max = 2**bits-1
|
@@ -470,9 +470,9 @@ module JCR
|
|
470
470
|
|
471
471
|
when rule[:uri]
|
472
472
|
if rule[:uri].is_a? Hash
|
473
|
-
retval = "
|
473
|
+
retval = "uri..#{rule[:uri][:uri_scheme].to_s}"
|
474
474
|
else
|
475
|
-
retval = "
|
475
|
+
retval = "uri"
|
476
476
|
end
|
477
477
|
|
478
478
|
when rule[:email]
|
data/lib/jcr/find_roots.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2015-
|
1
|
+
# Copyright (c) 2015-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
|
@@ -18,7 +18,7 @@ require 'jcr/evaluate_rules'
|
|
18
18
|
module JCR
|
19
19
|
|
20
20
|
class Root
|
21
|
-
attr_accessor :nameless, :name, :rule, :default
|
21
|
+
attr_accessor :nameless, :name, :rule, :default, :slice, :pos, :offset, :failures
|
22
22
|
|
23
23
|
def initialize rule, name = nil, nameless = true, default = false
|
24
24
|
@rule = rule
|
@@ -28,6 +28,9 @@ module JCR
|
|
28
28
|
@nameless = false
|
29
29
|
end
|
30
30
|
@default = default
|
31
|
+
@slice = JCR::find_first_slice( rule )
|
32
|
+
@pos = @slice.line_and_column
|
33
|
+
@offset = @slice.offset
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
@@ -52,18 +55,41 @@ module JCR
|
|
52
55
|
rn = node[:rule][:rule_name].to_str
|
53
56
|
rule = node[:rule]
|
54
57
|
ruledef = get_rule_by_type( rule )
|
55
|
-
|
58
|
+
new_root = nil
|
59
|
+
# look to see if the root_annotation is in the name before assignment ( @{root} $r = ... )
|
60
|
+
if rule[:annotations]
|
61
|
+
if rule[:annotations].is_a? Array
|
62
|
+
rule[:annotations].each do |annotation|
|
63
|
+
if annotation[:root_annotation]
|
64
|
+
new_root = Root.new(node, rn)
|
65
|
+
roots << new_root
|
66
|
+
# root is found, now look into subrule for unnamed roots
|
67
|
+
subrule = get_rule_by_type( ruledef )
|
68
|
+
roots.concat( find_roots_in_unnamed( subrule ) ) if subrule
|
69
|
+
end
|
70
|
+
end
|
71
|
+
elsif rule[:annotations][:root_annotation]
|
72
|
+
new_root = Root.new(node, rn)
|
73
|
+
roots << new_root
|
74
|
+
# root is found, now look into subrule for unnamed roots
|
75
|
+
subrule = get_rule_by_type( ruledef )
|
76
|
+
roots.concat( find_roots_in_unnamed( subrule ) ) if subrule
|
77
|
+
end
|
78
|
+
end
|
79
|
+
if ruledef && !new_root
|
56
80
|
if ruledef.is_a? Array
|
57
81
|
ruledef.each do |rdi|
|
82
|
+
# if it has a @{root} annotation in the rule definition
|
58
83
|
if rdi[:root_annotation]
|
59
|
-
roots << Root.new(
|
60
|
-
|
61
|
-
|
84
|
+
roots << Root.new(node, rn)
|
85
|
+
# else look into the definition further and examine subrules
|
86
|
+
elsif (subrule = get_rule_by_type(rdi))
|
87
|
+
roots.concat(find_roots_in_unnamed(subrule))
|
62
88
|
end
|
63
89
|
end
|
64
90
|
elsif ruledef.is_a? Hash
|
65
|
-
subrule = get_rule_by_type(
|
66
|
-
roots.concat(
|
91
|
+
subrule = get_rule_by_type(ruledef)
|
92
|
+
roots.concat(find_roots_in_unnamed(subrule)) if subrule
|
67
93
|
end
|
68
94
|
end
|
69
95
|
return roots
|
data/lib/jcr/jcr.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2015-
|
1
|
+
# Copyright (c) 2015-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
|
@@ -28,7 +28,7 @@ require 'jcr/version'
|
|
28
28
|
module JCR
|
29
29
|
|
30
30
|
class Context
|
31
|
-
attr_accessor :mapping, :callbacks, :id, :tree, :roots, :catalog, :trace
|
31
|
+
attr_accessor :mapping, :callbacks, :id, :tree, :roots, :catalog, :trace, :failed_roots, :failure_report
|
32
32
|
|
33
33
|
def add_ruleset_alias( ruleset_alias, alias_uri )
|
34
34
|
unless @catalog
|
@@ -60,6 +60,7 @@ module JCR
|
|
60
60
|
|
61
61
|
def initialize( ruleset = nil, trace = false )
|
62
62
|
@trace = trace
|
63
|
+
@failed_roots = []
|
63
64
|
if ruleset
|
64
65
|
ingested = JCR.ingest_ruleset( ruleset, false, nil )
|
65
66
|
@mapping = ingested.mapping
|
@@ -109,30 +110,56 @@ module JCR
|
|
109
110
|
end
|
110
111
|
|
111
112
|
def self.evaluate_ruleset( data, ctx, root_name = nil )
|
112
|
-
|
113
|
+
roots = []
|
113
114
|
if root_name
|
114
115
|
root_rule = ctx.mapping[root_name]
|
115
116
|
raise "No rule by the name of #{root_name} for a root rule has been found" unless root_rule
|
116
|
-
|
117
|
+
root = JCR::Root.new( root_rule, root_name )
|
118
|
+
roots << root
|
117
119
|
else
|
118
|
-
ctx.roots
|
119
|
-
root_rules << r.rule
|
120
|
-
end
|
120
|
+
roots = ctx.roots
|
121
121
|
end
|
122
122
|
|
123
|
-
raise "No root rule defined. Specify a root rule name" if
|
123
|
+
raise "No root rule defined. Specify a root rule name" if roots.empty?
|
124
124
|
|
125
125
|
retval = nil
|
126
|
-
|
127
|
-
pp "Evaluating Root:", rule_to_s( r, false ) if ctx.trace
|
128
|
-
raise "Root rules cannot be member rules" if r[:member_rule]
|
129
|
-
|
126
|
+
roots.each do |r|
|
127
|
+
pp "Evaluating Root:", rule_to_s( r.rule, false ) if ctx.trace
|
128
|
+
raise "Root rules cannot be member rules" if r.rule[:member_rule]
|
129
|
+
econs = EvalConditions.new( ctx.mapping, ctx.callbacks, ctx.trace )
|
130
|
+
retval = JCR.evaluate_rule( r.rule, r.rule, data, econs )
|
130
131
|
break if retval.success
|
132
|
+
# else
|
133
|
+
r.failures = econs.failures
|
134
|
+
ctx.failed_roots << r
|
131
135
|
end
|
132
136
|
|
137
|
+
ctx.failure_report = failure_report( ctx )
|
133
138
|
return retval
|
134
139
|
end
|
135
140
|
|
141
|
+
def self.failure_report ctx
|
142
|
+
report = []
|
143
|
+
ctx.failed_roots.each do |failed_root|
|
144
|
+
if failed_root.name
|
145
|
+
report << "- ** Failures for root rule named '#{failed_root.name}'"
|
146
|
+
else
|
147
|
+
report << "- ** Failures for root rule at line #{failed_root.pos[0]}"
|
148
|
+
end
|
149
|
+
failed_root.failures.sort.map do |stack_level, failures|
|
150
|
+
if failures.length > 1
|
151
|
+
report << " - failure at rule depth #{stack_level} caused by one of the following #{failures.length} reasons"
|
152
|
+
else
|
153
|
+
report << " - failure at rule depth #{stack_level} caused by"
|
154
|
+
end
|
155
|
+
failures.each_with_index do |failure, index|
|
156
|
+
report << " - #{failure.json_elided} failed rule #{failure.definition} at #{failure.pos} because #{failure.reason_elided}"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
return report
|
161
|
+
end
|
162
|
+
|
136
163
|
def self.main my_argv=nil
|
137
164
|
|
138
165
|
my_argv = ARGV unless my_argv
|
@@ -205,6 +232,10 @@ module JCR
|
|
205
232
|
options[:verbose] = true
|
206
233
|
end
|
207
234
|
|
235
|
+
opt.on("-q","quiet") do |quiet|
|
236
|
+
options[:quiet] = true
|
237
|
+
end
|
238
|
+
|
208
239
|
opt.on("-h","display help") do |help|
|
209
240
|
options[:help] = true
|
210
241
|
end
|
@@ -243,7 +274,7 @@ module JCR
|
|
243
274
|
|
244
275
|
if options[:verbose]
|
245
276
|
pp "Ruleset Parse Tree", ctx.tree
|
246
|
-
|
277
|
+
puts "Ruleset Map"
|
247
278
|
ctx.mapping.each do |name,rule|
|
248
279
|
puts "Parsed Rule: #{name}"
|
249
280
|
puts rule_to_s( rule, false )
|
@@ -258,7 +289,7 @@ module JCR
|
|
258
289
|
return 0
|
259
290
|
elsif options[:json]
|
260
291
|
data = JSON.parse( options[:json] )
|
261
|
-
ec = cli_eval( ctx, data, options[:root_name], options[:
|
292
|
+
ec = cli_eval( ctx, data, options[:root_name], options[:quiet] )
|
262
293
|
return ec
|
263
294
|
elsif $stdin.tty?
|
264
295
|
ec = 0
|
@@ -267,35 +298,55 @@ module JCR
|
|
267
298
|
else
|
268
299
|
my_argv.each do |fn|
|
269
300
|
data = JSON.parse( File.open( fn ).read )
|
270
|
-
tec = cli_eval( ctx, data, options[:root_name], options[:
|
301
|
+
tec = cli_eval( ctx, data, options[:root_name], options[:quiet] )
|
271
302
|
ec = tec if tec != 0 #record error but don't let non-error overwrite error
|
272
303
|
end
|
273
304
|
end
|
274
305
|
return ec
|
275
306
|
else
|
276
|
-
|
277
|
-
ec =
|
307
|
+
lines = ""
|
308
|
+
ec = 0
|
309
|
+
ARGF.each do |line|
|
310
|
+
lines = lines + line
|
311
|
+
if ARGF.eof?
|
312
|
+
data = JSON.parse( lines )
|
313
|
+
tec = cli_eval( ctx, data, options[:root_name], options[:quiet] )
|
314
|
+
ec = tec if tec != 0 #record error but don't let non-error overwrite error
|
315
|
+
lines = ""
|
316
|
+
end
|
317
|
+
end
|
278
318
|
return ec
|
279
319
|
end
|
280
320
|
|
281
321
|
rescue Parslet::ParseFailed => failure
|
282
|
-
puts failure.
|
322
|
+
puts failure.parse_failure_cause.ascii_tree unless options[:quiet]
|
323
|
+
return 1
|
324
|
+
rescue JSON::ParserError => parser_error
|
325
|
+
unless options[:quiet]
|
326
|
+
puts "Unable to parse JSON"
|
327
|
+
puts parser_error.message.inspect
|
328
|
+
end
|
329
|
+
return 3
|
283
330
|
end
|
331
|
+
|
284
332
|
end
|
285
333
|
|
286
334
|
end
|
287
335
|
|
288
|
-
def self.cli_eval ctx, data, root_name,
|
336
|
+
def self.cli_eval ctx, data, root_name, quiet
|
289
337
|
ec = 2
|
290
338
|
e = ctx.evaluate( data, root_name )
|
291
339
|
if e.success
|
292
|
-
|
340
|
+
unless quiet
|
293
341
|
puts "Success!"
|
294
342
|
end
|
295
343
|
ec = 0
|
296
344
|
else
|
297
|
-
|
298
|
-
puts "Failure
|
345
|
+
unless quiet
|
346
|
+
puts "Failure! Use -v for more information."
|
347
|
+
ctx.failure_report.each do |line|
|
348
|
+
puts line
|
349
|
+
end
|
299
350
|
end
|
300
351
|
ec = 3
|
301
352
|
end
|
data/lib/jcr/parser.rb
CHANGED
@@ -72,8 +72,12 @@ module JCR
|
|
72
72
|
#> jcr-version-kw = "jcr-version"
|
73
73
|
#! major_version = non_neg_integer
|
74
74
|
#! minor_version = non_neg_integer
|
75
|
-
rule(:extension_id) {
|
76
|
-
#! extension_id =
|
75
|
+
rule(:extension_id) { id }
|
76
|
+
#! extension_id = id
|
77
|
+
rule(:id) { match('[a-zA-Z]') >> id_tail.repeat }
|
78
|
+
#! id = ALPHA *id-tail
|
79
|
+
rule(:id_tail) { match('[^\s}]') }
|
80
|
+
#! id-tail = %x21-7C / %x7E-10FFFF ; not spaces, not }
|
77
81
|
rule(:ruleset_id_d) { (str('ruleset-id') >> dsps >> ruleset_id.as(:ruleset_id)).as(:ruleset_id_d) }
|
78
82
|
#! ruleset_id_d = ruleset-id-kw DSPs ruleset_id
|
79
83
|
#> ruleset-id-kw = "ruleset-id"
|
@@ -82,9 +86,8 @@ module JCR
|
|
82
86
|
#! [ DSPs as_kw DSPs ruleset_id_alias ]
|
83
87
|
#> import-kw = "import"
|
84
88
|
#> as-kw = "as"
|
85
|
-
rule(:ruleset_id) {
|
86
|
-
#! ruleset_id =
|
87
|
-
#! not-space = %x21-10FFFF
|
89
|
+
rule(:ruleset_id) { id }
|
90
|
+
#! ruleset_id = id
|
88
91
|
rule(:ruleset_id_alias) { name.as(:ruleset_id_alias) }
|
89
92
|
#! ruleset_id_alias = name
|
90
93
|
rule(:one_line_tbd_directive_d) { name.as(:directive_name) >> ( wsp >> match('[^\r\n]').repeat.as(:directive_parameters) ).maybe }
|
@@ -309,41 +312,41 @@ module JCR
|
|
309
312
|
str('{') >> spcCmnt? >> object_items.maybe >> spcCmnt? >> str('}') ).as(:object_rule) }
|
310
313
|
#! object_rule = annotations "{" spcCmnt?
|
311
314
|
#! [ object_items spcCmnt? ] "}"
|
312
|
-
rule(:object_items) { object_item >> ((
|
313
|
-
(
|
314
|
-
#! object_items = object_item
|
315
|
-
#! *( choice_combiner object_item )
|
316
|
-
rule(:object_item ) { object_item_types >> spcCmnt? >> repetition.maybe }
|
317
|
-
#! object_item = object_item_types spcCmnt? [ repetition ]
|
315
|
+
rule(:object_items) { object_item >> (( sequence_combiner >> object_item ).repeat(1) |
|
316
|
+
( choice_combiner >> object_item ).repeat(1) ).maybe }
|
317
|
+
#! object_items = object_item [ 1*( sequence_combiner object_item ) /
|
318
|
+
#! 1*( choice_combiner object_item ) ]
|
319
|
+
rule(:object_item ) { object_item_types >> spcCmnt? >> ( repetition >> spcCmnt? ).maybe }
|
320
|
+
#! object_item = object_item_types spcCmnt? [ repetition spcCmnt? ]
|
318
321
|
rule(:object_item_types) { object_group | member_rule | target_rule_name }
|
319
322
|
#! object_item_types = object_group / member_rule / target_rule_name
|
320
|
-
rule(:object_group) { ( str('(') >> spcCmnt? >> object_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
|
321
|
-
#! object_group = "(" spcCmnt? [ object_items spcCmnt? ] ")"
|
323
|
+
rule(:object_group) { ( annotations >> str('(') >> spcCmnt? >> object_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
|
324
|
+
#! object_group = annotations "(" spcCmnt? [ object_items spcCmnt? ] ")"
|
322
325
|
#!
|
323
326
|
|
324
327
|
rule(:array_rule) { ( annotations >>
|
325
328
|
str('[') >> spcCmnt? >> array_items.maybe >> spcCmnt? >> str(']') ).as(:array_rule) }
|
326
329
|
#! array_rule = annotations "[" spcCmnt? [ array_items spcCmnt? ] "]"
|
327
|
-
rule(:array_items) { array_item >> ((
|
328
|
-
(
|
329
|
-
#! array_items = array_item
|
330
|
-
#! *( choice_combiner array_item )
|
331
|
-
rule(:array_item) { array_item_types >> spcCmnt? >> repetition.maybe }
|
332
|
-
#! array_item = array_item_types spcCmnt? [ repetition ]
|
330
|
+
rule(:array_items) { array_item >> (( sequence_combiner >> array_item ).repeat(1) |
|
331
|
+
( choice_combiner >> array_item ).repeat(1) ).maybe }
|
332
|
+
#! array_items = array_item [ 1*( sequence_combiner array_item ) /
|
333
|
+
#! 1*( choice_combiner array_item ) ]
|
334
|
+
rule(:array_item) { array_item_types >> spcCmnt? >> ( repetition >> spcCmnt? ).maybe }
|
335
|
+
#! array_item = array_item_types spcCmnt? [ repetition spcCmnt? ]
|
333
336
|
rule(:array_item_types) { array_group | type_rule | explicit_type_choice }
|
334
337
|
#! array_item_types = array_group / type_rule / explicit_type_choice
|
335
|
-
rule(:array_group) { ( str('(') >> spcCmnt? >> array_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
|
336
|
-
#! array_group = "(" spcCmnt? [ array_items spcCmnt? ] ")"
|
338
|
+
rule(:array_group) { ( annotations >> str('(') >> spcCmnt? >> array_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
|
339
|
+
#! array_group = annotations "(" spcCmnt? [ array_items spcCmnt? ] ")"
|
337
340
|
#!
|
338
341
|
|
339
342
|
rule(:group_rule) { ( annotations >> str('(') >> spcCmnt? >> group_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
|
340
343
|
#! group_rule = annotations "(" spcCmnt? [ group_items spcCmnt? ] ")"
|
341
|
-
rule(:group_items) { group_item >> ((
|
342
|
-
(
|
343
|
-
#! group_items = group_item
|
344
|
-
#! *( choice_combiner group_item )
|
345
|
-
rule(:group_item) { group_item_types >> spcCmnt? >> repetition.maybe }
|
346
|
-
#! group_item = group_item_types spcCmnt? [ repetition ]
|
344
|
+
rule(:group_items) { group_item >> (( sequence_combiner >> group_item ).repeat(1) |
|
345
|
+
( choice_combiner >> group_item ).repeat(1) ).maybe }
|
346
|
+
#! group_items = group_item [ 1*( sequence_combiner group_item ) /
|
347
|
+
#! 1*( choice_combiner group_item ) ]
|
348
|
+
rule(:group_item) { group_item_types >> spcCmnt? >> ( repetition >> spcCmnt? ).maybe }
|
349
|
+
#! group_item = group_item_types spcCmnt? [ repetition spcCmnt? ]
|
347
350
|
rule(:group_item_types) { group_group | member_rule | type_rule | explicit_type_choice }
|
348
351
|
#! group_item_types = group_group / member_rule /
|
349
352
|
#! type_rule / explicit_type_choice
|
@@ -351,10 +354,10 @@ module JCR
|
|
351
354
|
#! group_group = group_rule
|
352
355
|
#!
|
353
356
|
|
354
|
-
rule(:sequence_combiner) { str(',').as(:sequence_combiner) }
|
355
|
-
#! sequence_combiner =
|
356
|
-
rule(:choice_combiner) { str('|').as(:choice_combiner) }
|
357
|
-
#! choice_combiner =
|
357
|
+
rule(:sequence_combiner) { str(',').as(:sequence_combiner) >> spcCmnt? }
|
358
|
+
#! sequence_combiner = "," spcCmnt?
|
359
|
+
rule(:choice_combiner) { str('|').as(:choice_combiner) >> spcCmnt? }
|
360
|
+
#! choice_combiner = "|" spcCmnt?
|
358
361
|
#!
|
359
362
|
|
360
363
|
rule(:repetition) { optional | one_or_more |
|
data/lib/jcr/version.rb
CHANGED
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.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Newton
|
@@ -9,20 +9,20 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2017-12-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parslet
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - ~>
|
18
|
+
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '1.7'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- - ~>
|
25
|
+
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '1.7'
|
28
28
|
- !ruby/object:Gem::Dependency
|
@@ -43,14 +43,14 @@ dependencies:
|
|
43
43
|
name: email_address_validator
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - ~>
|
46
|
+
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '2.0'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - ~>
|
53
|
+
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '2.0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
@@ -100,19 +100,18 @@ require_paths:
|
|
100
100
|
- lib
|
101
101
|
required_ruby_version: !ruby/object:Gem::Requirement
|
102
102
|
requirements:
|
103
|
-
- -
|
103
|
+
- - ">="
|
104
104
|
- !ruby/object:Gem::Version
|
105
105
|
version: '0'
|
106
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
requirements: []
|
112
112
|
rubyforge_project:
|
113
|
-
rubygems_version: 2.
|
113
|
+
rubygems_version: 2.5.2
|
114
114
|
signing_key:
|
115
115
|
specification_version: 4
|
116
116
|
summary: JCR Validator
|
117
117
|
test_files: []
|
118
|
-
has_rdoc:
|