kwalify 0.4.1 → 0.5.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,7 +1,18 @@
1
1
  .=title: ChangeLog
2
- .?release: $Release: 0.4.1 $
3
- .?lastupdate: $Date$
4
- .?version: $Rev$
2
+ .?release: $Release: 0.5.0 $
3
+ .?lastupdate: $Date: 2005-12-17 13:49:16 +0900 (Sat, 17 Dec 2005) $
4
+ .?version: $Rev: 42 $
5
+
6
+ .: 2005-12-17 (release 0.5.0)
7
+ .* Enhances:
8
+ .- Meta-validation check for 'max < min', 'max-ex <= min-ex', and so on.
9
+ .- Many test-cases are added
10
+ .* Changes:
11
+ .- 'Parser' class is renamed to 'YamlParser'
12
+ .- 'PlainParser' class is renamed to 'PlainYamlParser'
13
+ .- YamlParser#set_error_linenums() is renamed to set_errors_linenum()
14
+ .- ValidatorError#<=> added
15
+ .- ParseError class is renamed to YamlSyntaxError
5
16
 
6
17
  .: 2005-10-26 (release 0.4.1)
7
18
  .* Bugfix:
data/README.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  .=title: README
2
- .?version: $Rev: 18 $
3
- .?lastupdate: $Date: 2005-09-25 22:36:35 +0900 (Sun, 25 Sep 2005) $
4
- .?release: $Release: 0.4.1 $
2
+ .?version: $Rev: 41 $
3
+ .?lastupdate: $Date: 2005-11-22 03:24:54 +0900 (Tue, 22 Nov 2005) $
4
+ .?release: $Release: 0.5.0 $
5
5
 
6
6
 
7
7
  .$ About Kwalify
@@ -1,24 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  ###
4
- ### $Rev: 12 $
5
- ### $Release: 0.4.1 $
4
+ ### $Rev: 42 $
5
+ ### $Release: 0.5.0 $
6
6
  ### copyright(c) 2005 kuwata-lab all rights reserved.
7
7
  ###
8
8
 
9
9
  require 'kwalify'
10
- require 'kwalify/main-program'
11
-
10
+ require 'kwalify/main'
12
11
 
13
12
  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
24
- end
13
+ Kwalify::Main.main(command, ARGV)
@@ -2,7 +2,7 @@
2
2
  <html>
3
3
  <head>
4
4
  <meta http-equiv="Content-Type" content="text/html">
5
- <title>Kwalify Users' Guide</title>
5
+ <title>Kwalify Users' Guide (for Ruby and Java)</title>
6
6
  <meta name="author" content="makoto kuwata &lt;kwa(at)kuwata-lab.com&gt;">
7
7
  <meta name="generator" content="kwaser">
8
8
  <meta http-equiv="Content-Style-Type" content="text/css">
@@ -12,18 +12,18 @@
12
12
 
13
13
  <div class="mainbody">
14
14
 
15
- <div align="left"><h1>Kwalify Users' Guide</h1></div>
15
+ <div align="left"><h1>Kwalify Users' Guide (for Ruby and Java)</h1></div>
16
16
  <div align="left">
17
17
  makoto kuwata &lt;kwa(at)kuwata-lab.com&gt;<br>
