jcrvalidator 0.6.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e68e95dd86cf0ba170eae8a3ead3acb7c44ab59
4
- data.tar.gz: fe3a8c25bf2e420c43db8c32f33e764f7356d766
3
+ metadata.gz: a0b80dde864c20a32ff286e29e11b5179b3fa935
4
+ data.tar.gz: 8670787681c6b2aa7639f5c1fad552f5843f2d88
5
5
  SHA512:
6
- metadata.gz: 6d8a19a053ff78eeb76b2b46ee0c48be126465a80825737e87881cbdf4c9f7e4e1b9dae9c15b0768ddb27f091f4196e761f44ab2c65cc19a19a86288bbdb8d51
7
- data.tar.gz: ba031e433185f9857056a62759caee2d7edf396cc6067d35e1bd4d3114c9dc9b27985f0bc0a299bd2128095739f0b48724afdda750e14dad575040cdb78a7a0e
6
+ metadata.gz: 3f3da7c4224cfe32ea94f0681a8bbc39b32dd095056ebdf94ae0cc8f55b5332b212fca7b07800b992e3c6357e01876bff05b3b282f45d914194ac4e3a0788708
7
+ data.tar.gz: 5cd168ff7ea72fd9671d337c4cd0830fd38e4bac75480bb4d65d7e22252186b6edf2e24576f469705483cb1dbcde127c2187c8e4c2a08c609aa5f7865f861647
@@ -14,6 +14,7 @@
14
14
 
15
15
  require 'jcr/parser'
16
16
  require 'jcr/map_rule_names'
17
+ require 'pp'
17
18
 
18
19
  module JCR
19
20
 
@@ -69,6 +70,9 @@ module JCR
69
70
  end
70
71
 
71
72
  def self.check_member_for_group node, mapping
73
+ if node.is_a? Array
74
+ node = node[0]
75
+ end
72
76
  if node[:target_rule_name]
73
77
  trule = get_name_mapping( node[:target_rule_name][:rule_name], mapping )
74
78
  disallowed_group_in_member?( trule, mapping )
@@ -51,7 +51,7 @@ module JCR
51
51
  trace( econs, "Evaluating array rule starting at #{slice_to_s(jcr)} against", data )
52
52
  trace_def( econs, "array", jcr, data )
53
53
  retval = evaluate_array( jcr, rule_atom, data, econs, behavior )
54
- trace_eval( econs, "Array", retval )
54
+ trace_eval( econs, "Array", retval, jcr, data, "array" )
55
55
  pop_trace_stack( econs )
56
56
  return retval
57
57
 
@@ -32,7 +32,7 @@ module JCR
32
32
  trace( econs, "Evaluating group rule against ", data )
33
33
  trace_def( econs, "group", jcr, data )
34
34
  retval = evaluate_group( jcr, rule_atom, data, econs, behavior )
35
- trace_eval( econs, "Group", retval )
35
+ trace_eval( econs, "Group", retval, jcr, data, "group" )
36
36
  pop_trace_stack( econs )
37
37
  return retval
38
38
 
@@ -31,7 +31,7 @@ module 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
33
  retval = evaluate_member( jcr, rule_atom, data, econs )
34
- trace_eval( econs, "Member", retval )
34
+ trace_eval( econs, "Member", retval, jcr, data, "member" )
35
35
  pop_trace_stack( econs )
36
36
  return retval
37
37
 
@@ -45,7 +45,7 @@ module JCR
45
45
 
46
46
 
47
47
  rules, annotations = get_rules_and_annotations( jcr )
48
- rule = rules[0]
48
+ rule = merge_rules( rules )
49
49
 
50
50
  member_match = false
51
51
 
@@ -55,7 +55,13 @@ module JCR
55
55
  member_match = true
56
56
  end
57
57
  else # must be regex
58
- match_spec = Regexp.new( rule[:member_regex][:regex].to_s )
58
+ regex = rule[:member_regex][:regex]
59
+ if regex.is_a? Array
60
+ match_spec = Regexp.new( "" )
61
+ trace( econs, "Noting empty regular expression." )
62
+ else
63
+ match_spec = Regexp.new( rule[:member_regex][:regex].to_s )
64
+ end
59
65
  if match_spec =~ data[ 0 ]
60
66
  member_match = true
61
67
  end
