ddao-kwalify 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (208) hide show
  1. data/CHANGES.txt +243 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.txt +61 -0
  4. data/bin/kwalify +13 -0
  5. data/contrib/inline-require +153 -0
  6. data/contrib/kwalify +4159 -0
  7. data/doc-api/classes/CommandOptionError.html +184 -0
  8. data/doc-api/classes/CommandOptionParser.html +325 -0
  9. data/doc-api/classes/Kwalify.html +292 -0
  10. data/doc-api/classes/Kwalify/AssertionError.html +148 -0
  11. data/doc-api/classes/Kwalify/BaseError.html +297 -0
  12. data/doc-api/classes/Kwalify/BaseParser.html +461 -0
  13. data/doc-api/classes/Kwalify/CommandOptionError.html +168 -0
  14. data/doc-api/classes/Kwalify/ErrorHelper.html +223 -0
  15. data/doc-api/classes/Kwalify/HashInterface.html +118 -0
  16. data/doc-api/classes/Kwalify/Json.html +105 -0
  17. data/doc-api/classes/Kwalify/KwalifyError.html +111 -0
  18. data/doc-api/classes/Kwalify/Main.html +339 -0
  19. data/doc-api/classes/Kwalify/MetaValidator.html +448 -0
  20. data/doc-api/classes/Kwalify/Parser.html +155 -0
  21. data/doc-api/classes/Kwalify/PlainYamlParser.html +523 -0
  22. data/doc-api/classes/Kwalify/PlainYamlParser/Alias.html +165 -0
  23. data/doc-api/classes/Kwalify/Rule.html +433 -0
  24. data/doc-api/classes/Kwalify/SchemaError.html +148 -0
  25. data/doc-api/classes/Kwalify/SyntaxError.html +185 -0
  26. data/doc-api/classes/Kwalify/Types.html +302 -0
  27. data/doc-api/classes/Kwalify/Util.html +389 -0
  28. data/doc-api/classes/Kwalify/Util/HashLike.html +246 -0
  29. data/doc-api/classes/Kwalify/Util/OrderedHash.html +330 -0
  30. data/doc-api/classes/Kwalify/ValidationError.html +148 -0
  31. data/doc-api/classes/Kwalify/Validator.html +381 -0
  32. data/doc-api/classes/Kwalify/Yaml.html +194 -0
  33. data/doc-api/classes/Kwalify/Yaml/Parser.html +1538 -0
  34. data/doc-api/classes/Kwalify/YamlParser.html +542 -0
  35. data/doc-api/classes/Kwalify/YamlSyntaxError.html +119 -0
  36. data/doc-api/classes/Test.html +107 -0
  37. data/doc-api/classes/Test/Unit.html +101 -0
  38. data/doc-api/created.rid +1 -0
  39. data/doc-api/files/__/README_txt.html +172 -0
  40. data/doc-api/files/kwalify/errors_rb.html +114 -0
  41. data/doc-api/files/kwalify/main_rb.html +118 -0
  42. data/doc-api/files/kwalify/messages_rb.html +107 -0
  43. data/doc-api/files/kwalify/meta-validator_rb.html +117 -0
  44. data/doc-api/files/kwalify/parser/base_rb.html +116 -0
  45. data/doc-api/files/kwalify/parser/yaml_rb.html +117 -0
  46. data/doc-api/files/kwalify/rule_rb.html +116 -0
  47. data/doc-api/files/kwalify/types_rb.html +114 -0
  48. data/doc-api/files/kwalify/util/assert-text-equal_rb.html +115 -0
  49. data/doc-api/files/kwalify/util/hash-interface_rb.html +114 -0
  50. data/doc-api/files/kwalify/util/hashlike_rb.html +107 -0
  51. data/doc-api/files/kwalify/util/option-parser_rb.html +107 -0
  52. data/doc-api/files/kwalify/util/ordered-hash_rb.html +107 -0
  53. data/doc-api/files/kwalify/util/testcase-helper_rb.html +115 -0
  54. data/doc-api/files/kwalify/util_rb.html +107 -0
  55. data/doc-api/files/kwalify/validator_rb.html +117 -0
  56. data/doc-api/files/kwalify/yaml-parser_rb.html +117 -0
  57. data/doc-api/files/kwalify_rb.html +121 -0
  58. data/doc-api/fr_class_index.html +57 -0
  59. data/doc-api/fr_file_index.html +45 -0
  60. data/doc-api/fr_method_index.html +168 -0
  61. data/doc-api/index.html +24 -0
  62. data/doc-api/rdoc-style.css +208 -0
  63. data/doc/docstyle.css +188 -0
  64. data/doc/img/fig01.png +0 -0
  65. data/doc/users-guide.html +2050 -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.rb +67 -0
  82. data/lib/kwalify/errors.rb +128 -0
  83. data/lib/kwalify/kwalify.schema.yaml +58 -0
  84. data/lib/kwalify/main.rb +442 -0
  85. data/lib/kwalify/messages.rb +173 -0
  86. data/lib/kwalify/meta-validator.rb +276 -0
  87. data/lib/kwalify/parser/base.rb +127 -0
  88. data/lib/kwalify/parser/yaml.rb +841 -0
  89. data/lib/kwalify/rule.rb +560 -0
  90. data/lib/kwalify/templates/genclass-java.eruby +222 -0
  91. data/lib/kwalify/templates/genclass-php.eruby +104 -0
  92. data/lib/kwalify/templates/genclass-ruby.eruby +113 -0
  93. data/lib/kwalify/types.rb +156 -0
  94. data/lib/kwalify/util.rb +157 -0
  95. data/lib/kwalify/util/assert-text-equal.rb +46 -0
  96. data/lib/kwalify/util/hash-interface.rb +18 -0
  97. data/lib/kwalify/util/hashlike.rb +51 -0
  98. data/lib/kwalify/util/option-parser.rb +220 -0
  99. data/lib/kwalify/util/ordered-hash.rb +57 -0
  100. data/lib/kwalify/util/testcase-helper.rb +112 -0
  101. data/lib/kwalify/validator.rb +282 -0
  102. data/lib/kwalify/yaml-parser.rb +870 -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 +384 -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-validator.rb +95 -0
  204. data/test/test-validator.yaml +986 -0
  205. data/test/test-yaml-parser.rb +47 -0
  206. data/test/test-yaml-parser.yaml +1226 -0
  207. data/test/test.rb +60 -0
  208. metadata +261 -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,67 @@
