kwalify 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,62 +1,29 @@
1
- .=title: ChangeLog
2
- .?revision: $Rev: 9 $
3
- .?release: $Release: 0.1.0 $
4
- .?lastupdate: $Date: 2005-08-01 06:48:56 +0900 (Mon, 01 Aug 2005) $
5
-
6
- .: 2005-08-01 (rev.9) - release 0.1.0
7
- .- [change] block arguments of Kwalify::Validator.new() changed
8
- .- [change] webiste/* added
9
-
10
- .: 2005-07-29 (rev.8)
11
- .- [bugfix] meta-validator.rb is fixed to work fine
12
- .- [change] enclose key name in schema with '"' (ex. "email", "addr", ...)
13
- .- [change] document update (Tips section added)
14
- .- [enhance] command-line option '-M' which invoke Kwalify::meta_validator2
15
-
16
- .: 2005-07-27 (rev.7)
17
- .- [change] use 'seq' and 'map' instead of 'list' and 'hash' as type
18
- .- [change] use 'sequence:' and 'mapping:' instead of 'elements:'
19
- .- [enhance] use meta-validator for validating schema definition
20
- .- [change] command-line option '-c' is renamed to '-m'
21
- .- [enhance] 'type:' is keeped at @type and class name is at @klass in Schema class
22
- .- [enhance] 'name:' support
23
- .- [enahnce] (experimental) block support for Validator#initialize()
24
-
25
- .: 2005-07-26 (rev.6)
26
- .- [enhance] support multiple documents using YAML::load_stream()
27
- .- [enhance] new command-line option '-t' : expand tab characters
28
- .- [enhance] support domain document
29
- .- [enhance] add examples - 'address-book' and 'invoice'
30
- .- [enhance] add 'lib/kwalify/util/option-parser.rb'
31
-
32
- .: 2005-07-25 (rev.5)
33
- .- [enhance] Kwalify::DEFAULT_TYPE is String
34
- .- [change] array index starts with 1
35
- .- [change] command-line option '-s' is changed to '-f'
36
- .- [enhance] new command-line option '-s' (silent)
37
- .- [change] output format of bin/kwalify changed
38
- .- [enhance] untabify schema and document file using YAML::Helper
39
- .- [enhance] add new file 'lib/kwalify/util/yaml-helper.rb'
40
-
41
- .: 2005-07-25 (rev.4)
42
- .- [change] class Kwalify::RuleSet is renamed to Kwalify::Schema
43
- .- [enhance] add new class Kwalify::Validator
44
- .- [enhance] add bin/kwalify
45
- .- [enhance] add doc/users-guide.txt
46
- .- [enhance] add README.txt, COPYING, setup.rb, kwalify.gemspec
47
-
48
- .: 2005-07-25 (rev.3)
49
- .- [change] use mappings at elements of Hash
50
- .- [change] rename 'children' to 'elements'
51
- .- [enhance] support recursive collections
52
- .- [enhance] add RuleSet#inspect
53
- .- [change] rename 'error-messages.rb' to 'error-msg.rb'
54
- .- [change] rename Text and Boolean to Kwalify::Text and Kwalify::Boolean
55
-
56
- .: 2005-07-24 (rev.2)
57
- .- [enhance] add pattern check
58
- .- [enhance] add Text class
59
- .- [enhance] add test script
60
-
61
- .: 2005-07-24 (rev.1)
62
- .- initial commit
1
+ .=title: ChangeLog
2
+ .?release: $Release: 0.2.0 $
3
+ .?lastupdate: $Date$
4
+ .?version: $Rev$
5
+
6
+ .: 2005-09-25 (release 0.2.0)
7
+ .* Enhances:
8
+ .- New type 'scalar' and 'timestamp' added
9
+ .- Add new rule 'range:' which validates value range.
10
+ See users' guide for details.
11
+ .- Add new rule 'length:' which validate length of string value.
12
+ See users' guide for details.
13
+ .- Add experimental rule 'assert:' which validates value with an
14
+ expression. See users' guide for details.
15
+ .- New method 'Kwalify::Validator#validate_hook()' is added.
16
+ This method is called by Kwalify::Validator#validate().
17
+ See users' guide for details.
18
+ .- New class 'MetaValidator' added.
19
+ .- New test script 'test/test-metavalidator.rb' added.
20
+ .* Changes:
21
+ .- Type name changed to suite YAML data type:
22
+ .= string -> str
23
+ .= integer -> int
24
+ .= boolean -> bool
25
+ .- Error index starts with 0 (before starts with 1).
26
+ .- Class 'Schema' is renamed to 'Rule'.
27
+
28
+ .: 2005-08-01 (release 0.1.0)
29
+ .- beta release
data/README.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  .=title: README
2
- .?version: $Rev: 9 $
3
- .?lastupdate: $Date: 2005-08-01 06:48:56 +0900 (Mon, 01 Aug 2005) $
4
- .?release: $Release: 0.1.0 $
2
+ .?version: $Rev: 18 $
3
+ .?lastupdate: $Date: 2005-09-25 22:36:35 +0900 (Sun, 25 Sep 2005) $
4
+ .?release: $Release: 0.2.0 $
5
5
 
6
6
 
7
7
  .$ About Kwalify
@@ -15,14 +15,42 @@
15
15
 
16
16
  .$ Installation
17
17
 
18
- Just type 'gem install --remote kwalify' if you have installed RubyGems.
19
- Or use setup.rb as following:
20
- .====================
21
- $ ruby setup.rb config
22
- $ ruby setup.rb setup
23
- $ su -
24
- # ruby setup.rb install
25
- .====================
18
+ .* Just type 'gem install --remote kwalify' if you have installed RubyGems.
19
+ .====================
20
+ $ sudo gem install --remote kwalify
21
+ .====================
22
+
23
+ .* If you can be root user, use 'setup.rb' as following:
24
+ .====================
25
+ $ tar xjf kwalify_x.x.x.tar.bz2
26
+ $ cd kwalify_x.x.x/
27
+ $ ruby setup.rb config
28
+ $ ruby setup.rb setup
29
+ $ sudo ruby setup.rb install
30
+ .====================
31
+
32
+ .* If you can't be root user, copy script and libraries to proper directory.
33
+ .====================
34
+ $ tar xjf kwalify_x.x.x.tar.bz2
35
+ $ cd kwalify_x.x.x/
36
+ $ mkdir -p $HOME/bin
37
+ $ cp -a bin/* $HOME/bin
38
+ $ export PATH=$PATH:$HOME/bin
39
+ $ mkdir -p $HOME/lib/ruby
40
+ $ cp -a lib/* $HOME/lib/ruby
41
+ $ export RUBYLIB=$HOME/lib/ruby
42
+ .====================
43
+
44
+ .* Or use 'contrib/inline-require' script to concatenate all script and
45
+ libraries into one file.
46
+ .====================
47
+ $ tar xjf kwalify_x.x.x.tar.bz2
48
+ $ cd kwalify_x.x.x/
49
+ $ unset RUBYLIB
50
+ $ ruby contrib/inline-require -I ./lib bin/kwalify > kwalify
51
+ $ mv kwalify $HOME/bin
52
+ $ chmod a+x $HOME/bin/kwalify
53
+ .====================
26
54
 
27
55
 
28
56
  .$ License
@@ -1,185 +1,24 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  ###
4
- ### $Rev: 8 $
5
- ### $Release: 0.1.0 $
4
+ ### $Rev: 12 $
5
+ ### $Release: 0.2.0 $
6
6
  ### copyright(c) 2005 kuwata-lab all rights reserved.
7
7
  ###
8
8
 
9
9
  require 'kwalify'
10
- require 'yaml'
11
- require 'kwalify/meta-validator'
12
- require 'kwalify/util/yaml-helper'
13
- require 'kwalify/util/option-parser'
14
-
15
-
16
- module Kwalify
17
-
18
- RELEASE = ("$Release: 0.1.0 $" =~ /[.\d]+/) && $&
19
-
20
-
21
- class Main
22
-
23
- def initialize(command, argv=ARGV)
24
- @command = command
25
- @options, @proerties = parse_argv(argv)
26
- @filenames = argv
27
- end
28
-
29
-
30
- def execute(out=$stdout)
31
- if @options[:help] || @options[:version]
32
- $stderr.puts "Kwalify: #{RELEASE}" if @options[:version]
33
- $stderr.puts usage() if @options[:help]
34
- return
35
- end
36
- if !@options[:meta] && !@options[:schema]
37
- raise CommandOptionError.new("command-line option '-f' or '-m' required.")
38
- end
39
- #
40
- if @options[:meta]
41
- meta_validate(out)
42
- else
43
- validate(out)
44
- end
45
- end
46
-
47
-
48
- private
49
-
50
-
51
- def meta_validate(out)
52
- meta_validator = @options[:meta2] ? Kwalify.meta_validator2() : Kwalify.meta_validator()
53
- if @filenames.empty?
54
- _meta_validate(out, meta_validator, nil)
55
- else
56
- @filenames.each do |fname|
57
- _meta_validate(out, meta_validator, fname)
58
- end
59
- end
60
- end
61
-
62
-
63
- def _meta_validate(out, meta_validator, filename=nil)
64
- s = filename ? File.open(filename) { |f| f.read() } : $stdin.read()
65
- s = YamlHelper.untabify(s) if @options[:untabify]
66
- yaml = YAML.load(s)
67
- yaml = yaml.value if yaml.is_a?(YAML::Syck::DomainType)
68
- filename ||= "(stdin)"
69
- if !yaml || yaml.empty?
70
- out.puts "#{filename}: empty."
71
- return
72
- end
73
- errors = meta_validator.validate(yaml)
74
- if !errors.empty?
75
- out.puts "#{filename}: NG!"
76
- errors.each { |error| out.puts " - #{error.message}" }
77
- return
78
- end
79
- begin
80
- validator = Kwalify::Validator.new(yaml) # error raised when schema is wrong
81
- out.puts "#{filename}: ok." unless @options[:silent]
82
- rescue Kwalify::SchemaError => ex
83
- out.puts "#{filename}: NG! #{ex.message}"
84
- end
85
- end
86
-
87
-
88
- def validate(out)
89
- schema_filename = @options[:schema]
90
- s = File.open(schema_filename) { |f| f.read() }
91
- s = YamlHelper.untabify(s) if @options[:untabify]
92
- yaml = YAML.load(s)
93
- yaml = yaml.value if yaml.is_a?(YAML::Syck::DomainType)
94
- validator = Kwalify::Validator.new(yaml)
95
- #
96
- if @filenames.empty?
97
- _validate(out, validator, nil)
98
- else
99
- @filenames.each do |fname|
100
- _validate(out, validator, fname)
101
- end
102
- end
103
- end
104
-
105
-
106
- def _validate(out, validator, filename=nil)
107
- s = filename ? File.open(filename) { |f| f.read() } : $stdin.read()
108
- s = YamlHelper.untabify(s) if @options[:untabify]
109
- stream = YAML::load_stream(s)
110
- filename ||= "(stdin)"
111
- i = 0
112
- stream.documents.each do |document|
113
- i += 1
114
- document = document.value if document.is_a?(YAML::Syck::DomainType)
115
- if !document || document.empty?
116
- out.puts "#{filename}: empty."
117
- return
118
- end
119
- errors = validator.validate(document)
120
- if errors.empty?
121
- out.puts "#{filename}\##{i}: valid." unless @options[:silent]
122
- else
123
- out.puts "#{filename}\##{i}: INVALID"
124
- errors.each { |error| out.puts " - #{error.message}" }
125
- end
126
- end
127
- end
128
-
129
-
130
- def usage()
131
- s = ""
132
- s << "Usage1: #{@command} [-hvs] -f schema.yaml document.yaml [document2.yaml ...]\n"
133
- s << "Usage2: #{@command} [-hvs] -c schema.yaml [schema2.yaml ...]\n"
134
- s << " -h, --help : help\n"
135
- s << " -v : version\n"
136
- s << " -s : silent\n"
137
- s << " -f schema.yaml : schema definition file\n"
138
- s << " -m : meta-validation mode\n"
139
- s << " -t : expand tab character automatically\n"
140
- return s
141
- end
142
-
143
-
144
- def parse_argv(argv)
145
- opt_parser = CommandOptionParser.new("hvstmM", "f")
146
- #opts, props = opt_parser.parse(argv)
147
- #properties = {}
148
- #props.each do |pname, pvalue|
149
- # key = pname.gsub(/-/, '_').intern
150
- # value = value == nil ? true: CommandOptionParser.to_value(pvalue)
151
- # properties[key] = value
152
- #end
153
- auto_convert = true
154
- opts, properties = opt_parser.parse(argv, auto_convert)
155
- options = {}
156
- options[:help] = opts[?h] || properties[:help]
157
- options[:version] = opts[?v] || properties[:version]
158
- options[:silent] = opts[?s]
159
- options[:schema] = opts[?f]
160
- options[:meta] = opts[?m] || opts[?M]
161
- options[:meta2] = opts[?M]
162
- options[:untabify] = opts[?t]
163
- return options, properties
164
- end
165
-
166
- end
167
-
168
- end
169
-
170
-
171
- #if __FILE__ == $0
172
- unless defined?(KWALIFY_NOEXEC)
173
- command = File.basename($0)
174
- begin
175
- main = Kwalify::Main.new(command, ARGV)
176
- main.execute()
177
- exit 0
178
- rescue Kwalify::KwalifyError => ex
179
- $stderr.puts "ERROR: #{ex.message}"
180
- exit 1
181
- #rescue => ex
182
- # $stderr.puts ex.message
183
- # exit 1
184
- end
10
+ require 'kwalify/main-program'
11
+
12
+
13
+ command = File.basename($0)
14
+ begin
15
+ main = Kwalify::MainProgram.new(ARGV, command)
16
+ s = main.execute()
17
+ print s if s
18
+ rescue CommandOptionError => ex
19
+ $stderr.puts ex.message
20
+ exit 1
21
+ rescue Kwalify::KwalifyError => ex
22
+ $stderr.puts "ERROR: #{ex.message}"
23
+ exit 1
185
24
  end
@@ -15,14 +15,46 @@
15
15
  <div align="left"><h1>Kwalify Users' Guide</h1></div>
16
16
  <div align="left">
17
17
  makoto kuwata &lt;kwa(at)kuwata-lab.com&gt;<br>
18
- last update: $Date: 2005-08-01 06:48:56 +0900 (Mon, 01 Aug 2005) $<br>
18
+ last update: $Date: 2005-09-25 22:36:35 +0900 (Sun, 25 Sep 2005) $<br>
19
19
  </div>
20
20
 
21
21
  <a name="preface"></a>
22
22
  <h2 class="section1">Preface</h2>
23
23
  <p>Kwalify<sup>(<a href="#fnref:1" name="fnlink:1">*1</a>)</sup> is a tiny schema validator for YAML document.
24
24
  </p>
25
- <p>Kwalify is in fact very poor compared to Relax NG or DTD.
25
+ <p>Do you know "80-20 rule" known as Pareto Law? This rule suggests that 20% of the population owns 80% of the wealth.
26
+ Kwalify is based on a new "50-5 rule" which suggests that 5% of the population owns 50 of the wealth.
27
+ This rule is more aggressive and cost-effective than Pareto Law. The rule is named as "Levi's Law".
28
+ </p>
29
+ <div align="center">
30
+ <table class="table1" border="1" cellspacing="0">
31
+ <tr class="tr1">
32
+ <th class="th1">schema technology</th>
33
+ <th class="th1">(A) cover range</th>
34
+ <th class="th1">(B) cost to pay</th>
35
+ <th class="th1">(A)/(B) effectiveness</th>
36
+ </tr>
37
+ <tr class="tr1">
38
+ <td class="td1">XML Schema</td>
39
+ <td class="td1">96%</td>
40
+ <td class="td1">80%</td>
41
+ <td class="td1">1.2 (= 96/80)</td>
42
+ </tr>
43
+ <tr class="tr1">
44
+ <td class="td1">RelaxNG</td>
45
+ <td class="td1">80%</td>
46
+ <td class="td1">20%</td>
47
+ <td class="td1">4.0 (= 80/20)</td>
48
+ </tr>
49
+ <tr class="tr1">
50
+ <td class="td1">Kwalify</td>
51
+ <td class="td1">50%</td>
52
+ <td class="td1">5%</td>
53
+ <td class="td1">10.0 (= 50/5)</td>
54
+ </tr>
55
+ </table>
56
+ </div>
57
+ <p>Kwalify is very small and in fact very poor compared to RelaxNG or XML Schema.
26
58
  I hope you extend/customize Kwalify for your own way.
27
59
  </p>
28
60
  Table of Contents:
@@ -50,6 +82,8 @@ Table of Contents:
50
82
  </li>
51
83
  <li><a href="#schema-rules">Rules</a>
52
84
  </li>
85
+ <li><a href="#schema-hook">Validator#validator_hook()</a>
86
+ </li>
53
87
  <li><a href="#schema-block">Validator with Block</a>
54
88
  </li>
55
89
  </ul>
@@ -89,7 +123,7 @@ usage2: validate schema definition in command-line</div>
89
123
  </p>
90
124
  <dl class="dl3">
91
125
  <dt class="dt3"><strong>
92
- <code>-h</code>, <code>--help</code></strong></dt>
126
+ <code>-h</code>, <code>--help</code> </strong></dt>
93
127
  <dd class="dd3">
94
128
  Print help message.
95
129
  </dd>
@@ -129,17 +163,15 @@ validate YAML document in Ruby script</div>
129
163
  <pre class="program">require 'kwalify'
130
164
 
131
165
  ## parse schema definition and create validator
132
- str = File.read('schema.yaml')
133
- schema_def = YAML.load(str)
134
- validator = Kwalify::Validator.new(schema_def) # raises Kwalify::SchemaError if wrong
166
+ schema = YAML.load_file('schema.yaml')
167
+ validator = Kwalify::Validator.new(schema) # raises Kwalify::SchemaError if wrong
135
168
 
136
169
  ## validate YAML document
137
- str = File.read('document.yaml')
138
- document = YAML.load(str)
170
+ document = YAML.load_file('document.yaml')
139
171
  error_list = validator.validate(document)
140
172
  unless error_list.empty?
141
- error_list.each do |error| # error is Kwalify::ValidationException
142
- print error.message
173
+ error_list.each do |error| # error is Kwalify::ValidationError
174
+ puts "[#{error.path}] #{error.message}"
143
175
  end
144
176
  end
145
177
  </pre>
@@ -158,7 +190,7 @@ end
158
190
  <code>schema01.yaml</code> : sequence of string</div>
159
191
  <pre class="program">type: seq
160
192
  sequence:
161
- - type: string
193
+ - type: str
162
194
  </pre>
163
195
  <a name="document01a.yaml"></a>
164
196
  <div class="program_caption">
@@ -170,7 +202,7 @@ sequence:
170
202
  <div class="terminal_caption">
171
203
  validate</div>
172
204
  <pre class="terminal">$ kwalify -f schema01.yaml document01a.yaml
173
- document01a.yaml#1: valid.
205
+ document01a.yaml#0: valid.
174
206
  </pre>
175
207
  <a name="document01b.yaml"></a>
176
208
  <div class="program_caption">
@@ -182,10 +214,10 @@ document01a.yaml#1: valid.
182
214
  <div class="terminal_caption">
183
215
  validate</div>
184
216
  <pre class="terminal">$ kwalify -f schema01.yaml document01b.yaml
185
- document01b.yaml#1: INVALID
186
- - [/2] string type expected but got Fixnum.
217
+ document01b.yaml#0: INVALID
218
+ - [/1] '123': not a string.
187
219
  </pre>
188
- <p>Default '<code>type:</code>' is <code>string</code> so you can omit '<code>type: string</code>'.
220
+ <p>Default '<code>type:</code>' is <code>str</code> so you can omit '<code>type: str</code>'.
189
221
  </p>
190
222
  <br>
191
223
 
@@ -198,13 +230,13 @@ document01b.yaml#1: INVALID
198
230
  <pre class="program">type: map
199
231
  mapping:
200
232
  name:
201
- type: string
233
+ type: str
202
234
  required: yes
203
235
  email:
204
- type: string
236
+ type: str
205
237
  pattern: /@/
206
238
  age:
207
- type: integer
239
+ type: int
208
240
  birth:
209
241
  type: date
210
242
  </pre>
@@ -219,7 +251,7 @@ birth: 1985-01-01
219
251
  <div class="terminal_caption">
220
252
  validate</div>
221
253
  <pre class="terminal">$ kwalify -f schema02.yaml document02a.yaml
222
- document02a.yaml#1: valid.
254
+ document02a.yaml#0: valid.
223
255
  </pre>
224
256
  <a name="document02b.yaml"></a>
225
257
  <div class="program_caption">
@@ -232,10 +264,10 @@ birth: Jun 01, 1985
232
264
  <div class="terminal_caption">
233
265
  validate</div>
234
266
  <pre class="terminal">$ kwalify -f schema02.yaml document02b.yaml
235
- document02b.yaml#1: INVALID
236
- - [/birth] date type expected but got String.
237
- - [/age] integer type expected but got String.
238
- - [/email] 'foo(at)mail.com' is not matched to pattern /@/.
267
+ document02b.yaml#0: INVALID
268
+ - [/birth] 'Jun 01, 1985': not a date.
269
+ - [/age] 'twenty': not a integer.
270
+ - [/email] 'foo(at)mail.com': not matched to pattern /@/.
239
271
  </pre>
240
272
  <br>
241
273
 
@@ -250,10 +282,10 @@ sequence:
250
282
  - type: map
251
283
  mapping:
252
284
  name:
253
- type: string
285
+ type: str
254
286
  required: true
255
287
  email:
256
- type: string
288
+ type: str
257
289
  </pre>
258
290
  <a name="document03a.yaml"></a>
259
291
  <div class="program_caption">
@@ -268,7 +300,7 @@ sequence:
268
300
  <div class="terminal_caption">
269
301
  validate</div>
270
302
  <pre class="terminal">$ kwalify -f schema03.yaml document03a.yaml
271
- document03a.yaml#1: valid.
303
+ document03a.yaml#0: valid.
272
304
  </pre>
273
305
  <a name="document03b.yaml"></a>
274
306
  <div class="program_caption">
@@ -283,10 +315,10 @@ document03a.yaml#1: valid.
283
315
  <div class="terminal_caption">
284
316
  validate</div>
285
317
  <pre class="terminal">$ kwalify -f schema03.yaml document03b.yaml
286
- document03b.yaml#1: INVALID
287
- - [/2] key 'name' required but not found.
288
- - [/2] key 'naem' is not expected.
289
- - [/3] key 'mail' is not expected.
318
+ document03b.yaml#0: INVALID
319
+ - [/1] key 'name:' is required.
320
+ - [/1] key 'naem:' is undefined.
321
+ - [/2] key 'mail:' is undefined.
290
322
  </pre>
291
323
  <br>
292
324
 
@@ -299,23 +331,23 @@ document03b.yaml#1: INVALID
299
331
  <pre class="program">type: map
300
332
  mapping:
301
333
  company:
302
- type: text
334
+ type: str
303
335
  required: yes
304
336
  email:
305
- type: text
337
+ type: str
306
338
  employees:
307
339
  type: seq
308
340
  sequence:
309
341
  - type: map
310
342
  mapping:
311
343
  code:
312
- type: integer
344
+ type: int
313
345
  required: yes
314
346
  name:
315
- type: string
347
+ type: str
316
348
  required: yes
317
349
  email:
318
- type: string
350
+ type: str
319
351
  </pre>
320
352
  <a name="document04a.yaml"></a>
321
353
  <div class="program_caption">
@@ -333,7 +365,7 @@ employees:
333
365
  <div class="terminal_caption">
334
366
  validate</div>
335
367
  <pre class="terminal">$ kwalify -f schema04.yaml document04a.yaml
336
- document04a.yaml#1: valid.
368
+ document04a.yaml#0: valid.
337
369
  </pre>
338
370
  <a name="document04b.yaml"></a>
339
371
  <div class="program_caption">
@@ -351,9 +383,9 @@ employees:
351
383
  <div class="terminal_caption">
352
384
  validate</div>
353
385
  <pre class="terminal">$ kwalify -f schema04.yaml document04b.yaml
354
- document04b.yaml#1: INVALID
355
- - [/employees/1/code] integer type expected but got String.
356
- - [/employees/2] key 'mail' is not expected.
386
+ document04b.yaml#0: INVALID
387
+ - [/employees/0/code] 'A101': not a integer.
388
+ - [/employees/1] key 'mail:' is undefined.
357
389
  </pre>
358
390
  <br>
359
391
 
@@ -364,7 +396,7 @@ document04b.yaml#1: INVALID
364
396
  <dt class="dt3"><strong>
365
397
  <code>required:</code> </strong></dt>
366
398
  <dd class="dd3">
367
- Value is required (default is false).
399
+ Value is required when true (default is false).
368
400
  </dd>
369
401
  <dt class="dt3"><strong>
370
402
  <code>enum:</code> </strong></dt>
@@ -391,30 +423,50 @@ document04b.yaml#1: INVALID
391
423
  <dd class="dd3">
392
424
  Type of value. The followings are available:
393
425
  <ul type="circle">
394
- <li><code>string</code> (default)
426
+ <li><code>str</code>
395
427
  </li>
396
- <li><code>integer</code>
428
+ <li><code>int</code>
397
429
  </li>
398
430
  <li><code>float</code>
399
431
  </li>
400
- <li><code>number</code> (== integer or float)
432
+ <li><code>number</code> (== int or float)
401
433
  </li>
402
- <li><code>text</code> (== string or number)
434
+ <li><code>text</code> (== str or number)
403
435
  </li>
404
- <li><code>boolean</code>
436
+ <li><code>bool</code>
405
437
  </li>
406
438
  <li><code>date</code>
407
439
  </li>
408
440
  <li><code>time</code>
409
441
  </li>
442
+ <li><code>timestamp</code>
443
+ </li>
410
444
  <li><code>seq</code>
411
445
  </li>
412
446
  <li><code>map</code>
413
447
  </li>
414
- <li><code>object</code>
448
+ <li><code>scalar</code> (all but seq and map)
449
+ </li>
450
+ <li><code>any</code> (means any data)
415
451
  </li>
416
452
  </ul>
417
453
  </dd>
454
+ <dt class="dt3"><strong>
455
+ <code>range:</code> </strong></dt>
456
+ <dd class="dd3">
457
+ Range of value between max and min. Type <code>seq</code>, <code>map</code>, <code>bool</code> and <code>any</code> are not available with <code>range:</code>.
458
+ </dd>
459
+ <dt class="dt3"><strong>
460
+ <code>length:</code> </strong></dt>
461
+ <dd class="dd3">
462
+ Range of length of value between max and min. Only type <code>str</code> and <code>text</code> are available with <code>length:</code>.
463
+ </dd>
464
+ <dt class="dt3"><strong>
465
+ <code>assert:</code> </strong></dt>
466
+ <dd class="dd3">
467
+ String which represents validation expression. String should contain variable name <code>val</code> which repsents value.
468
+ (This is an experimental function.)
469
+ </dd>
418
470
  </dl>
419
471
  <a name="schema05.yaml"></a>
420
472
  <div class="program_caption">
@@ -424,16 +476,21 @@ sequence:
424
476
  - type: map
425
477
  mapping:
426
478
  name:
427
- #type: string # omittable
479
+ type: str
428
480
  required: yes
429
481
  email:
430
- #type: string # omittable
482
+ type: str
431
483
  required: yes
432
484
  pattern: /@/
485
+ password:
486
+ type: str
487
+ length: { max: 16, min: 8 }
433
488
  age:
434
- type: integer
489
+ type: int
490
+ range: { max: 30, min: 18 }
491
+ # or assert: 30 &lt;= val &amp;&amp; val &lt;= 18
435
492
  blood:
436
- #type: string # omittable
493
+ type: str
437
494
  enum:
438
495
  - A
439
496
  - B
@@ -441,92 +498,127 @@ sequence:
441
498
  - AB
442
499
  birth:
443
500
  type: date
501
+ memo:
502
+ type: any
444
503
  </pre>
445
504
  <a name="document05a.yaml"></a>
446
505
  <div class="program_caption">
447
506
  <code>document05a.yaml</code> : valid document example</div>
448
- <pre class="program">- name: foo
449
- email: foo@mail.com
450
- age: 20
451
- blood: A
452
- birth: 1985-01-01
453
- - name: bar
454
- email: bar@mail.net
455
- age: 25
456
- blood: AB
457
- birth: 1980-01-01
507
+ <pre class="program">- name: foo
508
+ email: foo@mail.com
509
+ password: xxx123456
510
+ age: 20
511
+ blood: A
512
+ birth: 1985-01-01
513
+ - name: bar
514
+ email: bar@mail.net
515
+ age: 25
516
+ blood: AB
517
+ birth: 1980-01-01
458
518
  </pre>
459
519
  <div class="terminal_caption">
460
520
  validate</div>
461
521
  <pre class="terminal">$ kwalify -f schema05.yaml document05a.yaml
462
- document05a.yaml#1: valid.
522
+ document05a.yaml#0: valid.
463
523
  </pre>
464
524
  <a name="document05b.yaml"></a>
465
525
  <div class="program_caption">
466
526
  <code>document05b.yaml</code> : invalid document example</div>
467
- <pre class="program">- name: foo
468
- email: foo(at)mail.com
469
- age: twenty
470
- blood: a
471
- birth: 1985-01-01
527
+ <pre class="program">- name: foo
528
+ email: foo(at)mail.com
529
+ password: xxx123
530
+ age: twenty
531
+ blood: a
532
+ birth: 1985-01-01
472
533
  - given-name: bar
473
534
  family-name: Bar
474
- email: bar@mail.net
475
- age: 25
476
- blood: AB
477
- birth: 1980/01/01
535
+ email: bar@mail.net
536
+ age: 15
537
+ blood: AB
538
+ birth: 1980/01/01
478
539
  </pre>
479
540
  <div class="terminal_caption">
480
541
  validate</div>
481
542
  <pre class="terminal">$ kwalify -f schema05.yaml document05b.yaml
482
- document05b.yaml#1: INVALID
483
- - [/1/blood] 'a' is invalid enum value.
484
- - [/1/age] integer type expected but got String.
485
- - [/1/email] 'foo(at)mail.com' is not matched to pattern /@/.
486
- - [/2] key 'name' required but not found.
487
- - [/2] key 'family-name' is not expected.
488
- - [/2] key 'given-name' is not expected.
489
- - [/2/birth] date type expected but got String.
543
+ document05b.yaml#0: INVALID
544
+ - [/0/blood] 'a': invalid blood value.
545
+ - [/0/age] 'twenty': not a integer.
546
+ - [/0/password] 'xxx123': too short (length 6 &lt; min 8).
547
+ - [/0/email] 'foo(at)mail.com': not matched to pattern /@/.
548
+ - [/1] key 'name:' is required.
549
+ - [/1] key 'family-name:' is undefined.
550
+ - [/1] key 'given-name:' is undefined.
551
+ - [/1/birth] '1980/01/01': not a date.
552
+ - [/1/age] '15': too small (&lt; min 18).
490
553
  </pre>
491
554
  <br>
492
555
 
493
556
 
494
- <a name="schema-block"></a>
495
- <h3 class="section2">Validator with Block</h3>
496
- <p><strong>Notice: This is an experimental feature.</strong>
497
- </p>
498
- <p><code>Kwalify::Validator.new()</code> method can take a block which is invoked when validation.
557
+ <a name="schema-hook"></a>
558
+ <h3 class="section2">Validator#validator_hook()</h3>
559
+ <p>You can extend Kwalify::Validator class and override Kwalify::Validator#validator_hook() method.
560
+ This method is called by Kwalify::Validator#validate().
499
561
  </p>
562
+ <a name="schema06.yaml"></a>
563
+ <div class="program_caption">
564
+ schema06.yaml : 'name:' is important.</div>
565
+ <pre class="program">type: map
566
+ mapping:
567
+ questionnaires:
568
+ type: seq
569
+ sequence:
570
+ - type: map
571
+ <strong>name: Questionnaire</strong>
572
+ mapping:
573
+ name:
574
+ type: str
575
+ required: yes
576
+ answer:
577
+ type: str
578
+ required: yes
579
+ enum:
580
+ - good
581
+ - not bad
582
+ - bad
583
+ reason:
584
+ type: str
585
+ </pre>
500
586
  <a name="validate06.rb"></a>
501
587
  <div class="program_caption">
502
- <code>validate06.rb</code> : validate script</div>
588
+ validate06.rb : validate script</div>
503
589
  <pre class="program">#!/usr/bin/env ruby
504
590
 
505
591
  require 'kwalify'
506
592
  require 'yaml'
507
593
 
508
- ## load schema definition
509
- schema_filename = 'schema06.yaml'
510
- schema_str = File.read(schema_filename)
511
- schema_hash = YAML.load(schema_str)
512
-
513
- ## create validator with a block
514
- validator = Kwalify::Validator.new(schema_hash) <strong>{ |schema, data, errors, path|</strong>
515
- case <strong>schema.name</strong> ## refer schema name
516
- when <strong>"USERNAME"</strong>
517
- username = data
518
- if username.length &gt; 16
519
- errors &lt;&lt; Kwalify::ValidationError.new("too long (&gt;16).", path, schema)
520
- end
521
- when <strong>"AGE"</strong>
522
- age = data
523
- if age &lt; 13
524
- errors &lt;&lt; Kwalify::ValidationError.new("too young (&lt;13).", path, schema)
525
- elsif age &gt;= 60
526
- errors &lt;&lt; Kwalify::ValidationError.new("too old (&gt;=60).", path, schema)
594
+ ## validator class for questionnaires
595
+ class QuestionnairesValidator &lt; Kwalify::Validator
596
+
597
+ ## load schema definition
598
+ @@schema = YAML.load_file('schema06.yaml')
599
+
600
+ def initialize()
601
+ super(@@schema)
602
+ end
603
+
604
+ ## hook method called by Validator#validate()
605
+ <strong>def validate_hook(value, rule, path, errors)</strong>
606
+ <strong>case rule.name</strong>
607
+ <strong>when 'Questionnaire'</strong>
608
+ if value['answer'] == 'bad'
609
+ reason = value['reason']
610
+ if !reason || reason.empty?
611
+ msg = "reason is required when answer is 'bad'."
612
+ errors &lt;&lt; Kwalify::ValidationError.new(msg, path)
613
+ end
614
+ end
527
615
  end
528
616
  end
529
- <strong>}</strong>
617
+
618
+ end
619
+
620
+ ## create validator
621
+ validator = QuestionnairesValidator.new
530
622
 
531
623
  ## load YAML document
532
624
  input = ARGF.read()
@@ -540,40 +632,22 @@ else
540
632
  puts "*** INVALID!"
541
633
  errors.each do |error|
542
634
  # error.class == Kwalify::ValidationError
543
- puts " - #{error.message}"
635
+ puts " - [#{error.path}] : #{error.message}"
544
636
  end
545
637
  end
546
638
  </pre>
547
- <a name="schema06.yaml"></a>
548
- <div class="program_caption">
549
- <code>schema06.yaml</code> : 'name:' is important.</div>
550
- <pre class="program">type: map
551
- mapping:
552
- members:
553
- type: seq
554
- sequence:
555
- - type: map
556
- mapping:
557
- username:
558
- required: yes
559
- <strong>name:</strong> <strong>USERNAME</strong>
560
- email:
561
- required: yes
562
- pattern: /@/
563
- age:
564
- type: integer
565
- <strong>name:</strong> <strong>AGE</strong>
566
- </pre>
567
639
  <a name="document06a.yaml"></a>
568
640
  <div class="program_caption">
569
641
  <code>document06a.yaml</code> : valid document example</div>
570
- <pre class="program">members:
571
- - username: foo
572
- email: foo@mail.com
573
- age: 19
574
- - username: bar
575
- email: bar@mail.org
576
- age: 21
642
+ <pre class="program">questionnaires:
643
+ - name: Foo
644
+ answer: good
645
+ reason: I like this style.
646
+ - name: Bar
647
+ answer: not bad
648
+ - name: Baz
649
+ answer: bad
650
+ reason: I don't like this style.
577
651
  </pre>
578
652
  <div class="terminal_caption">
579
653
  validate</div>
@@ -583,20 +657,80 @@ Valid.
583
657
  <a name="document06b.yaml"></a>
584
658
  <div class="program_caption">
585
659
  <code>document06b.yaml</code> : invalid document example</div>
586
- <pre class="program">members:
587
- - username: toooooooloooooong
588
- email: foo@mail.com
589
- age: 20
590
- - username: bar
591
- email: bar@mail.org
592
- age: 12
660
+ <pre class="program">questionnaires:
661
+ - name: Foo
662
+ answer: good
663
+ - name: Bar
664
+ answer: bad
665
+ - name: Baz
666
+ answer: not bad
593
667
  </pre>
594
668
  <div class="terminal_caption">
595
669
  validate</div>
596
670
  <pre class="terminal">$ ruby validate06.rb document06b.yaml
597
671
  *** INVALID!
598
- - [/members/1/username] too long (&gt;16).
599
- - [/members/2/age] too young (&lt;13).
672
+ - [/questionnaires/1] : reason is required when answer is 'bad'.
673
+ </pre>
674
+ <br>
675
+
676
+
677
+ <a name="schema-block"></a>
678
+ <h3 class="section2">Validator with Block</h3>
679
+ <p><strong>Notice: This is an experimental feature.</strong>
680
+ </p>
681
+ <p><code>Kwalify::Validator.new()</code> method can take a block which is invoked when validation.
682
+ </p>
683
+ <a name="validate07.rb"></a>
684
+ <div class="program_caption">
685
+ <code>validate07.rb</code> : validate script</div>
686
+ <pre class="program">#!/usr/bin/env ruby
687
+
688
+ require 'kwalify'
689
+ require 'yaml'
690
+
691
+ ## load schema definition
692
+ schema = YAML.load_file('schema06.yaml')
693
+
694
+ ## create validator for questionnaires
695
+ validator = Kwalify::Validator.new(schema) <strong>{ |value, rule, path, errors|</strong>
696
+ <strong>case rule.name</strong>
697
+ <strong>when 'Questionnaire'</strong>
698
+ if value['answer'] == 'bad'
699
+ reason = value['reason']
700
+ if !reason || reason.empty?
701
+ msg = "reason is required when answer is 'bad'."
702
+ errors &lt;&lt; Kwalify::ValidationError.new(msg, path)
703
+ end
704
+ end
705
+ end
706
+ <strong>}</strong>
707
+
708
+ ## load YAML document
709
+ input = ARGF.read()
710
+ document = YAML.load(input)
711
+
712
+ ## validate
713
+ errors = validator.validate(document)
714
+ if errors.empty?
715
+ puts "Valid."
716
+ else
717
+ puts "*** INVALID!"
718
+ errors.each do |error|
719
+ # error.class == Kwalify::ValidationError
720
+ puts " - [#{error.path}] : #{error.message}"
721
+ end
722
+ end
723
+ </pre>
724
+ <div class="terminal_caption">
725
+ validate</div>
726
+ <pre class="terminal">$ ruby validate07.rb document06a.yaml
727
+ Valid.
728
+ </pre>
729
+ <div class="terminal_caption">
730
+ validate</div>
731
+ <pre class="terminal">$ ruby validate07.rb document06b.yaml
732
+ *** INVALID!
733
+ - [/questionnaires/1] : reason is required when answer is 'bad'.
600
734
  </pre>
601
735
  <br>
602
736
 
@@ -620,7 +754,7 @@ mapping:
620
754
  "email":
621
755
  pattern: /@/
622
756
  "age":
623
- type: integer
757
+ type: int
624
758
  "birth":
625
759
  type: date
626
760
  </pre>
@@ -635,7 +769,7 @@ mapping:
635
769
  "email":
636
770
  pattern: /@/
637
771
  "age":
638
- type: integer
772
+ type: int
639
773
  "birth":
640
774
  type: date
641
775
  </pre>
@@ -655,7 +789,7 @@ sequence:
655
789
  type: map
656
790
  mapping:
657
791
  "given-name": <strong>&amp;name</strong>
658
- type: string
792
+ type: str
659
793
  required: yes
660
794
  "family-name": <strong>*name</strong>
661
795
  "post":
@@ -691,7 +825,7 @@ sequence:
691
825
  <div class="terminal_caption">
692
826
  validate</div>
693
827
  <pre class="terminal">$ kwalify -f schema12.yaml document12a.yaml
694
- document12a.yaml#1: valid.
828
+ document12a.yaml#0: valid.
695
829
  </pre>
696
830
  <br>
697
831