@@ -63,6 +69,7 @@ module JCR
63
69
 
64
70
  if member_match
65
71
  e = evaluate_rule( rule, rule_atom, data[ 1 ], econs )
72
+ e.member_found = true
66
73
  return evaluate_not( annotations, e, econs )
67
74
  end
68
75
 
@@ -74,7 +81,7 @@ module JCR
74
81
  def self.member_to_s( jcr, shallow=true )
75
82
  rules, annotations = get_rules_and_annotations( jcr )
76
83
  retval = ""
77
- rule = rules[ 0 ]
84
+ rule = merge_rules( rules )
78
85
  case
79
86
  when rule[:member_name]
80
87
  retval = %Q|"#{rule[:member_name][:q_string].to_s}"|
@@ -33,7 +33,7 @@ module JCR
33
33
  trace( econs, "Evaluating object rule starting at #{slice_to_s(jcr)} against", data )
34
34
  trace_def( econs, "object", jcr, data )
35
35
  retval = evaluate_object( jcr, rule_atom, data, econs, behavior )
36
- trace_eval( econs, "Object", retval )
36
+ trace_eval( econs, "Object", retval, jcr, data, "object" )
37
37
  pop_trace_stack( econs )
38
38
  return retval
39
39
 
@@ -124,22 +124,32 @@ module JCR
124
124
  end
125
125
  else
126
126
  trace( econs, "No member '#{k}' found in object.")
127
+ e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil)
128
+ repeat_results[ nil ] = nil if e.success
127
129
  end
128
130
 
129
131
  else
130
132
 
131
- trace( econs, "Scanning object.")
133
+ regex = lrules[0][:member_regex][:regex]
134
+ trace( econs, "Scanning object for #{regex}.")
132
135
  i = 0
136
+ found = false
133
137
  repeat_results = data.select do |k,v|
134
138
  unless behavior.checked_hash[k]
135
139
  if i < repeat_max
136
140
  e = evaluate_rule(rule, rule_atom, [k, v], econs, nil)
137
141
  behavior.checked_hash[k] = e.success
138
142
  i = i + 1 if e.success
143
+ found = true if e.member_found
139
144
  e.success
140
145
  end
141
146
  end
142
147
  end
148
+ unless found
149
+ trace( econs, "No member matching #{regex} found in object.")
150
+ e = evaluate_rule(rule, rule_atom, [nil, nil], econs, nil)
151
+ repeat_results[ nil ] = nil if e.success
152
+ end
143
153
 
144
154
  end
145
155
 
@@ -19,6 +19,7 @@ require 'addressable/uri'
19
19
  require 'addressable/template'
20
20
  require 'email_address_validator'
21
21
  require 'big-phoney'
22
+ require 'json'
22
23
 
23
24
  require 'jcr/parser'
24
25
  require 'jcr/map_rule_names'
@@ -45,7 +46,7 @@ end
45
46
  module JCR
46
47
 
47
48
  class Evaluation
48
- attr_accessor :success, :reason, :child_evaluation
49
+ attr_accessor :success, :reason, :member_found
49
50
  def initialize success, reason
50
51
  @success = success
51
52
  @reason = reason
@@ -53,8 +54,9 @@ module JCR
53
54
  end
54
55
 
55
56
  class EvalConditions
56
- attr_accessor :mapping, :callbacks, :trace, :trace_stack
57
+ attr_accessor :mapping, :callbacks, :trace, :trace_stack, :first_failure
57
58
  def initialize mapping, callbacks, trace = false
59
+ @first_failure = nil
58
60
  @mapping = mapping
59
61
  @trace = trace
60
62
  @trace_stack = []
@@ -207,6 +209,16 @@ module JCR
207
209
  return rules, annotations
208
210
  end
209
211
 
212
+ def self.merge_rules rules
213
+ new_rule = Hash.new
214
+ rules.each do |rule|
215
+ new_rule.merge!(rule) do |key,oldval,newval|
216
+ raise "error: conflict in merge of #{rule} with #{new_rule}"
217
+ end
218
+ end
219
+ return new_rule
220
+ end
221
+
210
222
  def self.evaluate_not annotations, evaluation, econs
211
223
  is_not = false
212
224
  annotations.each do |a|
@@ -296,15 +308,27 @@ module JCR
296
308
  else
297
309
  s = "** unknown rule **"
298
310
  end