1
+ ###
2
+ ### $Rev: 99 $
3
+ ### $Release: 0.7.1 $
4
+ ### copyright(c) 2006 kuwata-lab.com all rights reserved.
5
+ ###
6
+
7
+
8
+ module Kwalify
9
+
10
+ RELEASE = ("$Release: 0.7.1 $" =~ /[.\d]+/) && $&
11
+
12
+ end
13
+
14
+ require 'kwalify/types'
15
+ require 'kwalify/messages'
16
+ require 'kwalify/errors'
17
+ require 'kwalify/rule'
18
+ require 'kwalify/validator'
19
+ require 'kwalify/meta-validator'
20
+ require 'kwalify/yaml-parser'
21
+ #require 'kwalify/parser/base'
22
+ #require 'kwalify/parser/yaml'
23
+
24
+
25
+ module Kwalify
26
+
27
+ module Util
28
+
29
+ autoload :HashLike, 'kwalify/util/hashlike'
30
+
31
+ end
32
+
33
+ module Yaml
34
+
35
+ autoload :Parser, 'kwalify/parser/yaml'
36
+
37
+ ## read yaml_str, parse it, and return yaml document.
38
+ ##
39
+ ## opts:
40
+ ## ::validator: Kwalify::Validator object
41
+ ## ::preceding_aliass: allow preceding alias if true
42
+ ## ::data_binding: enable data binding if true
43
+ ## ::untabify: expand tab chars if true
44
+ ## ::filename: filename
45
+ def self.load(yaml_str, opts={})
46
+ #require 'kwalify/parser/yaml'
47
+ parser = Kwalify::Yaml::Parser.new(opts[:validator])
48
+ parser.preceding_alias = true if opts[:preceding_alias]
49
+ parser.data_binding = true if opts[:data_binding]
50
+ yaml_str = Kwalify::Util.untabify(yaml_str) if opts[:untabify]
51
+ ydoc = parser.parse(yaml_str, :filename=>opts[:filename])
52
+ return ydoc
53
+ end
54
+
55
+ ## read file, parse it, and return yaml document.
56
+ ## see Kwalify::Yaml::Parser.load()
57
+ def self.load_file(filename, opts={})
58
+ opts[:filename] = filename
59
+ return self.load(File.read(filename), opts)
60
+ end
61
+
62
+ end
63
+
64
+ module Json
65
+ end
66
+
67
+ end
@@ -0,0 +1,128 @@
1
+ ###
2
+ ### $Rev: 99 $
3
+ ### $Release: 0.7.1 $
4
+ ### copyright(c) 2005-2008 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
+ @filename = @linenum = nil
30
+ end
31
+ attr_accessor :error_symbol, :rule, :path, :value
32
+ attr_accessor :filename, :linenum, :column
33
+
34
+ def to_path
35
+ return @path == '' ? "/" : @path
36
+ end
37
+
38
+ alias _to_s to_s
39
+ alias message to_s
40
+
41
+ def to_s
42
+ s = ''
43
+ s << @filename << ":" if @filename
44
+ s << "#{@linenum}:#{@column} " if @linenum
45
+ s << "[#{to_path()}] " if @path
46
+ s << _to_s()
47
+ return s
48
+ end
49
+
50
+ def <=>(ex)
51
+ #return @linenum <=> ex.linenum
52
+ v = 0
53
+ v = @linenum <=> ex.linenum if @linenum && ex.linenum
54
+ v = @column <=> ex.column if v == 0 && @column && ex.column
55
+ v = @path <=> ex.path if v == 0
56
+ return v
57
+ end
58
+ end
59
+
60
+
61
+ class SchemaError < BaseError
62
+ def initialize(message="", path=nil, rule=nil, value=nil, error_symbol=nil)
63
+ super(message, path, rule, value, error_symbol)
64
+ end
65
+ end
66
+
67
+
68
+ class ValidationError < BaseError
69
+ def initialize(message="", path=nil, rule=nil, value=nil, error_symbol=nil)
70
+ super(message, path, rule, value, error_symbol)
71
+ end
72
+ end
73
+
74
+
75
+ ## syntax error for YAML and JSON
76
+ class SyntaxError < BaseError #KwalifyError
77
+ def initialize(msg, linenum=nil, error_symbol=nil)
78
+ super(linenum ? "line #{linenum}: #{msg}" : msg)
79
+ @linenum = linenum
80
+ @error_symbol = error_symbol
81
+ end
82
+ #attr_accessor :linenum, :error_symbol
83
+ def message
84
+ "file: #{@filename}, line #{@linenum}: #{super}"
85
+ end
86
+ end
87
+
88
+
89
+ ## (obsolete) use Kwalify::SyntaxError instead
90
+ class YamlSyntaxError < SyntaxError
91
+ end
92
+
93
+
94
+ module ErrorHelper
95
+
96
+ #module_function
97
+
98
+ def assert_error(message="")
99
+ raise AssertionError.new(message)
100
+ end
101
+
102
+ def validate_error(error_symbol, rule, path, val, args=nil)
103
+ msg = _build_message(error_symbol, val, args);
104
+ path = '/'+path.join('/') if path.is_a?(Array)
105
+ return ValidationError.new(msg, path, val, rule, error_symbol)
106
+ end
107
+ module_function :validate_error
108
+
109
+ def schema_error(error_symbol, rule, path, val, args=nil)
110
+ msg = _build_message(error_symbol, val, args);
111
+ path = '/'+path.join('/') if path.is_a?(Array)
112
+ return SchemaError.new(msg, path, val, rule, error_symbol)
113
+ end
114
+
115
+ def _build_message(message_key, val, args)
116
+ msg = Kwalify.msg(message_key)
117
+ assert_error("message_key=#{message_key.inspect}") unless msg
118
+ msg = msg % args if args
119
+ msg = "'#{val.to_s.gsub(/\n/, '\n')}': #{msg}" if !val.nil? && Types.scalar?(val)
120
+ return msg;
121
+ end
122
+ module_function :_build_message
123
+
124
+ end
125
+
126
+ extend ErrorHelper
127
+
128
+ end
@@ -0,0 +1,58 @@
1
+ ## $Rev: 95 $
2
+ ## $Date: 2008-01-27 22:49:22 +0900 (Sun, 27 Jan 2008) $
3
+ ## copyright(c) 2005-2008 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: 95 $
3
+ ### $Release: 0.7.1 $
4
+ ### copyright(c) 2005-2008 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