dc-kwalify 0.7.2

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.
Files changed (209) hide show
  1. data/CHANGES.txt +252 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.txt +61 -0
  4. data/bin/kwalify +13 -0
  5. data/contrib/inline-require +179 -0
  6. data/contrib/kwalify +4160 -0
  7. data/doc/docstyle.css +188 -0
  8. data/doc/img/fig01.png +0 -0
  9. data/doc/users-guide.html +2050 -0
  10. data/doc-api/classes/CommandOptionError.html +184 -0
  11. data/doc-api/classes/CommandOptionParser.html +325 -0
  12. data/doc-api/classes/Kwalify/AssertionError.html +148 -0
  13. data/doc-api/classes/Kwalify/BaseError.html +297 -0
  14. data/doc-api/classes/Kwalify/BaseParser.html +461 -0
  15. data/doc-api/classes/Kwalify/CommandOptionError.html +168 -0
  16. data/doc-api/classes/Kwalify/ErrorHelper.html +223 -0
  17. data/doc-api/classes/Kwalify/HashInterface.html +118 -0
  18. data/doc-api/classes/Kwalify/Json.html +105 -0
  19. data/doc-api/classes/Kwalify/KwalifyError.html +111 -0
  20. data/doc-api/classes/Kwalify/Main.html +339 -0
  21. data/doc-api/classes/Kwalify/MetaValidator.html +448 -0
  22. data/doc-api/classes/Kwalify/Parser.html +155 -0
  23. data/doc-api/classes/Kwalify/PlainYamlParser/Alias.html +165 -0
  24. data/doc-api/classes/Kwalify/PlainYamlParser.html +523 -0
  25. data/doc-api/classes/Kwalify/Rule.html +433 -0
  26. data/doc-api/classes/Kwalify/SchemaError.html +148 -0
  27. data/doc-api/classes/Kwalify/SyntaxError.html +185 -0
  28. data/doc-api/classes/Kwalify/Types.html +302 -0
  29. data/doc-api/classes/Kwalify/Util/HashLike.html +246 -0
  30. data/doc-api/classes/Kwalify/Util/OrderedHash.html +330 -0
  31. data/doc-api/classes/Kwalify/Util.html +390 -0
  32. data/doc-api/classes/Kwalify/ValidationError.html +148 -0
  33. data/doc-api/classes/Kwalify/Validator.html +381 -0
  34. data/doc-api/classes/Kwalify/Yaml/Parser.html +1538 -0
  35. data/doc-api/classes/Kwalify/Yaml.html +194 -0
  36. data/doc-api/classes/Kwalify/YamlParser.html +542 -0
  37. data/doc-api/classes/Kwalify/YamlSyntaxError.html +119 -0
  38. data/doc-api/classes/Kwalify.html +292 -0
  39. data/doc-api/classes/Test/Unit.html +101 -0
  40. data/doc-api/classes/Test.html +107 -0
  41. data/doc-api/created.rid +1 -0
  42. data/doc-api/files/__/README_txt.html +172 -0
  43. data/doc-api/files/kwalify/errors_rb.html +114 -0
  44. data/doc-api/files/kwalify/main_rb.html +118 -0
  45. data/doc-api/files/kwalify/messages_rb.html +107 -0
  46. data/doc-api/files/kwalify/meta-validator_rb.html +117 -0
  47. data/doc-api/files/kwalify/parser/base_rb.html +116 -0
  48. data/doc-api/files/kwalify/parser/yaml_rb.html +117 -0
  49. data/doc-api/files/kwalify/rule_rb.html +116 -0
  50. data/doc-api/files/kwalify/types_rb.html +114 -0
  51. data/doc-api/files/kwalify/util/assert-text-equal_rb.html +115 -0
  52. data/doc-api/files/kwalify/util/hash-interface_rb.html +114 -0
  53. data/doc-api/files/kwalify/util/hashlike_rb.html +107 -0
  54. data/doc-api/files/kwalify/util/option-parser_rb.html +107 -0
  55. data/doc-api/files/kwalify/util/ordered-hash_rb.html +107 -0
  56. data/doc-api/files/kwalify/util/testcase-helper_rb.html +115 -0
  57. data/doc-api/files/kwalify/util_rb.html +107 -0
  58. data/doc-api/files/kwalify/validator_rb.html +117 -0
  59. data/doc-api/files/kwalify/yaml-parser_rb.html +117 -0
  60. data/doc-api/files/kwalify_rb.html +121 -0
  61. data/doc-api/fr_class_index.html +57 -0
  62. data/doc-api/fr_file_index.html +45 -0
  63. data/doc-api/fr_method_index.html +168 -0
  64. data/doc-api/index.html +24 -0
  65. data/doc-api/rdoc-style.css +208 -0
  66. data/examples/address-book/Makefile +10 -0
  67. data/examples/address-book/address-book.schema.yaml +45 -0
  68. data/examples/address-book/address-book.yaml +36 -0
  69. data/examples/data-binding/BABEL.data.yaml +63 -0
  70. data/examples/data-binding/BABEL.schema.yaml +31 -0
  71. data/examples/data-binding/Makefile +8 -0
  72. data/examples/data-binding/Rakefile +13 -0
  73. data/examples/data-binding/main.rb +27 -0
  74. data/examples/invoice/Makefile +9 -0
  75. data/examples/invoice/invoice.schema.yaml +43 -0
  76. data/examples/invoice/invoice.yaml +32 -0
  77. data/examples/tapkit/Makefile +10 -0
  78. data/examples/tapkit/main.rb +7 -0
  79. data/examples/tapkit/tapkit.schema.yaml +146 -0
  80. data/examples/tapkit/tapkit.yaml +85 -0
  81. data/lib/kwalify/errors.rb +127 -0
  82. data/lib/kwalify/kwalify.schema.yaml +58 -0
  83. data/lib/kwalify/main.rb +442 -0
  84. data/lib/kwalify/messages.rb +173 -0
  85. data/lib/kwalify/meta-validator.rb +275 -0
  86. data/lib/kwalify/parser/base.rb +127 -0
  87. data/lib/kwalify/parser/yaml.rb +841 -0
  88. data/lib/kwalify/rule.rb +559 -0
  89. data/lib/kwalify/templates/genclass-java.eruby +222 -0
  90. data/lib/kwalify/templates/genclass-php.eruby +104 -0
  91. data/lib/kwalify/templates/genclass-ruby.eruby +113 -0
  92. data/lib/kwalify/types.rb +156 -0
  93. data/lib/kwalify/util/assert-text-equal.rb +46 -0
  94. data/lib/kwalify/util/hash-interface.rb +18 -0
  95. data/lib/kwalify/util/hashlike.rb +51 -0
  96. data/lib/kwalify/util/option-parser.rb +220 -0
  97. data/lib/kwalify/util/ordered-hash.rb +57 -0
  98. data/lib/kwalify/util/testcase-helper.rb +112 -0
  99. data/lib/kwalify/util.rb +158 -0
  100. data/lib/kwalify/validator.rb +282 -0
  101. data/lib/kwalify/yaml-parser.rb +870 -0
  102. data/lib/kwalify.rb +67 -0
  103. data/setup.rb +1585 -0
  104. data/test/Rookbook.yaml +10 -0
  105. data/test/data/users-guide/AddressBook.java.expected +40 -0
  106. data/test/data/users-guide/BABEL.data.yaml +24 -0
  107. data/test/data/users-guide/BABEL.schema.yaml +30 -0
  108. data/test/data/users-guide/ExampleAddressBook.java +47 -0
  109. data/test/data/users-guide/Group.java.expected +24 -0
  110. data/test/data/users-guide/Person.java.expected +44 -0
  111. data/test/data/users-guide/address_book.rb +52 -0
  112. data/test/data/users-guide/address_book.schema.yaml +28 -0
  113. data/test/data/users-guide/address_book.yaml +27 -0
  114. data/test/data/users-guide/answers-schema.yaml +12 -0
  115. data/test/data/users-guide/answers-validator.rb +52 -0
  116. data/test/data/users-guide/babel_genclass.result +26 -0
  117. data/test/data/users-guide/config.schema.yaml +7 -0
  118. data/test/data/users-guide/config.yaml +4 -0
  119. data/test/data/users-guide/document01a.yaml +3 -0
  120. data/test/data/users-guide/document01b.yaml +3 -0
  121. data/test/data/users-guide/document02a.yaml +4 -0
  122. data/test/data/users-guide/document02b.yaml +4 -0
  123. data/test/data/users-guide/document03a.yaml +6 -0
  124. data/test/data/users-guide/document03b.yaml +6 -0
  125. data/test/data/users-guide/document04a.yaml +9 -0
  126. data/test/data/users-guide/document04b.yaml +9 -0
  127. data/test/data/users-guide/document05a.yaml +11 -0
  128. data/test/data/users-guide/document05b.yaml +12 -0
  129. data/test/data/users-guide/document06a.yaml +15 -0
  130. data/test/data/users-guide/document06b.yaml +16 -0
  131. data/test/data/users-guide/document07a.yaml +9 -0
  132. data/test/data/users-guide/document07b.yaml +7 -0
  133. data/test/data/users-guide/document12a.json +10 -0
  134. data/test/data/users-guide/document12b.json +6 -0
  135. data/test/data/users-guide/document13a.yaml +17 -0
  136. data/test/data/users-guide/document14a.yaml +3 -0
  137. data/test/data/users-guide/document14b.yaml +3 -0
  138. data/test/data/users-guide/document15a.yaml +6 -0
  139. data/test/data/users-guide/document15b.yaml +5 -0
  140. data/test/data/users-guide/example_address_book.rb +10 -0
  141. data/test/data/users-guide/example_address_book_java.result +32 -0
  142. data/test/data/users-guide/example_address_book_ruby.result +31 -0
  143. data/test/data/users-guide/genclass_java.result +4 -0
  144. data/test/data/users-guide/howto-validation-with-parsing.rb +28 -0
  145. data/test/data/users-guide/howto-validation.rb +25 -0
  146. data/test/data/users-guide/howto3.rb +6 -0
  147. data/test/data/users-guide/howto3.result +5 -0
  148. data/test/data/users-guide/howto3.yaml +8 -0
  149. data/test/data/users-guide/howto5_databinding.result +111 -0
  150. data/test/data/users-guide/invalid01.result +3 -0
  151. data/test/data/users-guide/invalid02.result +5 -0
  152. data/test/data/users-guide/invalid03.result +5 -0
  153. data/test/data/users-guide/invalid04.result +4 -0
  154. data/test/data/users-guide/invalid05.result +11 -0
  155. data/test/data/users-guide/invalid06.result +4 -0
  156. data/test/data/users-guide/invalid07.result +3 -0
  157. data/test/data/users-guide/invalid08.result +3 -0
  158. data/test/data/users-guide/invalid12.json +8 -0
  159. data/test/data/users-guide/invalid14.result +4 -0
  160. data/test/data/users-guide/invalid15.result +4 -0
  161. data/test/data/users-guide/loadbabel.rb +27 -0
  162. data/test/data/users-guide/loadconfig.rb +16 -0
  163. data/test/data/users-guide/loadconfig.result +6 -0
  164. data/test/data/users-guide/models.rb +22 -0
  165. data/test/data/users-guide/option_ha.result +6 -0
  166. data/test/data/users-guide/option_ha_genclass_java.result +7 -0
  167. data/test/data/users-guide/schema01.yaml +3 -0
  168. data/test/data/users-guide/schema02.yaml +12 -0
  169. data/test/data/users-guide/schema03.yaml +9 -0
  170. data/test/data/users-guide/schema04.yaml +20 -0
  171. data/test/data/users-guide/schema05.yaml +29 -0
  172. data/test/data/users-guide/schema06.yaml +11 -0
  173. data/test/data/users-guide/schema12.json +12 -0
  174. data/test/data/users-guide/schema13.yaml +13 -0
  175. data/test/data/users-guide/schema14.yaml +5 -0
  176. data/test/data/users-guide/schema15.yaml +21 -0
  177. data/test/data/users-guide/valid01.result +2 -0
  178. data/test/data/users-guide/valid02.result +2 -0
  179. data/test/data/users-guide/valid03.result +2 -0
  180. data/test/data/users-guide/valid04.result +2 -0
  181. data/test/data/users-guide/valid05.result +2 -0
  182. data/test/data/users-guide/valid06.result +2 -0
  183. data/test/data/users-guide/valid07.result +2 -0
  184. data/test/data/users-guide/valid08.result +2 -0
  185. data/test/data/users-guide/valid12.result +2 -0
  186. data/test/data/users-guide/valid13.result +2 -0
  187. data/test/data/users-guide/valid14.result +2 -0
  188. data/test/data/users-guide/valid15.result +2 -0
  189. data/test/data/users-guide/validate08.rb +37 -0
  190. data/test/test-action.rb +78 -0
  191. data/test/test-action.yaml +738 -0
  192. data/test/test-databinding.rb +83 -0
  193. data/test/test-databinding.yaml +339 -0
  194. data/test/test-main.rb +157 -0
  195. data/test/test-main.yaml +415 -0
  196. data/test/test-metavalidator.rb +80 -0
  197. data/test/test-metavalidator.yaml +1179 -0
  198. data/test/test-parser-yaml.rb +57 -0
  199. data/test/test-parser-yaml.yaml +1749 -0
  200. data/test/test-rule.rb +26 -0
  201. data/test/test-rule.yaml +317 -0
  202. data/test/test-users-guide.rb +75 -0
  203. data/test/test-util.rb +125 -0
  204. data/test/test-validator.rb +95 -0
  205. data/test/test-validator.yaml +986 -0
  206. data/test/test-yaml-parser.rb +47 -0
  207. data/test/test-yaml-parser.yaml +1226 -0
  208. data/test/test.rb +61 -0
  209. metadata +274 -0