299
- trace( econs, "#{type}: #{s}", data)
311
+ trace( econs, "#{type} definition: #{s}", data)
300
312
  end
301
313
  end
302
314
 
303
- def self.trace_eval econs, message, evaluation
315
+ def self.trace_eval econs, message, evaluation, jcr, data, type
304
316
  if evaluation.success
305
317
  trace( econs, "#{message} evaluation is true" )
306
318
  else
307
319
  trace( econs, "#{message} evaluation failed: #{evaluation.reason}")
320
+ unless econs.first_failure
321
+ econs.first_failure = evaluation
322
+ trace( econs, "** LIKELY ROOT CAUSE FOR FAILURE **" )
323
+ trace( econs, "***********************************" )
324
+ rule = find_first_slice( jcr )
325
+ pos = "Failed rule at line,column: #{rule.line_and_column} file position offset: #{rule.offset}"
326
+ trace( econs, pos )
327
+ trace_def( econs, type, jcr, data )
328
+ data_s = "JSON that failed to validate: #{data.to_json}"
329
+ trace( econs, data_s )
330
+ trace( econs, "***********************************" )
331
+ end
308
332
  end
309
333
  end
310
334
 
@@ -363,7 +387,7 @@ module JCR
363
387
  elsif rule[:rule]
364
388
  retval = rule_to_s( rule[:rule], shallow )
365
389
  else
366
- retval = "** unknown rule definition **"
390
+ retval = "** unknown rule definition ** #{rule}"
367
391
  end
368
392
  return retval
369
393
  end
@@ -33,7 +33,7 @@ module JCR
33
33
  rules, annotations = get_rules_and_annotations( jcr )
34
34
 
35
35
  retval = evaluate_not( annotations, evaluate_values( rules[0], rule_atom, data, econs ), econs )
36
- trace_eval( econs, "Value", retval)
36
+ trace_eval( econs, "Value", retval, jcr, data, "value")
37
37
  pop_trace_stack( econs )
38
38
  return retval
39
39
  end
@@ -219,25 +219,17 @@ module JCR
219
219
  end
220
220
 
221
221
  #
222
- # uri and uri templates
222
+ # uri and uri scheme
223
223
  #
224
224
 
225
225
  when jcr[:uri]
226
226
  return bad_value( jcr, rule_atom, "URI", data ) unless data.is_a?( String )
227
227
  uri = Addressable::URI.parse( data )
228
228
  return bad_value( jcr, rule_atom, "URI", data ) unless uri.is_a?( Addressable::URI )
229
- when jcr[:uri_template]
230
- t = jcr[:uri_template].to_s
229
+ when jcr[:uri_scheme]
230
+ t = jcr[:uri_scheme].to_s
231
231
  return bad_value( jcr, rule_atom, t, data ) unless data.is_a? String
232
- template = Addressable::Template.new( t )
233
- e = template.extract( data )
234
- if e == nil
235
- return bad_value( jcr, rule_atom, t, data )
236
- else
237
- e.each do |k,v|
238
- return bad_value( jcr, rule_atom, t, data ) unless v
239
- end
240
- end
232
+ return bad_value( jcr, rule_atom, t, data ) unless data.start_with?( t )
241
233
 
242
234
  #
243
235
  # phone and email value rules
@@ -476,8 +468,8 @@ module JCR
476
468
 
477
469
  when rule[:uri]
478
470
  retval = "URI"
479
- when rule[:uri_template]
480
- retval = "URI template #{rule[:uri_template].to_s}"
471
+ when rule[:uri_scheme]
472
+ retval = "URI with specific scheme #{rule[:uri_scheme].to_s}"
481
473
 
482
474
  when rule[:email]
483
475
  retval = "email"
data/lib/jcr/jcr.rb CHANGED
@@ -207,6 +207,13 @@ module JCR
207
207
  opt.on("-h","display help") do |help|
208
208
  options[:help] = true
209
209
  end
210
+
211
+ opt.separator ""
212
+ opt.separator "Return codes:"
213
+ opt.separator " 0 = success"
214
+ opt.separator " 1 = parsing or other bad condition"
215
+ opt.separator " 2 = fall through bad condition"
216
+ opt.separator " 3 = unsuccessful evaluation of JSON"
210
217
  end
211
218
 
212
219
  opt_parser.parse! my_argv
