schema-validator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +42 -0
  4. data/bin/schema-validator +82 -0
  5. data/lib/rx/ruby/Rx.rb +658 -0
  6. metadata +49 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 35da5c079158aa63d96d214b3ae9178236ffeba8
4
+ data.tar.gz: 5deffeb8218a0c223536dce3214362b41c668ed5
5
+ SHA512:
6
+ metadata.gz: 6605965706c35485ffb5da9774151e68a4d7616eba9cd100da244f8f17349bdb9cf041dea688d648e4576704b0f700a59f1011b7351815c8390744cd104bf92e
7
+ data.tar.gz: 61967ced8167906dd409ca9131df95e5317b260956f80a4beded6b40231c64ac9626a44300fd78226e8f9e13b8b91ad0297148c7c4c040e11a4215610144cd5b
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017 Lars Lockefeer
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # SchemaValidator
2
+
3
+ A simple CLI wrapper around [Rx](http://rx.codesimply.com) for all your schema validation needs.
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ Usage: runner [options]
9
+ -s, --schema SCHEMA The schema to validate against
10
+ -f, --file FILE The file to validate
11
+ -m META_SCHEMATA, A file containing meta schema definitions
12
+ --meta-schemata
13
+ ```
14
+
15
+ Example: validate `validatable.json` against the schema defined in `schema.json`, using the meta schemas from `meta_schemata.json`:
16
+
17
+ ```
18
+ ./schema-validator -s schema.json -f validatable.json -m meta_schemata.json
19
+ ```
20
+
21
+ ## Installation
22
+
23
+ Clone this repository and run:
24
+
25
+ ```
26
+ gem build schema-validator.gemspec
27
+ gem install schema-validator-{version}.gem
28
+ ```
29
+
30
+ Or add the following to your Gemfile:
31
+
32
+ ```
33
+ gem 'schema-validator', :git => 'https://github.com/larslockefeer/schema-validator.git', :submodules => true
34
+ ```
35
+
36
+ ## Acknowledgements
37
+
38
+ Under the hood, this gem uses [Rx](http://rx.codesimply.com) as the actual schema validation implementation.
39
+
40
+ ## Author
41
+
42
+ * Lars Lockefeer ([@larslockefeer](https://twitter.com/larslockefeer))
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'json'
4
+ require 'optparse'
5
+ require 'ostruct'
6
+ require_relative '../lib/rx/ruby/Rx.rb'
7
+ require 'yaml'
8
+
9
+ # A utility to parse JSON or YAML
10
+ def parse_json_or_yaml(file)
11
+ begin
12
+ JSON.parse(file)
13
+ rescue Exception => e
14
+ YAML.load(file)
15
+ end
16
+ end
17
+
18
+ options = OpenStruct.new
19
+ OptionParser.new do |opt|
20
+ opt.on('-s', '--schema SCHEMA', 'The schema to validate against.') { |o| options.schema = o }
21
+ opt.on('-f', '--file FILE', 'The file to validate.') { |o| options.validatable = o }
22
+ opt.on('-m', '--meta-schemata META_SCHEMATA', 'A file containing meta schema definitions.') { |o| options.meta_schemata = o }
23
+ end.parse!
24
+
25
+ unless options.schema && options.validatable
26
+ puts "Please provide a schema and a file to validate."
27
+ puts "Run me with the -h flag to see usage instructions."
28
+ exit
29
+ end
30
+
31
+ if options.meta_schemata
32
+ meta_schemata_file = File.open(options.meta_schemata).read
33
+ meta_schemata = parse_json_or_yaml(meta_schemata_file)
34
+ else
35
+ meta_schemata = []
36
+ end
37
+
38
+ schema_file = File.open(options.schema).read
39
+ schema = parse_json_or_yaml(schema_file)
40
+
41
+ file = File.open(options.validatable).read
42
+ validatable = parse_json_or_yaml(file)
43
+
44
+ rx = Rx.new({ :load_core => true })
45
+
46
+ # Step 1: Learn the meta schemata
47
+ unless meta_schemata.empty?
48
+ puts "Learning meta schemata"
49
+ end
50
+ meta_schemata.each do |meta_schema|
51
+ begin
52
+ rx.learn_type(meta_schema['uri'], meta_schema['schema'])
53
+ puts " ✅ Learned meta scheme #{meta_schema['uri']}"
54
+ rescue Exception => e
55
+ puts " ❌ An error occured learning meta scheme #{meta_schema['uri']}"
56
+ puts " #{e.message}"
57
+ exit
58
+ end
59
+ end
60
+
61
+ # Step 2: Load the schema that we are going to validate against
62
+ puts "Loading schema to validate against"
63
+ begin
64
+ schema = rx.make_schema(schema)
65
+ puts " ✅ Schema loaded successfully"
66
+ rescue Exception => e
67
+ puts " ❌ An error occured loading the schema"
68
+ puts " #{e.message}"
69
+ exit
70
+ end
71
+
72
+ # Step 3: Validate our file against the schema
73
+ puts "Validating"
74
+ if schema then
75
+ begin
76
+ schema.check!(validatable)
77
+ puts " ✅ File is according to schema."
78
+ rescue Exception => e
79
+ puts " ❌ An error occured validating the file against the schema"
80
+ puts " #{e.message}"
81
+ end
82
+ end
data/lib/rx/ruby/Rx.rb ADDED
@@ -0,0 +1,658 @@
1
+
2
+ class Rx
3
+ def self.schema(schema)
4
+ Rx.new(:load_core => true).make_schema(schema)
5
+ end
6
+
7
+ def initialize(opt={})
8
+ @type_registry = {}
9
+ @prefix = {
10
+ '' => 'tag:codesimply.com,2008:rx/core/',
11
+ '.meta' => 'tag:codesimply.com,2008:rx/meta/',
12
+ }
13
+
14
+ if opt[:load_core] then
15
+ Type::Core.core_types.each { |t| register_type(t) }
16
+ end
17
+ end
18
+
19
+ def register_type(type)
20
+ uri = type.uri
21
+
22
+ if @type_registry.has_key?(uri) then
23
+ raise Rx::Exception.new(
24
+ "attempted to register already-known type #{uri}"
25
+ )
26
+ end
27
+
28
+ @type_registry[ uri ] = type
29
+ end
30
+
31
+ def learn_type(uri, schema)
32
+ if @type_registry.has_key?(uri) then
33
+ raise Rx::Exception.new(
34
+ "attempted to learn type for already-registered uri #{uri}"
35
+ )
36
+ end
37
+
38
+ # make sure schema is valid
39
+ # should this be in a begin/rescue?
40
+ make_schema(schema)
41
+
42
+ @type_registry[ uri ] = { 'schema' => schema }
43
+ end
44
+
45
+ def expand_uri(name)
46
+ if name.match(/\A\w+:/) then; return name; end;
47
+
48
+ match = name.match(/\A\/(.*?)\/(.+)\z/)
49
+ if ! match then
50
+ raise Rx::Exception.new("couldn't understand Rx type name: #{name}")
51
+ end
52
+
53
+ if ! @prefix.has_key?(match[1]) then
54
+ raise Rx::Exception.new("unknown prefix '#{match[1]}' in name 'name'")
55
+ end
56
+
57
+ return @prefix[ match[1] ] + match[2]
58
+ end
59
+
60
+ def add_prefix(name, base)
61
+ if @prefix.has_key?(name) then
62
+ throw Rx::Exception.new("the prefix '#{name}' is already registered")
63
+ end
64
+
65
+ @prefix[name] = base
66
+ end
67
+
68
+ def make_schema(schema)
69
+ schema = { 'type' => schema } if schema.instance_of?(String)
70
+
71
+ if not (schema.instance_of?(Hash) and schema['type']) then
72
+ raise Rx::Exception.new('invalid type')
73
+ end
74
+
75
+ uri = expand_uri(schema['type'])
76
+
77
+ if ! @type_registry.has_key?(uri) then
78
+ raise Rx::Exception.new('unknown type')
79
+ end
80
+
81
+ type_class = @type_registry[uri]
82
+
83
+ if type_class.instance_of?(Hash) then
84
+ if schema.keys != [ 'type' ] then
85
+ raise Rx::Exception.new('composed type does not take check arguments')
86
+ end
87
+ return make_schema(type_class['schema'])
88
+ else
89
+ return type_class.new(schema, self)
90
+ end
91
+ end
92
+
93
+ class Helper; end;
94
+ class Helper::Range
95
+
96
+ def initialize(arg)
97
+ @range = { }
98
+
99
+ arg.each_pair { |key,value|
100
+ if not ['min', 'max', 'min-ex', 'max-ex'].index(key) then
101
+ raise Rx::Exception.new("illegal argument for Rx::Helper::Range")
102
+ end
103
+
104
+ @range[ key ] = value
105
+ }
106
+ end
107
+
108
+ def check(value)
109
+ return false if ! @range['min' ].nil? and value < @range['min' ]
110
+ return false if ! @range['min-ex'].nil? and value <= @range['min-ex']
111
+ return false if ! @range['max-ex'].nil? and value >= @range['max-ex']
112
+ return false if ! @range['max' ].nil? and value > @range['max' ]
113
+ return true
114
+ end
115
+ end
116
+
117
+ class Exception < StandardError
118
+ end
119
+
120
+ class ValidationError < StandardError
121
+ attr_accessor :path
122
+
123
+ def initialize(message, path)
124
+ @message = message
125
+ @path = path
126
+ end
127
+
128
+ def path
129
+ @path ||= ""
130
+ end
131
+
132
+ def message
133
+ "#{@message} (#{@path})"
134
+ end
135
+
136
+ def inspect
137
+ "#{@message} (#{@path})"
138
+ end
139
+
140
+ def to_s
141
+ inspect
142
+ end
143
+ end
144
+
145
+ class Type
146
+ def initialize(param, rx)
147
+ assert_valid_params(param)
148
+ end
149
+
150
+ def uri; self.class.uri; end
151
+
152
+ def assert_valid_params(param)
153
+ param.each_key { |k|
154
+ unless self.allowed_param?(k) then
155
+ raise Rx::Exception.new("unknown parameter #{k} for #{uri}")
156
+ end
157
+ }
158
+ end
159
+
160
+ module NoParams
161
+ def initialize(param, rx)
162
+ return if param.keys.length == 0
163
+ return if param.keys == [ 'type' ]
164
+
165
+ raise Rx::Exception.new('this type is not parameterized')
166
+ end
167
+ end
168
+
169
+ class Type::Core < Type
170
+ class << self
171
+ def uri
172
+ return 'tag:codesimply.com,2008:rx/core/' + subname
173
+ end
174
+ end
175
+
176
+ def check(value)
177
+ begin
178
+ check!(value)
179
+ true
180
+ rescue ValidationError
181
+ false
182
+ end
183
+ end
184
+
185
+ class All < Type::Core
186
+ @@allowed_param = { 'of' => true, 'type' => true }
187
+ def allowed_param?(p); return @@allowed_param[p]; end
188
+
189
+ def initialize(param, rx)
190
+ super
191
+
192
+ if ! param.has_key?('of') then
193
+ raise Rx::Exception.new("no 'of' parameter provided for #{uri}")
194
+ end
195
+
196
+ if param['of'].length == 0 then
197
+ raise Rx::Exception.new("no schemata provided for 'of' in #{uri}")
198
+ end
199
+
200
+ @alts = [ ]
201
+ param['of'].each { |alt| @alts.push(rx.make_schema(alt)) }
202
+ end
203
+
204
+ class << self; def subname; return 'all'; end; end
205
+
206
+ def check!(value)
207
+ @alts.each do |alt|
208
+ begin
209
+ alt.check!(value)
210
+ rescue ValidationError => e
211
+ e.path = "/all" + e.path
212
+ raise e
213
+ end
214
+ end
215
+ return true
216
+ end
217
+ end
218
+
219
+ class Any < Type::Core
220
+ @@allowed_param = { 'of' => true, 'type' => true }
221
+ def allowed_param?(p); return @@allowed_param[p]; end
222
+
223
+ def initialize(param, rx)
224
+ super
225
+
226
+ if param['of'] then
227
+ if param['of'].length == 0 then
228
+ raise Rx::Exception.new(
229
+ "no alternatives provided for 'of' in #{uri}"
230
+ )
231
+ end
232
+
233
+ @alts = [ ]
234
+ param['of'].each { |alt| @alts.push(rx.make_schema(alt)) }
235
+ end
236
+ end
237
+
238
+ class << self; def subname; return 'any'; end; end
239
+
240
+ def check!(value)
241
+ return true unless @alts
242
+
243
+ @alts.each do |alt|
244
+ begin
245
+ return true if alt.check!(value)
246
+ rescue ValidationError
247
+ end
248
+ end
249
+
250
+ raise ValidationError.new("expected one to match", "/any")
251
+ end
252
+ end
253
+
254
+ class Arr < Type::Core
255
+ class << self; def subname; return 'arr'; end; end
256
+
257
+ @@allowed_param = { 'contents' => true, 'length' => true, 'type' => true }
258
+ def allowed_param?(p); return @@allowed_param[p]; end
259
+
260
+ def initialize(param, rx)
261
+ super
262
+
263
+ unless param['contents'] then
264
+ raise Rx::Exception.new("no contents schema given for #{uri}")
265
+ end
266
+
267
+ @contents_schema = rx.make_schema( param['contents'] )
268
+
269
+ if param['length'] then
270
+ @length_range = Rx::Helper::Range.new( param['length'] )
271
+ end
272
+ end
273
+
274
+ def check!(value)
275
+ unless value.instance_of?(Array)
276
+ raise ValidationError.new("expected array got #{value.class}", "/arr")
277
+ end
278
+
279
+ if @length_range
280
+ unless @length_range.check(value.length)
281
+ raise ValidationError.new("expected array with #{@length_range} elements, got #{value.length}", "/arr")
282
+ end
283
+ end
284
+
285
+ if @contents_schema then
286
+ value.each do |v|
287
+ begin
288
+ @contents_schema.check!(v)
289
+ rescue ValidationError => e
290
+ e.path = "/arr" + e.path
291
+ raise e
292
+ end
293
+ end
294
+ end
295
+
296
+ return true
297
+ end
298
+ end
299
+
300
+ class Bool < Type::Core
301
+ class << self; def subname; return 'bool'; end; end
302
+
303
+ include Type::NoParams
304
+
305
+ def check!(value)
306
+ unless value.instance_of?(TrueClass) or value.instance_of?(FalseClass)
307
+ raise ValidationError.new("expected bool got #{value.inspect}", "/bool")
308
+ end
309
+ true
310
+ end
311
+ end
312
+
313
+ class Fail < Type::Core
314
+ class << self; def subname; return 'fail'; end; end
315
+ include Type::NoParams
316
+ def check(value); return false; end
317
+ def check!(value); raise ValidationError.new("explicit fail", "/fail"); end
318
+ end
319
+
320
+ #
321
+ # Added by dan - 81030
322
+ class Date < Type::Core
323
+ class << self; def subname; return 'date'; end; end
324
+
325
+ include Type::NoParams
326
+
327
+ def check!(value)
328
+ unless value.instance_of?(::Date)
329
+ raise ValidationError("expected Date got #{value.inspect}", "/date")
330
+ end
331
+ true
332
+ end
333
+ end
334
+
335
+ class Def < Type::Core
336
+ class << self; def subname; return 'def'; end; end
337
+ include Type::NoParams
338
+ def check!(value); raise ValidationError.new("def failed", "/def") unless ! value.nil?; end
339
+ end
340
+
341
+ class Map < Type::Core
342
+ class << self; def subname; return 'map'; end; end
343
+ @@allowed_param = { 'values' => true, 'type' => true }
344
+ def allowed_param?(p); return @@allowed_param[p]; end
345
+
346
+ def initialize(param, rx)
347
+ super
348
+
349
+ unless param['values'] then
350
+ raise Rx::Exception.new("no values schema given for #{uri}")
351
+ end
352
+
353
+ @value_schema = rx.make_schema(param['values'])
354
+ end
355
+
356
+ def check!(value)
357
+ unless value.instance_of?(Hash) or value.class.to_s == "HashWithIndifferentAccess"
358
+ raise ValidationError.new("expected map got #{value.inspect}", "/map")
359
+ end
360
+
361
+ if @value_schema
362
+ value.each_value do |v|
363
+ begin
364
+ @value_schema.check!(v)
365
+ rescue ValidationError => e
366
+ e.path = "/map" + e.path
367
+ raise e
368
+ end
369
+ end
370
+ end
371
+
372
+ return true
373
+ end
374
+ end
375
+
376
+ class Nil < Type::Core
377
+ class << self; def subname; return 'nil'; end; end
378
+ include Type::NoParams
379
+ def check!(value); raise ValidationError.new("expected nil got #{value.inspect}", "/nil") unless value.nil?; true; end
380
+ end
381
+
382
+ class Num < Type::Core
383
+ class << self; def subname; return 'num'; end; end
384
+ @@allowed_param = { 'range' => true, 'type' => true, 'value' => true }
385
+ def allowed_param?(p); return @@allowed_param[p]; end
386
+
387
+ def initialize(param, rx)
388
+ super
389
+
390
+ if param.has_key?('value') then
391
+ if ! param['value'].kind_of?(Numeric) then
392
+ raise Rx::Exception.new("invalid value parameter for #{uri}")
393
+ end
394
+
395
+ @value = param['value']
396
+ end
397
+
398
+ if param['range'] then
399
+ @value_range = Rx::Helper::Range.new( param['range'] )
400
+ end
401
+ end
402
+
403
+ def check!(value)
404
+ if not value.kind_of?(Numeric)
405
+ raise ValidationError.new("expected Numeric got #{value.inspect}", "/#{self.class.subname}")
406
+ end
407
+ if @value_range and not @value_range.check(value)
408
+ raise ValidationError.new("expected Numeric in range #{@value_range} got #{value.inspect}", "/#{self.class.subname}")
409
+ end
410
+ if @value and value != @value
411
+ raise ValidationError.new("expected Numeric to equal #{@value} got #{value.inspect}", "/#{self.class.subname}")
412
+ end
413
+ true
414
+ end
415
+ end
416
+
417
+ class Int < Type::Core::Num
418
+ class << self; def subname; return 'int'; end; end
419
+
420
+ def initialize(param, rx)
421
+ super
422
+
423
+ if @value and @value % 1 != 0 then
424
+ raise Rx::Exception.new("invalid value parameter for #{uri}")
425
+ end
426
+ end
427
+
428
+ def check!(value)
429
+ super
430
+ unless value % 1 == 0
431
+ raise ValidationError.new("expected Integer got #{value.inspect}", "/int")
432
+ end
433
+ return true
434
+ end
435
+ end
436
+
437
+ class One < Type::Core
438
+ class << self; def subname; return 'one'; end; end
439
+ include Type::NoParams
440
+
441
+ def check!(value)
442
+ unless [ Numeric, String, TrueClass, FalseClass ].any? { |cls| value.kind_of?(cls) }
443
+ raise ValidationError.new("expected One got #{value.inspect}", "/one")
444
+ end
445
+ end
446
+ end
447
+
448
+ class Rec < Type::Core
449
+ class << self; def subname; return 'rec'; end; end
450
+ @@allowed_param = {
451
+ 'type' => true,
452
+ 'rest' => true,
453
+ 'required' => true,
454
+ 'optional' => true,
455
+ }
456
+
457
+ def allowed_param?(p); return @@allowed_param[p]; end
458
+
459
+ def initialize(param, rx)
460
+ super
461
+
462
+ @field = { }
463
+
464
+ @rest_schema = rx.make_schema(param['rest']) if param['rest']
465
+
466
+ [ 'optional', 'required' ].each { |type|
467
+ next unless param[type]
468
+ param[type].keys.each { |field|
469
+ if @field[field] then
470
+ raise Rx::Exception.new("#{field} in both required and optional")
471
+ end
472
+
473
+ @field[field] = {
474
+ :required => (type == 'required'),
475
+ :schema => rx.make_schema(param[type][field]),
476
+ }
477
+ }
478
+ }
479
+ end
480
+
481
+ def check!(value)
482
+ unless value.instance_of?(Hash) or value.class.to_s == "HashWithIndifferentAccess"
483
+ raise ValidationError.new("expected Hash got #{value.class}", "/rec")
484
+ end
485
+
486
+ rest = [ ]
487
+
488
+ value.each do |field, field_value|
489
+ unless @field[field] then
490
+ rest.push(field)
491
+ next
492
+ end
493
+
494
+ begin
495
+ @field[field][:schema].check!(field_value)
496
+ rescue ValidationError => e
497
+ e.path = "/rec:'#{field}'"
498
+ raise e
499
+ end
500
+ end
501
+
502
+ @field.select { |k,v| @field[k][:required] }.each do |pair|
503
+ unless value.has_key?(pair[0])
504
+ raise ValidationError.new("expected Hash to have key: '#{pair[0]}', only had #{value.keys.inspect}", "/rec")
505
+ end
506
+ end
507
+
508
+ if rest.length > 0 then
509
+ unless @rest_schema
510
+ raise ValidationError.new("Hash had extra keys: #{rest.inspect}", "/rec")
511
+ end
512
+ rest_hash = { }
513
+ rest.each { |field| rest_hash[field] = value[field] }
514
+ begin
515
+ @rest_schema.check!(rest_hash)
516
+ rescue ValidationError => e
517
+ e.path = "/rec"
518
+ raise e
519
+ end
520
+ end
521
+
522
+ return true
523
+ end
524
+ end
525
+
526
+ class Seq < Type::Core
527
+ class << self; def subname; return 'seq'; end; end
528
+ @@allowed_param = { 'tail' => true, 'contents' => true, 'type' => true }
529
+ def allowed_param?(p); return @@allowed_param[p]; end
530
+
531
+ def initialize(param, rx)
532
+ super
533
+
534
+ unless param['contents'] and param['contents'].kind_of?(Array) then
535
+ raise Rx::Exception.new("missing or invalid contents for #{uri}")
536
+ end
537
+
538
+ @content_schemata = param['contents'].map { |s| rx.make_schema(s) }
539
+
540
+ if param['tail'] then
541
+ @tail_schema = rx.make_schema(param['tail'])
542
+ end
543
+ end
544
+
545
+ def check!(value)
546
+ unless value.instance_of?(Array)
547
+ raise ValidationError.new("expected Array got #{value.inspect}", "/seq")
548
+ end
549
+ if value.length < @content_schemata.length
550
+ raise ValidationError.new("expected Array to have at least #{@content_schemata.length} elements, had #{value.length}", "/seq")
551
+ end
552
+ @content_schemata.each_index { |i|
553
+ begin
554
+ @content_schemata[i].check!(value[i])
555
+ rescue ValidationError => e
556
+ e.path = "/seq" + e.path
557
+ raise e
558
+ end
559
+ }
560
+
561
+ if value.length > @content_schemata.length then
562
+ unless @tail_schema
563
+ raise ValidationError.new("expected tail_schema", "/seq")
564
+ end
565
+ begin
566
+ @tail_schema.check!(value[
567
+ @content_schemata.length,
568
+ value.length - @content_schemata.length
569
+ ])
570
+ rescue ValidationError => e
571
+ e.path = "/seq" + e.path
572
+ raise e
573
+ end
574
+ end
575
+
576
+ return true
577
+ end
578
+ end
579
+
580
+ class Str < Type::Core
581
+ class << self; def subname; return 'str'; end; end
582
+ @@allowed_param = { 'type' => true, 'value' => true, 'length' => true }
583
+ def allowed_param?(p); return @@allowed_param[p]; end
584
+
585
+ def initialize(param, rx)
586
+ super
587
+
588
+ if param['length'] then
589
+ @length_range = Rx::Helper::Range.new( param['length'] )
590
+ end
591
+
592
+ if param.has_key?('value') then
593
+ if ! param['value'].instance_of?(String) then
594
+ raise Rx::Exception.new("invalid value parameter for #{uri}")
595
+ end
596
+
597
+ @value = param['value']
598
+ end
599
+ end
600
+
601
+ def check!(value)
602
+ unless value.instance_of?(String)
603
+ raise ValidationError.new("expected String got #{value.inspect}", "/str")
604
+ end
605
+
606
+ if @length_range
607
+ unless @length_range.check(value.length)
608
+ raise ValidationError.new("expected string with #{@length_range} characters, got #{value.length}", "/str")
609
+ end
610
+ end
611
+
612
+ if @value and value != @value
613
+ raise ValidationError.new("expected #{@value.inspect} got #{value.inspect}", "/str")
614
+ end
615
+ return true
616
+ end
617
+ end
618
+
619
+ #
620
+ # Added by dan - 81106
621
+ class Time < Type::Core
622
+ class << self; def subname; return 'time'; end; end
623
+
624
+ include Type::NoParams
625
+
626
+ def check!(value)
627
+ unless value.instance_of?(::Time)
628
+ raise ValidationError.new("expected Time got #{value.inspect}", "/time")
629
+ end
630
+ true
631
+ end
632
+ end
633
+
634
+ class << self
635
+ def core_types
636
+ return [
637
+ Type::Core::All,
638
+ Type::Core::Any,
639
+ Type::Core::Arr,
640
+ Type::Core::Bool,
641
+ Type::Core::Date,
642
+ Type::Core::Def,
643
+ Type::Core::Fail,
644
+ Type::Core::Int,
645
+ Type::Core::Map,
646
+ Type::Core::Nil,
647
+ Type::Core::Num,
648
+ Type::Core::One,
649
+ Type::Core::Rec,
650
+ Type::Core::Seq,
651
+ Type::Core::Str,
652
+ Type::Core::Time
653
+ ]
654
+ end
655
+ end
656
+ end
657
+ end
658
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: schema-validator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Lars Lockefeer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-10-27 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: "\n A JSON schema validation tool.\n "
14
+ email:
15
+ - lars.lockefeer@teampicnic.com
16
+ executables:
17
+ - schema-validator
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - LICENSE
22
+ - README.md
23
+ - bin/schema-validator
24
+ - lib/rx/ruby/Rx.rb
25
+ homepage: https://github.com/larslockefeer/schema-validator
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib/rx/ruby
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - "~>"
36
+ - !ruby/object:Gem::Version
37
+ version: '2.0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubyforge_project:
45
+ rubygems_version: 2.4.8
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: A JSON schema validation tool.
49
+ test_files: []