18
- last update: $Date: 2005-10-26 11:38:26 +0900 (Wed, 26 Oct 2005) $<br>
18
+ last update: $Date: 2005-12-17 13:49:16 +0900 (Sat, 17 Dec 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 and JSON document.
24
24
  </p>
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.
25
+ <p>You know "80-20 rule" known as Pareto Law, don't you? 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
27
  This rule is more aggressive and cost-effective than Pareto Law. The rule is named as "Levi's Law".
28
28
  </p>
29
29
  <div align="center">
@@ -54,7 +54,7 @@ This rule is more aggressive and cost-effective than Pareto Law. The rule is nam
54
54
  </tr>
55
55
  </table>
56
56
  </div>
57
- <p>Kwalify is very small and in fact very poor compared to RelaxNG or XML Schema.
57
+ <p>Kwalify is small and in fact poorer than RelaxNG or XML Schema.
58
58
  I hope you extend/customize Kwalify for your own way.
59
59
  </p>
60
60
  Table of Contents:
@@ -80,7 +80,7 @@ Table of Contents:
80
80
  </li>
81
81
  <li><a href="#schema-map-of-seq">Mapping of Sequence</a>
82
82
  </li>
83
- <li><a href="#schema-rules">Rule and Constraint</a>
83
+ <li><a href="#schema-rules">Rule and Entry</a>
84
84
  </li>
85
85
  <li><a href="#schema-unique">Unique constraint</a>
86
86
  </li>
@@ -121,11 +121,19 @@ Table of Contents:
121
121
  <h3 class="section2">Usage in Command-Line</h3>
122
122
  <div class="terminal_caption">
123
123
  usage1: validate YAML document in command-line</div>
124
- <pre class="terminal">$ kwalify -f schema.yaml document.yaml [document2.yaml ...]
124
+ <pre class="terminal">### kwalify-ruby
125
+ $ kwalify -f schema.yaml document.yaml [document2.yaml ...]
126
+
127
+ ### kwalify-java
128
+ $ java -classpath kwalify.jar kwalify.Main -f schema.yaml document.yaml [document2.yaml ...]
125
129
  </pre>
126
130
  <div class="terminal_caption">
127
131
  usage2: validate schema definition in command-line</div>
128
- <pre class="terminal">$ kwalify -m schema.yaml [schema2.yaml ...]
132
+ <pre class="terminal">### kwalify-ruby
133
+ $ kwalify -m schema.yaml [schema2.yaml ...]
134
+
135
+ ### kwalify-java
136
+ $ java -classpath kwalify.jar kwalify.Main -m schema.yaml [schema2.yaml ...]
129
137
  </pre>
130
138
  <p>Command-line options:
131
139
  </p>
@@ -173,6 +181,8 @@ usage2: validate schema definition in command-line</div>
173
181
 
174
182
  <a name="usage2"></a>
175
183
  <h3 class="section2">Usage in Ruby Script</h3>
184
+ <p>The followings are example scripts for Ruby.
185
+ </p>
176
186
  <div class="program_caption">
177
187
  validate YAML document in Ruby script</div>
178
188
  <pre class="program">require 'kwalify'
@@ -206,14 +216,51 @@ document = parser.parse()
206
216
  ## validate document and show errors
207
217
  error_list = validator.validate(document)
208
218
  unless error_list.empty?
209
- parser.set_error_linenums(error_list) # set linenum on error
210
- error_list.sort { |e1, e2| e1.linenum &lt;=&gt; e2.linenum }.each do |error|
219
+ parser.set_errors_linenum(error_list) # set linenum on error
220
+ error_list.sort.each do |error|
211
221
  puts "(line %d)[%s] %s" % [error.linenum, error.path, error.message]
212
222
  end
213
223
  end
214
224
  </pre>
215
225
  <p>Kwalify's YAML parser is experimental. You should notice that Kwalify's YAML parser is limited only for basic syntax of YAML.
216
226
  </p>
227
+ <p>The followings are example programs of Java.
228
+ </p>
229
+ <div class="program_caption">
230
+ validate YAML document and show linenumber on where error is found.</div>
231
+ <pre class="program">import kwalify.*;
232
+
233
+ public class Test {
234
+
235
+ public static void main(String[] args) throws Exception {
236
+ // read schema
237
+ String schema_str = Util.readFile("schema.yaml");
238
+ Object schema = new YamlParser(schema_str).parse();
239
+
240
+ // read document file
241
+ String document_str = Util.readFile("document.yaml");
242
+ YamlParser parser = new YamlParser(document_str);
243
+ Object document = parser.parse();
244
+
245
+ // create validator and validate
246
+ Validator validator = new Validator(schema);
247
+ List errors = validator.validate(document);
248
+
249
+ // show errors
250
+ if (errors != null &amp;&amp; errors.size() &gt; 0) {
251
+ parser.setErrorsLineNumber(errors);
252
+ Collections.sort(errors);
253
+ for (Iterator it = errors.iterator(); it.hasNext(); ) {
254
+ ValidationException error = (ValidationException)it.next();
255
+ int linenum = error.getLineNumber();
256
+ String path = error.getPath();
257
+ String mesg = error.getMessage();
258
+ System.out.println("- " + linenum + ": [" + path + "] " + mesg);
259
+ }
260
+ }
261
+ }
262
+ }
263
+ </pre>
217
264
  <br>
218
265
 
219
266
 
@@ -430,8 +477,10 @@ document04b.yaml#0: INVALID
430
477
 
431
478
 
432
479
  <a name="schema-rules"></a>
433
- <h3 class="section2">Rule and Constraint</h3>
434
- <p>The followings are constraints.
480
+ <h3 class="section2">Rule and Entry</h3>
481
+ <p>Rule is set of entries. Entry usually represents constraint outside of a few exceptions.
482
+ </p>
483
+ <p>The followings are constraint entries.
435
484
  </p>
436
485
  <dl class="dl3">
437
486
  <dt class="dt3"><strong>
@@ -450,16 +499,6 @@ document04b.yaml#0: INVALID
450
499
  Specifies regular expression pattern of value.
451
500
  </dd>
452
501
  <dt class="dt3"><strong>
453
- <code>name:</code> </strong></dt>
454
- <dd class="dd3">
455
- Name of schema.
456
- </dd>
457
- <dt class="dt3"><strong>
458
- <code>desc:</code> </strong></dt>
459
- <dd class="dd3">
460
- Description. This is not used for validation.
461
- </dd>
462
- <dt class="dt3"><strong>
463
502
  <code>type:</code> </strong></dt>
464
503
  <dd class="dd3">
465
504
  Type of value. The followings are available:
@@ -517,7 +556,7 @@ document04b.yaml#0: INVALID
517
556
  <code>assert:</code> </strong></dt>
518
557
  <dd class="dd3">
519
558
  String which represents validation expression. String should contain variable name <code>val</code> which repsents value.
520
- (This is an experimental function.)
559
+ (This is an experimental function and supported only Kwartz-ruby).
521
560
  </dd>
522
561
  <dt class="dt3"><strong>
523
562
  <code>unique:</code> </strong></dt>
@@ -525,40 +564,55 @@ document04b.yaml#0: INVALID
525
564
  Value is unique for mapping or sequence. See the next subsection for detail.
526
565
  </dd>
527
566
  </dl>
528
- <p>A group of constraints is called "rule". For example, constraints which are element value of 'sequence:' or 'mapping:' are rules.
567
+ <p>The followings are non-constraint entries.
568
+ </p>
569
+ <dl class="dl3">
570
+ <dt class="dt3"><strong>
571
+ <code>name:</code> </strong></dt>
572
+ <dd class="dd3">
573
+ Name of schema.
574
+ </dd>
575
+ <dt class="dt3"><strong>
576
+ <code>desc:</code> </strong></dt>
577
+ <dd class="dd3">
578
+ Description. This is not used for validation.
579
+ </dd>
580
+ </dl>
581
+ <p>Rule contains 'type:' entry. 'sequence:' entry takes a list of rule. 'mapping:' entry takes a hash which values are rules.
529
582
  </p>
530
583
  <a name="schema05.yaml"></a>
531
584
  <div class="program_caption">
532
- <code>schema05.yaml</code> : rules examples</div>
533
- <pre class="program">type: seq
585
+ <code>schema05.yaml</code> : rule examples</div>
586
+ <pre class="program">type: seq # new rule
534
587
  sequence:
535
- - type: map
588
+ -
589
+ type: map # new rule
536
590
  mapping:
537
591
  name:
538
- type: str
592
+ type: str # new rule
539
593
  required: yes
540
594
  email:
541
- type: str
595
+ type: str # new rule
542
596
  required: yes
543
597
  pattern: /@/
544
598
  password:
545
- type: str
599
+ type: text # new rule
546
600
  length: { max: 16, min: 8 }
547
601
  age:
548
- type: int
602
+ type: int # new rule
549
603
  range: { max: 30, min: 18 }
550
604
  # or assert: 18 &lt;= val &amp;&amp; val &lt;= 30
551
605
  blood:
552
- type: str
606
+ type: str # new rule
553
607
  enum:
554
608
  - A
555
609
  - B
556
610
  - O
557
611
  - AB
558
612
  birth:
559
- type: date
613
+ type: date # new rule
560
614
  memo:
561
- type: any
615
+ type: any # new rule
562
616
  </pre>
563
617
  <a name="document05a.yaml"></a>
564
618
  <div class="program_caption">
@@ -615,15 +669,15 @@ document05b.yaml#0: INVALID
615
669
 
616
670
  <a name="schema-unique"></a>
617
671
  <h3 class="section2">Unique constraint</h3>
618
- <p>'<code>unique:</code>' constraint is available with elements of sequence or mapping.
672
+ <p>'<code>unique:</code>' constraint entry is available with elements of sequence or mapping.
619
673
  This is equivalent to unique key or primary key of RDBMS.
620
674
  </p>
621
- <p>Type of a rule which has '<code>unique:</code>' constraint must be scalar (str, int, float, ...).
675
+ <p>Type of rule which has '<code>unique:</code>' entry must be scalar (str, int, float, ...).
622
676
  Type of parent rule must be sequence or mapping.
623
677
  </p>
624
678
  <a name="schema06.yaml"></a>
625
679
  <div class="program_caption">
626
- <code>schema06.yaml</code> : unique constraint with mapping and sequence</div>
680
+ <code>schema06.yaml</code> : unique constraint entry with mapping and sequence</div>
627
681
  <pre class="program">type: seq
628
682
  sequence:
629
683
  - type: map
@@ -697,12 +751,12 @@ document06b.yaml#0: INVALID
697
751
 
698
752
  <a name="schema-hook"></a>
699
753
  <h3 class="section2">Validator#validator_hook()</h3>
700
- <p>You can extend Kwalify::Validator class and override Kwalify::Validator#validator_hook() method.
701
- This method is called by Kwalify::Validator#validate().
754
+ <p>You can extend Kwalify::Validator class (Ruby) or kwalify.Validator class (Java), and override Kwalify::Validator#validator_hook() method (Ruby) or kwalify.Validator#validateHook() method (Java).
755
+ This method is called by Kwalify::Validator#validate() (Ruby) or kwalify.Validator#validate() (Java).
702
756
  </p>
703
- <a name="schema07.yaml"></a>
757
+ <a name="answers-schema.yaml"></a>
704
758
  <div class="program_caption">
705
- schema07.yaml : 'name:' is important.</div>
759
+ answers-schema.yaml : 'name:' is important.</div>
706
760
  <pre class="program">type: map
707
761
  mapping:
708
762
  answers:
@@ -724,9 +778,9 @@ mapping:
724
778
  reason:
725
779
  type: str
726
780
  </pre>
727
- <a name="validate07.rb"></a>
781
+ <a name="answers-validator.rb"></a>
728
782
  <div class="program_caption">
729
- validate07.rb : validate script</div>
783
+ answers-validator.rb : validate script for Ruby</div>
730
784
  <pre class="program">#!/usr/bin/env ruby
731
785
 
732
786
  require 'kwalify'
@@ -736,7 +790,7 @@ require 'yaml'
736
790
  class AnswersValidator &lt; Kwalify::Validator
737
791
 
738
792
  ## load schema definition
739
- @@schema = YAML.load_file('schema07.yaml')
793
+ @@schema = YAML.load_file('answers-schema.yaml')
740
794
 
741
795
  def initialize()
742
796
  super(@@schema)
@@ -792,7 +846,7 @@ end
792
846
  </pre>
793
847
  <div class="terminal_caption">
794
848
  validate</div>
795
- <pre class="terminal">$ ruby validate07.rb document07a.yaml
849
+ <pre class="terminal">$ ruby answers-validator.rb document07a.yaml
796
850
  Valid.
797
851
  </pre>
798
852
  <a name="document07b.yaml"></a>
@@ -800,18 +854,141 @@ Valid.
800
854
  <code>document07b.yaml</code> : invalid document example</div>
801
855
  <pre class="program">answers:
802
856
  - name: Foo
803
- answer: good
857
+ answer: good
804
858
  - name: Bar
805
- answer: bad
859
+ answer: bad
806
860
  - name: Baz
807
- answer: not bad
861
+ answer: not bad
808
862
  </pre>
809
863
  <div class="terminal_caption">
810
864
  validate</div>
811
- <pre class="terminal">$ ruby validate07.rb document07b.yaml
865
+ <pre class="terminal">$ ruby answers-validator.rb document07b.yaml
812
866
  *** INVALID!
813
867
  - [/answers/1] : reason is required when answer is 'bad'.
814
868
  </pre>
869
+ <p>You can validate some document by a Validator instance because Validator class and Validator#validate() method are stateless. If you use instance variables in custom validator_hook() method, it becomes to be stateful.
870
+ </p>
871
+ <p>Here is a Java program equivarent to 'answers-validator.rb'.
872
+ </p>
873
+ <a name="AnswersValidator.java"></a>
874
+ <div class="program_caption">
875
+ AnswersValidator.java : validate program for Java</div>
876
+ <pre class="program">import kwalify.Validator;
877
+ import kwalify.Rule;
878
+ import kwalify.Util;
879
+ import kwalify.YamlUtil;
880
+ import kwalify.YamlParser;
881
+ import kwalify.SyntaxException;
882
+ import kwalify.ValidationException;
883
+
884
+ import java.util.*;
885
+ import java.io.IOException;
886
+
887
+
888
+ /**
889
+ * validator class for answers
890
+ */
891
+ public class AnswersValidator extends Validator {
892
+
893
+ /** schema string */
894
+ private static final String SCHEMA = ""
895
+ + "type: map\n"
896
+ + "mapping:\n"
897
+ + " answers:\n"
898
+ + " type: seq\n"
899
+ + " sequence:\n"
900
+ + " - type: map\n"
901
+ + " name: Answer\n"
902
+ + " mapping:\n"
903
+ + " name:\n"
904
+ + " type: str\n"
905
+ + " required: yes\n"
906
+ + " answer:\n"
907
+ + " type: str\n"
908
+ + " required: yes\n"
909
+ + " enum:\n"
910
+ + " - good\n"
911
+ + " - not bad\n"
912
+ + " - bad\n"
913
+ + " reason:\n"
914
+ + " type: str\n"
915
+ ;
916
+
917
+ /** schema object */
918
+ private static Map schema = null;
919
+ static {
920
+ try {
921
+ schema = (Map)YamlUtil.load(SCHEMA);
922
+ } catch (SyntaxException ex) {
923
+ assert false;
924
+ }
925
+ }
926
+
927
+ /** construnctor */
928
+ public AnswersValidator() {
929
+ super(schema);
930
+ }
931
+
932
+ /** hook method called by Validator#validate() */
933
+ protected void validateHook(Object value, Rule rule, String path, List errors) {
934
+ String rule_name = rule.getName();
935
+ if (rule_name != null &amp;&amp; rule_name.equals("Answer")) {
936
+ assert value instanceof Map;
937
+ Map val = (Map)value;
938
+ assert val.get("answer") != null;
939
+ if (val.get("answer").equals("bad")) {
940
+ String reason = (String)val.get("reason");
941
+ if (reason == null || reason.length() == 0) {
942
+ String msg = "reason is required when answer is 'bad'.";
943
+ errors.add(new ValidationException(msg, path));
944
+ }
945
+ }
946
+ }
947
+ }
948
+
949
+ /** main program */
950
+ public static void main(String[] args) throws IOException, SyntaxException {
951
+ // create validator
952
+ Validator validator = new AnswersValidator();
953
+
954
+ // load YAML document
955
+ String input;
956
+ if (args.length &gt; 0) {
957
+ input = Util.readFile(args[0]);
958
+ } else {
959
+ input = Util.readInputStream(System.in);
960
+ }
961
+ YamlParser parser = new YamlParser(input);
962
+ Object document = parser.parse();
963
+
964
+ // validate and show errors
965
+ List errors = validator.validate(document);
966
+ if (errors == null || errors.size() == 0) {
967
+ System.out.println("Valid.");
968
+ } else {
969
+ System.out.println("*** INVALID!");
970
+ parser.setErrorsLineNumber(errors);
971
+ Collections.sort(errors);
972
+ for (Iterator it = errors.iterator(); it.hasNext(); ) {
973
+ ValidationException error = (ValidationException)it.next();
974
+ int linenum = error.getLineNumber();
975
+ String path = error.getPath();
976
+ String mesg = error.getMessage();
977
+ String s = "- line " + linenum + ": [" + path + "] " + mesg;
978
+ System.out.println(s);
979
+ }
980
+ }
981
+ }
982
+ }
983
+ </pre>
984
+ <div class="terminal_caption">
985
+ validate</div>
986
+ <pre class="terminal">$ java -classpath kwalify.jar AnswersValidator document07a.yaml
987
+ Valid.
988
+ $ java -classpath kwalify.jar AnswersValidator document07b.yaml
989
+ *** INVALID!
990
+ - line 4: [/answers/1] reason is required when answer is 'bad'.
991
+ </pre>
815
992
  <br>
816
993
 
817
994
 
@@ -830,7 +1007,7 @@ require 'kwalify'
830
1007
  require 'yaml'
831
1008
 
832
1009
  ## load schema definition
833
- schema = YAML.load_file('schema06.yaml')
1010
+ schema = YAML.load_file('answers-schema.yaml')
834
1011
 
835
1012
  ## create validator for answers
836
1013
  validator = Kwalify::Validator.new(schema) <strong>{ |value, rule, path, errors|</strong>
@@ -865,14 +1042,13 @@ end
865
1042
  <div class="terminal_caption">
866
1043
  validate</div>
867
1044
  <pre class="terminal">$ ruby validate08.rb document07a.yaml
868
- *** INVALID!
869
- - [/] : not a sequence.
1045
+ Valid.
870
1046
  </pre>
871
1047
  <div class="terminal_caption">
872
1048
  validate</div>
873
1049
  <pre class="terminal">$ ruby validate08.rb document07b.yaml
874
1050
  *** INVALID!
875
- - [/] : not a sequence.
1051
+ - [/answers/1] : reason is required when answer is 'bad'.
876
1052
  </pre>
877
1053
  <br>
878
1054
 
@@ -974,7 +1150,7 @@ document12a.yaml#0: valid.
974
1150
  <a name="document12b.yaml"></a>
975
1151
  <div class="program_caption">
976
1152
  <code>document12b.yaml</code> : invalid JSON document example</div>
977
- <pre class="program">{
1153
+ <pre class="program">{
978
1154
  "mail": "foo@mail.com",
979
1155
  "age": twenty,
980
1156
  "gender": "X",
@@ -1125,11 +1301,11 @@ tmp.update(a1) # merge
1125
1301
  tmp["A"] = 15 # override
1126
1302
  tmp["C"] = 30 # add
1127
1303
  </pre>
1128
- <p>This feature allows Kwalify to merge rules.
1304
+ <p>This feature allows Kwalify to merge rule entries.
1129
1305
  </p>
1130
1306
  <a name="schema15.yaml"></a>
1131
1307
  <div class="program_caption">
1132
- <code>schema15.yaml</code> : default rule example</div>
1308
+ <code>schema15.yaml</code> : merging rule entries example</div>
1133
1309
  <pre class="program">type: map
1134
1310
  mapping:
1135
1311
  "group":
@@ -1146,11 +1322,11 @@ mapping:
1146
1322
  type: map
1147
1323
  mapping:
1148
1324
  "name":
1149
- <strong>&lt;&lt;: *name # merge</strong>
1150
- <strong>length: { max: 16 } # override</strong>
1325
+ <strong>&lt;&lt;: *name</strong> # merge
1326
+ <strong>length: { max: 16 }</strong> # override
1151
1327
  "email":
1152
- <strong>&lt;&lt;: *email # merge</strong>
1153
- <strong>required: yes # add</strong>
1328
+ <strong>&lt;&lt;: *email</strong> # merge
1329
+ <strong>required: yes</strong> # add
1154
1330
  </pre>
1155
1331
  <a name="document15a.yaml"></a>
1156
1332
  <div class="program_caption">