kwalify 0.1.0 → 0.2.0

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.
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