@@ -286,7 +293,7 @@ module JCR
286
293
  if verbose
287
294
  puts "Failure: #{e.reason}"
288
295
  end
289
- ec = 1
296
+ ec = 3
290
297
  end
291
298
  return ec
292
299
  end
data/lib/jcr/parser.rb CHANGED
@@ -36,34 +36,46 @@ module JCR
36
36
  #/ spaces? -> [ spaces ]
37
37
  rule(:wsp) { match('[\t ]') }
38
38
  # WSP is a standard ABNF production so is not expanded here
39
- rule(:comment) { str(';') >> ( str('\;') | match('[^\r\n;]') ).repeat >> match('[\r\n;]') }
40
- #! comment = ";" *( "\;" / comment-char ) comment-end-char
41
- #! comment-char = HTAB / %x20-3A / %x3C-10FFFF
42
- #! ; Any char other than ";" / CR / LF
43
- #! comment-end-char = CR / LF / ";"
39
+ rule(:dsps) { spcCmnt.repeat(1) | wsp.repeat(1) }
40
+ #! DSPs = ; Directive spaces
41
+ #! 1*WSP / ; When in one-line directive
42
+ #! 1*spcCmnt ; When in muti-line directive
43
+ rule(:dsps?) { dsps.maybe }
44
+ #/ DSPs? -> [ DSPs ]
45
+ rule(:comment) { str(';') >> match('[^\r\n]').repeat >> match('[\r\n]') }
46
+ #! comment = ";" *comment-char comment-end-char
47
+ #! comment-char = HTAB / %x20-10FFFF
48
+ #! ; Any char other than CR / LF
49
+ #! comment-end-char = CR / LF
44
50
  #!
45
51
 
46
52
  rule(:directive) { ( str('#') >> (one_line_directive | multi_line_directive) ).as(:directive) }
47
53
  #! directive = "#" (one_line_directive / multi_line_directive)
48
- rule(:one_line_directive) { ( spaces? >> ( directive_def | one_line_tbd_directive_d ) >> wsp.repeat >> match('[\r\n]') ) }
49
- #! one_line_directive = spaces?
54
+ rule(:one_line_directive) { ( dsps? >> ( directive_def | one_line_tbd_directive_d ) >> wsp.repeat >> match('[\r\n]') ) }
55
+ #! one_line_directive = DSPs?
50
56
  #! (directive_def / one_line_tbd_directive_d) *WSP eol
51
57
  rule(:multi_line_directive) { str('{') >> spcCmnt? >> (directive_def | multi_line_tbd_directive_d) >> spcCmnt? >> str('}') }
52
58
  #! multi_line_directive = "{" spcCmnt?
53
59
  #! (directive_def / multi_line_tbd_directive_d) spcCmnt? "}"
54
60
  rule(:directive_def) { jcr_version_d | ruleset_id_d | import_d }
55
61
  #! directive_def = jcr_version_d / ruleset_id_d / import_d
56
- rule(:jcr_version_d) { (str('jcr-version') >> spaces >> non_neg_integer.as(:major_version) >> str('.') >> non_neg_integer.as(:minor_version)).as(:jcr_version_d) }
57
- #! jcr_version_d = jcr-version-kw spaces major_version "." minor_version
62
+ rule(:jcr_version_d) { ( str('jcr-version') >> dsps >>
63
+ non_neg_integer.as(:major_version) >> str('.') >> non_neg_integer.as(:minor_version) >>
64
+ ( dsps >> str('+') >> dsps? >> extension_id ).repeat
65
+ ).as(:jcr_version_d) }
66
+ #! jcr_version_d = jcr-version-kw DSPs major_version "." minor_version
67
+ #! *( DSPs "+" DSPs? extension_id )
58
68
  #> jcr-version-kw = "jcr-version"
59
69
  #! major_version = non_neg_integer
60
70
  #! minor_version = non_neg_integer
61
- rule(:ruleset_id_d) { (str('ruleset-id') >> spaces >> ruleset_id.as(:ruleset_id)).as(:ruleset_id_d) }
62
- #! ruleset_id_d = ruleset-id-kw spaces ruleset_id
71
+ rule(:extension_id) { match('[a-zA-Z]') >> match('[\S]').repeat }
72
+ #! extension_id = ALPHA *not-space
73
+ rule(:ruleset_id_d) { (str('ruleset-id') >> dsps >> ruleset_id.as(:ruleset_id)).as(:ruleset_id_d) }
74
+ #! ruleset_id_d = ruleset-id-kw DSPs ruleset_id
63
75
  #> ruleset-id-kw = "ruleset-id"