@@ -0,0 +1,85 @@
1
+ ##
2
+ ## original:
3
+ ## http://www.spice-of-life.net/tapkit/ja/TapKitUserGuide_J_c5_s6.html#doc7_1532
4
+ ##
5
+
6
+ adapter_name: DBI
7
+
8
+ connection:
9
+ url: dbi:Mysql:examples
10
+ user: mysql
11
+ password: mysql
12
+
13
+ entities:
14
+ -
15
+ name: Employee
16
+ external_name: EMPLOYEE
17
+
18
+ attributes:
19
+ -
20
+ name: employee_id
21
+ column_name: EMPLOYEE_ID
22
+ external_type: int
23
+ class_name: Integer
24
+ -
25
+ name: name
26
+ column_name: NAME
27
+ external_type: char
28
+ class_name: String
29
+ width: 64
30
+ -
31
+ name: company_id
32
+ column_name: COMPANY_ID
33
+ external_type: int
34
+ class_name: Integer
35
+
36
+ relationships:
37
+ -
38
+ name: company
39
+ destination: Company
40
+ to_many: false
41
+ joins:
42
+ -
43
+ source: company_id
44
+ destination: company_id
45
+
46
+ primary_key_attributes:
47
+ - employee_id
48
+
49
+ class_properties:
50
+ - name
51
+ - company
52
+
53
+ -
54
+ name: Company
55
+ external_name: COMPANY
56
+
57
+ attributes:
58
+ -
59
+ name: company_id
60
+ column_name: COMPANY_ID
61
+ external_type: int
62
+ class_name: Integer
63
+ -
64
+ name: name
65
+ column_name: NAME
66
+ external_type: char
67
+ class_name: String
68
+ width: 64
69
+
70
+ relationships:
71
+ -
72
+ name: employees
73
+ destination: Employee
74
+ to_many: true
75
+ joins:
76
+ -
77
+ source: company_id
78
+ destination: company_id
79
+
80
+ primary_key_attributes:
81
+ - company_id
82
+
83
+ class_properties:
84
+ - name
85
+ - employees
@@ -0,0 +1,127 @@
1
+ ###
2
+ ### $Rev$
3
+ ### $Release: 0.7.2 $
4
+ ### copyright(c) 2005-2010 kuwata-lab all rights reserved.
5
+ ###
6
+
7
+ require 'kwalify/messages'
8
+
9
+ module Kwalify
10
+
11
+ class KwalifyError < StandardError
12
+ end
13
+
14
+
15
+ class AssertionError < KwalifyError
16
+ def initialize(msg)
17
+ super("*** assertion error: " + msg)
18
+ end
19
+ end
20
+
21
+
22
+ class BaseError < KwalifyError
23
+ def initialize(message="", path=nil, value=nil, rule=nil, error_symbol=nil)
24
+ super(message)
25
+ @path = path.is_a?(Array) ? '/'+path.join('/') : path
26
+ @rule = rule
27
+ @value = value
28
+ @error_symbol = error_symbol
29
+ end
30
+ attr_accessor :error_symbol, :rule, :path, :value
31
+ attr_accessor :filename, :linenum, :column
32
+
33
+ def path
34
+ return @path == '' ? "/" : @path
35
+ end
36
+
37
+ alias _to_s to_s
38
+ alias message to_s
39
+
40
+ def to_s
41
+ s = ''
42
+ s << @filename << ":" if @filename
43
+ s << "#{@linenum}:#{@column} " if @linenum
44
+ s << "[#{path()}] " if @path
45
+ s << _to_s()
46
+ return s
47
+ end
48
+
49
+ def <=>(ex)
50
+ #return @linenum <=> ex.linenum
51
+ v = 0
52
+ v = @linenum <=> ex.linenum if @linenum && ex.linenum
53
+ v = @column <=> ex.column if v == 0 && @column && ex.column
54
+ v = @path <=> ex.path if v == 0
55
+ return v
56
+ end
57
+ end
58
+
59
+
60
+ class SchemaError < BaseError
61
+ def initialize(message="", path=nil, rule=nil, value=nil, error_symbol=nil)
62
+ super(message, path, rule, value, error_symbol)
63
+ end
64
+ end
65
+
66
+
67
+ class ValidationError < BaseError
68
+ def initialize(message="", path=nil, rule=nil, value=nil, error_symbol=nil)
69
+ super(message, path, rule, value, error_symbol)
70
+ end
71
+ end
72
+
73
+
74
+ ## syntax error for YAML and JSON
75
+ class SyntaxError < BaseError #KwalifyError
76
+ def initialize(msg, linenum=nil, error_symbol=nil)
77
+ super(linenum ? "line #{linenum}: #{msg}" : msg)
78
+ @linenum = linenum
79
+ @error_symbol = error_symbol
80
+ end
81
+ #attr_accessor :linenum, :error_symbol
82
+ def message
83
+ "file: #{@filename}, line #{@linenum}: #{super}"
84
+ end
85
+ end
86
+
87
+
88
+ ## (obsolete) use Kwalify::SyntaxError instead
89
+ class YamlSyntaxError < SyntaxError
90
+ end
91
+
92
+
93
+ module ErrorHelper
94
+
95
+ #module_function
96
+
97
+ def assert_error(message="")
98
+ raise AssertionError.new(message)
99
+ end
100
+
101
+ def validate_error(error_symbol, rule, path, val, args=nil)
102
+ msg = _build_message(error_symbol, val, args);
103
+ path = '/'+path.join('/') if path.is_a?(Array)
104
+ return ValidationError.new(msg, path, val, rule, error_symbol)
105
+ end
106
+ module_function :validate_error
107
+
108
+ def schema_error(error_symbol, rule, path, val, args=nil)
109
+ msg = _build_message(error_symbol, val, args);
110
+ path = '/'+path.join('/') if path.is_a?(Array)
111
+ return SchemaError.new(msg, path, val, rule, error_symbol)
112
+ end
113
+
114
+ def _build_message(message_key, val, args)
115
+ msg = Kwalify.msg(message_key)
116
+ assert_error("message_key=#{message_key.inspect}") unless msg
117
+ msg = msg % args if args
118
+ msg = "'#{val.to_s.gsub(/\n/, '\n')}': #{msg}" if !val.nil? && Types.scalar?(val)
119
+ return msg;
120
+ end
121
+ module_function :_build_message
122
+
123
+ end
124
+
125
+ extend ErrorHelper
126
+
127
+ end
@@ -0,0 +1,58 @@
1
+ ## $Rev$
2
+ ## $Date$
3
+ ## copyright(c) 2005-2010 kuwata-lab all rights reserved.
4
+
5
+ name: MAIN
6
+ type: map
7
+ required: yes
8
+ mapping: &main-rule
9
+ "name": { type: str }
10
+ "desc": { type: str }
11
+ "class": { type: str }
12
+ "type":
13
+ type: str
14
+ #required: yes
15
+ enum: [ seq, map, str, int, float, number, bool, text,
16
+ date, time, timestamp, any, scalar ]
17
+ "required": { type: bool } # equivarent to 'not-null'
18
+ "enum":
19
+ type: seq
20
+ sequence:
21
+ - type: scalar
22
+ unique: yes
23
+ "pattern": { type: str }
24
+ "assert": { type: str, pattern: /\bval\b/ }
25
+ "range":
26
+ type: map
27
+ mapping:
28
+ "max": { type: scalar }
29
+ "min": { type: scalar }
30
+ "max-ex": { type: scalar }
31
+ "min-ex": { type: scalar }
32
+ "length":
33
+ type: map
34
+ mapping:
35
+ "max": { type: int }
36
+ "min": { type: int }
37
+ "max-ex": { type: int }
38
+ "min-ex": { type: int }
39
+ "ident": { type: bool } # equivarent to 'primary-key' (undocumented)
40
+ "unique": { type: bool }
41
+ "default": { type: scalar } # used only in action's template
42
+ "sequence":
43
+ name: SEQUENCE
44
+ type: seq
45
+ sequence:
46
+ - type: map
47
+ mapping: *main-rule
48
+ name: MAIN
49
+ #required: yes
50
+ "mapping":
51
+ name: MAPPING
52
+ type: map
53
+ mapping:
54
+ =:
55
+ type: map
56
+ mapping: *main-rule
57
+ name: MAIN
58
+ #required: yes
@@ -0,0 +1,442 @@
1
+ ###
2
+ ### $Rev$
3
+ ### $Release: 0.7.2 $
4
+ ### copyright(c) 2005-2010 kuwata-lab all rights reserved.
5
+ ###
6
+
7
+ require 'yaml'
8
+ require 'erb'
9
+ require 'kwalify'
10
+ require 'kwalify/util'
11
+ require 'kwalify/util/ordered-hash'
12
+
13
+
14
+ module Kwalify
15
+
16
+
17
+ class CommandOptionError < KwalifyError
18
+ def initialize(message, option, error_symbol)
19
+ super(message)
20
+ @option = option
21
+ @error_symbol = error_symbol
22
+ end
23
+ attr_reader :option, :error_symbol
24
+ end
25
+
26
+
27
+ ##
28
+ ## ex.
29
+ ## command = File.basename($0)
30
+ ## begin
31
+ ## main = Kwalify::Main.new(command)
32
+ ## s = main.execute
33
+ ## print s if s
34
+ ## rescue Kwalify::CommandOptionError => ex
35
+ ## $stderr.puts "ERROR: #{ex.message}"
36
+ ## exit 1
37
+ ## rescue Kwalify::KwalifyError => ex
38
+ ## $stderr.puts "ERROR: #{ex.message}"
39
+ ## exit 1
40
+ ## end
41
+ ##
42
+ class Main
43
+
44
+
45
+ def initialize(command=nil)
46
+ @command = command || File.basename($0)
47
+ @options = {}
48
+ @properties = {}
49
+ @template_path = []
50
+ $:.each do |path|
51
+ tpath = "#{path}/kwalify/templates"
52
+ @template_path << tpath if test(?d, tpath)
53
+ end
54
+ end
55
+
56
+
57
+ def debug?
58
+ @options[:debug]
59
+ end
60
+
61
+
62
+ def _inspect()
63
+ sb = []
64
+ sb << "command: #{@command}\n"
65
+ sb << "options:\n"
66
+ @options.keys.sort {|k1,k2| k1.to_s<=>k2.to_s }.each do |key|
67
+ sb << " - #{key}: #{@options[key]}\n"
68
+ end
69
+ sb << "properties:\n"
70
+ @properties.keys.sort_by {|k| k.to_s}.each do |key|
71
+ sb << " - #{key}: #{@properties[key]}\n"
72
+ end
73
+ #sb << "template_path:\n"
74
+ #@template_path.each do |path|
75
+ # sb << " - #{path}\n"
76
+ #end
77
+ return sb.join
78
+ end
79
+
80
+
81
+ def execute(argv=ARGV)
82
+ ## parse command-line options
83
+ filenames = _parse_argv(argv)
84
+
85
+ ## help or version
86
+ if @options[:help] || @options[:version]
87
+ action = @options[:action]
88
+ s = ''
89
+ s << _version() << "\n" if @options[:version]
90
+ s << _usage() if @options[:help] && !action
91
+ s << _describe_properties(action) if @options[:help] && action
92
+ puts s
93
+ return
94
+ end
95
+
96
+ # validation
97
+ if @options[:meta2]
98
+ validate_schemafiles2(filenames)
99
+ elsif @options[:meta]
100
+ validate_schemafiles(filenames)
101
+ elsif @options[:action]
102
+ unless @options[:schema]
103
+ #* key=:command_option_actionnoschema msg="schema filename is not specified."
104
+ raise option_error(:command_option_actionnoschema, @options[:action])
105
+ end
106
+ perform_action(@options[:action], @options[:schema])
107
+ elsif @options[:schema]
108
+ if @options[:debug]
109
+ inspect_schema(@options[:schema])
110
+ else
111
+ validate_files(filenames, @options[:schema])
112
+ end
113
+ else
114
+ #* key=:command_option_noaction msg="command-line option '-f' or '-m' required."
115
+ raise option_error(:command_option_noaction, @command)
116
+ end
117
+ return
118
+ end
119
+
120
+
121
+ def self.main(command, argv=ARGV)
122
+ begin
123
+ main = Kwalify::Main.new(command)
124
+ s = main.execute(argv)
125
+ print s if s
126
+ rescue Kwalify::CommandOptionError => ex
127
+ raise ex if main.debug?
128
+ $stderr.puts ex.message
129
+ exit 1
130
+ rescue Kwalify::KwalifyError => ex
131
+ raise ex if main.debug?
132
+ $stderr.puts "ERROR: #{ex.to_s}"
133
+ exit 1
134
+ #rescue => ex
135
+ # if main.debug?
136
+ # raise ex
137
+ # else
138
+ # $stderr.puts ex.message
139
+ # exit 1
140
+ # end
141
+ end
142
+ end
143
+
144
+
145
+ private
146
+
147
+
148
+ def option_error(error_symbol, arg)
149
+ msg = Kwalify.msg(error_symbol) % arg
150
+ return CommandOptionError.new(msg, arg, error_symbol)
151
+ end
152
+
153
+
154
+ def _find_template(action)
155
+ template_filename = action + '.eruby'
156
+ unless test(?f, template_filename)
157
+ pathlist = []
158
+ pathlist.concat(@options[:tpath].split(/,/)) if @options[:tpath]
159
+ pathlist.concat(@template_path)
160
+ tpath = pathlist.find {|path| test(?f, "#{path}/#{template_filename}") }
161
+ #* key=:command_option_notemplate msg="%s: invalid action (template not found).\n"
162
+ raise option_error(:command_option_notemplate, action) unless tpath
163
+ template_filename = "#{tpath}/#{action}.eruby"
164
+ end
165
+ return template_filename
166
+ end
167
+
168
+
169
+ def apply_template(template_filename, hash)
170
+ template = File.read(template_filename)
171
+ trim_mode = 1
172
+ erb = ERB.new(template, nil, trim_mode)
173
+ context = Object.new
174
+ hash.each do |key, val|
175
+ context.instance_variable_set("@#{key}", val)
176
+ end
177
+ s = context.instance_eval(erb.src, template_filename)
178
+ return s
179
+ end
180
+
181
+
182
+ def _describe_properties(action)
183
+ template_filename = _find_template(action)
184
+ s = apply_template(template_filename, :describe=>true)
185
+ return s
186
+ end
187
+
188
+
189
+ def perform_action(action, schema_filename, describe=false)
190
+ template_filename = _find_template(action)
191
+ schema = _load_schemafile(schema_filename, ordered=true)
192
+ validator = Kwalify::Validator.new(schema)
193
+ @properties[:schema_filename] = schema_filename
194
+ hash = { :validator=>validator, :schema=>schema, :properties=>@properties }
195
+ s = apply_template(template_filename, hash)
196
+ puts s if s && !s.empty?
197
+ end
198
+
199
+
200
+ def inspect_schema(schema_filename)
201
+ schema = _load_schemafile(schema_filename)
202
+ if schema.nil?
203
+ puts "nil"
204
+ else
205
+ validator = Kwalify::Validator.new(schema) # error raised when schema is wrong
206
+ puts validator._inspect()
207
+ end
208
+ end
209
+
210
+
211
+ ## -f schemafile datafile
212
+ def validate_files(filenames, schema_filename)
213
+ schema = _load_schemafile(schema_filename)
214
+ validator = Kwalify::Validator.new(schema)
215
+ _validate_files(validator, filenames)
216
+ end
217
+
218
+
219
+ def _load_schemafile(schema_filename, ordered=false)
220
+ str = File.read(schema_filename)
221
+ if str.empty?
222
+ #* key=:schema_empty msg="%s: empty schema.\n"
223
+ msg = Kwalify.msg(:schema_emtpy) % filename
224
+ raise CommandOptionError.new(msg)
225
+ end
226
+ str = Util.untabify(str) if @options[:untabify]
227
+ parser = Kwalify::Yaml::Parser.new()
228
+ parser.preceding_alias = true if @options[:preceding]
229
+ parser.mapping_class = Kwalify::Util::OrderedHash if ordered
230
+ schema = parser.parse(str, :filename=>schema_filename) # or YAML.load(str)
231
+ return schema
232
+ end
233
+
234
+
235
+ ## -m schemafile
236
+ def validate_schemafiles(schema_filenames)
237
+ meta_validator = Kwalify::MetaValidator.instance()
238
+ _validate_files(meta_validator, schema_filenames)
239
+ end
240
+
241
+
242
+ ## -M schemafile
243
+ def validate_schemafiles2(schema_filenames)
244
+ parser = Kwalify::Yaml::Parser.new()
245
+ parser.preceding_alias = true if @options[:preceding]
246
+ for schema_filename in schema_filenames
247
+ str = File.read(schema_filename)
248
+ str = Util.untabify(str) if @options[:untabify]
249
+ schema = parser.parse(str, :filename=>schema_filename)
250
+ Kwalify::Validator.new(schema) # exception raised when schema has errors
251
+ end
252
+ end
253
+
254
+
255
+ def _validate_files(validator, filenames)
256
+ ## parser
257
+ if @options[:linenum] || @options[:preceding]
258
+ parser = Kwalify::Yaml::Parser.new(validator)
259
+ parser.preceding_alias = true if @options[:preceding]
260
+ else
261
+ parser = nil
262
+ end
263
+ ## filenames
264
+ if filenames.empty?
265
+ filenames = [ $stdin ]
266
+ end
267
+ for filename in filenames
268
+ ## read input
269
+ if filename.is_a?(IO)
270
+ input = filename.read()
271
+ filename = '(stdin)'
272
+ else
273
+ input = File.read(filename)
274
+ end
275
+ if input.empty?
276
+ #* key=:validation_empty msg="%s#%d: empty."
277
+ puts kwalify.msg(:validation_empty) % [filename, i]
278
+ #puts "#{filename}##{i}: empty."
279
+ next
280
+ end
281
+ input = Util.untabify(input) if @options[:untabify]
282
+ ## parse input
283
+ if parser
284
+ #i = 0
285
+ #ydoc = parser.parse(input, :filename=>filename)
286
+ #_show_errors(filename, i, ydoc, parser.errors)
287
+ #while parser.has_next?
288
+ # i += 1
289
+ # ydoc = parser.parse_next()
290
+ # _show_errors(filename, i, ydoc, parser.errors)
291
+ #end
292
+ i = 0
293
+ parser.parse_stream(input, :filename=>filename) do |ydoc|
294
+ _show_errors(filename, i, ydoc, parser.errors)
295
+ i += 1
296
+ end
297
+ else
298
+ i = 0
299
+ YAML.load_documents(input) do |ydoc|
300
+ errors = validator.validate(ydoc)
301
+ _show_errors(filename, i, ydoc, errors)
302
+ i += 1
303
+ end
304
+ end
305
+ end
306
+ end
307
+
308
+
309
+ def _show_errors(filename, i, ydoc, errors, ok_label="valid.", ng_label="INVALID")
310
+ if errors && !errors.empty?
311
+ puts "#{filename}##{i}: #{ng_label}"
312
+ errors.sort!
313
+ for error in errors
314
+ e = error
315
+ if @options[:emacs]
316
+ raise unless @options[:linenum]
317
+ puts "#{filename}:#{e.linenum}:#{e.column} [#{e.path}] #{e.message}\n"
318
+ elsif @options[:linenum]
319
+ puts " - (line #{e.linenum}) [#{e.path}] #{e.message}\n"
320
+ else
321
+ puts " - [#{e.path}] #{e.message}\n"
322
+ end
323
+ end
324
+ elsif ydoc.nil?
325
+ #* key=:validation_empty msg="%s#%d: empty.\n"
326
+ puts Kwalify.msg(:validation_empty) % [filename, i]
327
+ else
328
+ #* key=:validation_valid msg="%s#%d: valid."
329
+ puts Kwalify.msg(:validation_valid) % [filename, i] unless @options[:quiet]
330
+ #puts "#{filename}##{i} - #{ok_label}" unless @options[:quiet]
331
+ end
332
+ end
333
+
334
+
335
+ def _usage()
336
+ #msg = Kwalify.msg(:command_help) % [@command, @command, @command]
337
+ msg = Kwalify.msg(:command_help)
338
+ return msg
339
+ end
340
+
341
+
342
+ def _version()
343
+ return RELEASE
344
+ end
345
+
346
+
347
+ def _to_value(str)
348
+ case str
349
+ when nil, "null", "nil" ; return nil
350
+ when "true", "yes" ; return true
351
+ when "false", "no" ; return false
352
+ when /\A\d+\z/ ; return str.to_i
353
+ when /\A\d+\.\d+\z/ ; return str.to_f
354
+ when /\/(.*)\// ; return Regexp.new($1)
355
+ when /\A'.*'\z/, /\A".*"\z/ ; return eval(str)
356
+ else ; return str
357
+ end
358
+ end
359
+
360
+
361
+ def _parse_argv(argv)
362
+ option_table = {
363
+ ?h => :help,
364
+ ?v => :version,
365
+ ?q => :quiet,
366
+ ?s => :quiet,
367
+ ?t => :untabify,
368
+ #?z => :meta,
369
+ ?m => :meta,
370
+ ?M => :meta2,
371
+ ?E => :emacs,
372
+ ?l => :linenum,
373
+ ?f => :schema,
374
+ ?D => :debug,
375
+ ?a => :action,
376
+ ?I => :tpath,
377
+ ?P => :preceding,
378
+ }
379
+
380
+ errcode_table = {
381
+ #* key=:command_option_schema_required msg="-%s: schema filename required."
382
+ ?f => :command_option_schema_required,
383
+ #* key=:command_option_action_required msg="-%s: action required."
384
+ ?a => :command_option_action_required,
385
+ #* key=:command_option_tpath_required msg="-%s: template path required."
386
+ ?I => :command_option_tpath_required,
387
+ }
388
+
389
+ while argv[0] && argv[0][0] == ?-
390
+ optstr = argv.shift
391
+ optstr = optstr[1, optstr.length-1]
392
+ ## property
393
+ if optstr[0] == ?-
394
+ unless optstr =~ /\A\-([-\w]+)(?:=(.*))?\z/
395
+ #* key=:command_property_invalid msg="%s: invalid property."
396
+ raise option_error(:command_property_invalid, optstr)
397
+ end
398
+ prop_name = $1; prop_value = $2
399
+ key = prop_name.gsub(/-/, '_').intern
400
+ value = prop_value.nil? ? true : _to_value(prop_value)
401
+ @properties[key] = value
402
+ ## option
403
+ else
404
+ while optstr && !optstr.empty?
405
+ optchar = optstr[0]
406
+ optstr[0,1] = ""
407
+ unless option_table.key?(optchar)
408
+ #* key=:command_option_invalid msg="-%s: invalid command option."
409
+ raise option_error(:command_option_invalid, optchar.chr)
410
+ end
411
+ optkey = option_table[optchar]
412
+ case optchar
413
+ when ?f, ?a, ?I
414
+ arg = optstr.empty? ? argv.shift : optstr
415
+ raise option_error(errcode_table[optchar], optchar.chr) unless arg
416
+ @options[optkey] = arg
417
+ optstr = ''
418
+ else
419
+ @options[optkey] = true
420
+ end
421
+ end
422
+ end
423
+ end # end of while
424
+ #
425
+ @options[:linenum] = true if @options[:emacs]
426
+ @options[:help] = true if @properties[:help]
427
+ @options[:version] = true if @properties[:version]
428
+ filenames = argv
429
+ return filenames
430
+ end
431
+
432
+
433
+ def _domain_type?(doc)
434
+ klass = defined?(YAML::DomainType) ? YAML::DomainType : YAML::Syck::DomainType
435
+ return doc.is_a?(klass)
436
+ end
437
+
438
+
439
+ end
440
+
441
+
442
+ end