64
- rule(:import_d) { (str('import') >> spaces >> ruleset_id.as(:ruleset_id) >> ( spaces >> str('as') >> spaces >> ruleset_id_alias ).maybe).as(:import_d) }
65
- #! import_d = import-kw spaces ruleset_id
66
- #! [ spaces as_kw spaces ruleset_id_alias ]
76
+ rule(:import_d) { (str('import') >> dsps >> ruleset_id.as(:ruleset_id) >> ( dsps >> str('as') >> dsps >> ruleset_id_alias ).maybe).as(:import_d) }
77
+ #! import_d = import-kw DSPs ruleset_id
78
+ #! [ DSPs as_kw DSPs ruleset_id_alias ]
67
79
  #> import-kw = "import"
68
80
  #> as-kw = "as"
69
81
  rule(:ruleset_id) { match('[a-zA-Z]') >> match('[\S]').repeat }
@@ -77,9 +89,9 @@ module JCR
77
89
  #! one_line_directive_parameters = *not_eol
78
90
  #! not_eol = HTAB / %x20-10FFFF
79
91
  #! eol = CR / LF
80
- rule(:multi_line_tbd_directive_d) { name.as(:directive_name) >> ( spaces >> multi_line_directive_parameters.as(:directive_parameters) ).maybe }
92
+ rule(:multi_line_tbd_directive_d) { name.as(:directive_name) >> ( spcCmnt.repeat(1) >> multi_line_directive_parameters.as(:directive_parameters) ).maybe }
81
93
  #! multi_line_tbd_directive_d = directive_name
82
- #! [ spaces multi_line_directive_parameters ]
94
+ #! [ 1*spcCmnt multi_line_directive_parameters ]
83
95
  rule(:multi_line_directive_parameters) { multi_line_parameters }
84
96
  #! multi_line_directive_parameters = multi_line_parameters
85
97
  rule(:multi_line_parameters) { (comment | q_string | regex | match('[^"/;}]')).repeat }
@@ -243,8 +255,8 @@ module JCR
243
255
  rule(:idn_type) { str('idn').as(:idn) }
244
256
  #! idn_type = idn-kw
245
257
  #> idn-kw = "idn"
246
- rule(:uri_range) { str('uri..') >> uri_template }
247
- #! uri_range = uri-dotdot-kw uri_template
258
+ rule(:uri_range) { str('uri..') >> uri_scheme }
259
+ #! uri_range = uri-dotdot-kw uri_scheme
248
260
  #> uri-dotdot-kw = "uri.."
249
261
  rule(:uri_type) { str('uri').as(:uri) }
250
262
  #! uri_type = uri-kw
@@ -414,8 +426,8 @@ module JCR
414
426
  #! regex_modifiers = *( "i" / "s" / "x" )
415
427
  #!
416
428
 
417
- rule(:uri_template) { ( match('[a-zA-Z{}]').repeat(1) >> str(':') >> match('[\S]').repeat(1) ).as(:uri_template) }
418
- #! uri_template = 1*ALPHA ":" 1*not-space
429
+ rule(:uri_scheme) { ( match('[a-zA-Z]').repeat(1) ).as(:uri_scheme) }
430
+ #! uri_scheme = 1*ALPHA
419
431
 
420
432
  end
421
433
 
@@ -52,10 +52,10 @@ module JCR
52
52
  major = directive[:major_version].to_str.to_i
53
53
  minor = directive[:minor_version].to_str.to_i
54
54
  if major != 0
55
- raise "jcr version #{major}.#{minor} is incompatible with 0.5"
55
+ raise "jcr version #{major}.#{minor} is incompatible with 0.7"
56
56
  end
57
- if minor != 5
58
- raise "jcr version #{major}.#{minor} is incompatible with 0.5"
57
+ if minor != 7
58
+ raise "jcr version #{major}.#{minor} is incompatible with 0.7"
59
59
  end
60
60
  end
61
61
 
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.6.0
4
+ version: 0.6.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: 2016-07-16 00:00:00.000000000 Z
12
+ date: 2016-07-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parslet