lib/kwalify/meta-validator.rb in kwalify-0.1.0 vs lib/kwalify/meta-validator.rb in kwalify-0.2.0
- old
+ new
@@ -1,137 +1,260 @@
###
-### $Rev: 9 $
-### $Release: 0.1.0 $
+### $Rev: 18 $
+### $Release: 0.2.0 $
### copyright(c) 2005 kuwata-lab all rights reserved.
###
require 'kwalify/errors'
+require 'kwalify/rule'
require 'kwalify/validator'
require 'yaml'
module Kwalify
- META_SCHEMA_DEF = <<'END'
-
+ META_SCHEMA = <<'END'
name: MAIN
type: map
required: yes
-mapping: &main-schema
+mapping: &main-rule
"name":
- type: string
+ type: str
"desc":
- type: text
+ type: str
"type":
- type: string
+ type: str
+ #required: yes
enum:
- seq
- - sequence
+ #- sequence
#- list
- map
- - mapping
+ #- mapping
#- hash
- - string
- - integer
+ - str
+ #- string
+ - int
+ #- integer
- float
- number
- - numeric
+ #- numeric
- bool
- - boolean
+ #- boolean
- text
- date
- time
- - object
+ - timestamp
+ #- object
- any
+ - scalar
+ #- collection
"required":
- type: boolean
+ type: bool
"enum":
type: seq
sequence:
- - type: object
+ - type: scalar
"pattern":
- type: string
+ type: str
+ "assert":
+ type: str
+ pattern: /\bval\b/
+ "range":
+ type: map
+ mapping:
+ "max":
+ type: scalar
+ "min":
+ type: scalar
+ "length":
+ type: map
+ mapping:
+ "max":
+ type: int
+ "min":
+ type: int
"sequence":
name: SEQUENCE
type: seq
sequence:
- type: map
- mapping: *main-schema
+ mapping: *main-rule
name: MAIN
+ #required: yes
"mapping":
name: MAPPING
type: map
mapping:
- '*':
+ '*':
type: map
- mapping: *main-schema
+ mapping: *main-rule
name: MAIN
-
+ #required: yes
END
- def self.meta_validator()
- yaml = YAML.load(META_SCHEMA_DEF)
- validator = Kwalify::Validator.new(yaml)
- return validator
- end
+ ##
+ ## ex.
+ ## meta_validator = Kwalify.meta_validator()
+ ## schema = File.load_file('schema.yaml')
+ ## errors << meta_validator.validate(schema)
+ ## if !errors.empty?
+ ## errors.each do |error|
+ ## puts "[#{error.path}] #{error.message}"
+ ## end
+ ## end
+ ##
+ class MetaValidator < Validator
+ def initialize(schema, &block)
+ super
+ end
-
- def self.meta_validator2()
- yaml = YAML.load(META_SCHEMA_DEF)
- validator = Kwalify::Validator.new(yaml) { |schema, obj, errors, path|
- next if obj == nil ## realy?
- if schema.name == "MAIN"
- hash = obj
- if hash.key?('pattern')
- val = hash['pattern']
- pat = (val =~ /\A\/(.*)\/\z/ ? $1 : val)
- begin
- Regexp.compile(pat)
- rescue RegexpError => ex
- errors << Kwalify::Errors.validate_error(:regexp_error, schema, path, obj)
+ def validate_hook(value, rule, path, errors)
+ return if value == nil ## realy?
+ return unless rule.name == "MAIN"
+ #
+ hash = value
+ type = hash['type']
+ type = Kwalify::DEFAULT_TYPE if type == nil
+ unless type.is_a?(String)
+ errors << Kwalify.validate_error(:type_notstr, rule, "#{path}/type", type.to_s)
+ end
+ klass = Kwalify.get_type_class(type)
+ unless klass
+ errors << Kwalify.validate_error(:type_unknown, rule, "#{path}/type", type.to_s)
+ end
+ #
+ if hash.key?('pattern')
+ val = hash['pattern']
+ pat = (val =~ /\A\/(.*)\/([mi]?[mi]?)\z/ ? $1 : val)
+ begin
+ Regexp.compile(pat)
+ rescue RegexpError => ex
+ errors << Kwalify.validate_error(:pattern_syntaxerr, rule, "#{path}/pattern", val)
+ end
+ end
+ #
+ if hash.key?('enum')
+ if type == 'seq' || type == 'map' # unless Kwalify.scalar_class?(klass)
+ errors << schema_error(:enum_notscalar, rule, path, 'enum:')
+ else
+ elem_table = {}
+ hash['enum'].each do |elem|
+ if elem_table[elem]
+ errors << Kwalify.validate_error(:enum_duplicate, rule, "#{path}/enum", elem.to_s)
+ end
+ elem_table[elem] = true
+ unless elem.is_a?(klass)
+ errors << schema_error(:enum_type_unmatch, rule, "#{path}/enum", elem, [Kwalify.word(type)])
+ end
end
end
- type = hash['type']
- if type == nil
- if hash.key?('sequence')
- type = 'seq'
- elsif hash.key?('mapping')
- type = 'map'
+ end
+ #
+ if hash.key?('assert')
+ val = hash['assert']
+ val =~ /\bval\b/ or errors << Kwalify.validate_error(:assert_noval, rule, "#{path}/assert", val)
+ begin
+ eval "proc { |val| #{val} }"
+ rescue SyntaxError => ex
+ errors << Kwalify.validate_error(:assert_syntaxerr, rule, "#{path}/assert", val)
+ end
+ end
+ #
+ if hash.key?('range')
+ val = hash['range']
+ curr_path = path + "/range"
+ if ! val.is_a?(Hash)
+ errors << Kwalify.validate_error(:range_notmap, rule, curr_path, val)
+ elsif type == 'seq' || type == 'map' || type == 'bool' || type == 'any'
+ errors << Kwalify.validate_error(:range_notscalar, rule, path, 'range:')
+ else
+ val.each do |rkey, rval|
+ case rkey
+ when 'max', 'min'
+ unless rval.is_a?(klass)
+ typename = Kwalify.word(type) || type
+ errors << Kwalify.validate_error(:range_type_unmatch, rule, "#{curr_path}/#{rkey}", rval, [typename])
+ end
+ else
+ errors << Kwalify.validate_error(:range_undefined, rule, curr_path, "#{rkey}:")
+ end
+ end
+ end
+ end
+ #
+ if hash.key?('length')
+ val = hash['length']
+ curr_path = path + "/length"
+ val.is_a?(Hash) or errors << Kwalify.validate_error(:length_notmap, rule, curr_path, val)
+ unless type == 'str' || type == 'text'
+ errors << validate_error(:length_nottext, rule, path, 'length:')
+ end
+ val.each do |lkey, lval|
+ case lkey
+ when 'max', 'min'
+ unless lval.is_a?(Integer)
+ errors << Kwalify.validate_error(:length_notint, rule, "#{curr_path}/#{lkey}", lval)
+ end
else
- type = Kwalify::DEFAULT_TYPE
+ errors << validate_error(:length_undefined, rule, curr_path, "#{lkey}:")
end
end
- klass = Kwalify.type_table[type]
- if klass == nil
- errors << Kwalify::Errors.validate_error(:invalid_type, schema, path, obj)
- elsif klass == Array
- errors << Kwalify::Errors.validate_error(:seq_has_enum, schema, path, obj) if hash.key?('enum')
- errors << Kwalify::Errors.validate_error(:seq_has_pattern, schema, path, obj) if hash.key?('pattern')
- errors << Kwalify::Errors.validate_error(:seq_has_mapping, schema, path, obj) if hash.key?('mapping')
- elsif klass == Hash
- errors << Kwalify::Errors.validate_error(:map_has_enum, schema, path, obj) if hash.key?('enum')
- errors << Kwalify::Errors.validate_error(:map_has_pattern, schema, path, obj) if hash.key?('pattern')
- errors << Kwalify::Errors.validate_error(:map_has_sequence, schema, path, obj) if hash.key?('sequence')
- else
- errors << Kwalify::Errors.validate_error(:scalar_has_sequence, schema, path, obj) if hash.key?('sequence')
- errors << Kwalify::Errors.validate_error(:scalar_has_mapping, schema, path, obj) if hash.key?('mapping')
+ end
+ #
+ if hash.key?('sequence')
+ val = hash['sequence']
+ if val != nil && !val.is_a?(Array)
+ errors << Kwalify.validate_error(:sequence_notseq, rule, "#{path}/sequence", val)
+ elsif val == nil || val.empty?
+ errors << Kwalify.validate_error(:sequence_noelem, rule, "#{path}/sequence", val)
+ elsif val.length > 1
+ errors << Kwalify.validate_error(:sequence_toomany, rule, "#{path}/sequence", val)
end
- elsif schema.name == "SEQUENCE"
- if !obj.is_a?(Array)
- errors << Kwalify::Errors.validate_error(:sequence_not_seq, schema, path, obj)
- else
- errors << Kwalify::Errors.validate_error(:sequence_no_elem, schema, path, obj) if obj.empty?
- errors << Kwalify::Errors.validate_error(:sequence_too_many, schema, path, obj) if obj.length > 1
+ end
+ #
+ if hash.key?('mapping')
+ val = hash['mapping']
+ if val != nil && !val.is_a?(Hash)
+ errors << Kwalify.validate_error(:mapping_notmap, rule, "#{path}/mapping", val)
+ elsif val == nil || val.empty?
+ errors << Kwalify.validate_error(:mapping_noelem, rule, "#{path}/mapping", val)
end
- elsif schema.name == "MAPPING"
- if !obj.is_a?(Hash)
- errors << Kwalify::Errors.validate_error(:mapping_not_map, schema, path, obj)
- else
- errors << Kwalify::Errors.validate_error(:mapping_no_elem, schema, path, obj) if obj.empty?
+ end
+ #
+ if type == 'seq'
+ errors << Kwalify.validate_error(:seq_nosequence, rule, path, nil) unless hash.key?('sequence')
+ #errors << Kwalify.validate_error(:seq_conflict, rule, path, 'enum:') if hash.key?('enum')
+ errors << Kwalify.validate_error(:seq_conflict, rule, path, 'pattern:') if hash.key?('pattern')
+ errors << Kwalify.validate_error(:seq_conflict, rule, path, 'mapping:') if hash.key?('mapping')
+ #errors << Kwalify.validate_error(:seq_conflict, rule, path, 'range:') if hash.key?('range')
+ errors << Kwalify.validate_error(:seq_conflict, rule, path, 'length:') if hash.key?('length')
+ elsif type == 'map'
+ errors << Kwalify.validate_error(:map_nomapping, rule, path, nil) unless hash.key?('mapping')
+ #errors << Kwalify.validate_error(:map_conflict, rule, path, 'enum:') if hash.key?('enum')
+ errors << Kwalify.validate_error(:map_conflict, rule, path, 'pattern:') if hash.key?('pattern')
+ errors << Kwalify.validate_error(:map_conflict, rule, path, 'sequence:') if hash.key?('sequence')
+ #errors << Kwalify.validate_error(:map_conflict, rule, path, 'range:') if hash.key?('range')
+ errors << Kwalify.validate_error(:map_conflict, rule, path, 'length:') if hash.key?('length')
+ else
+ errors << Kwalify.validate_error(:scalar_conflict, rule, path, 'sequence:') if hash.key?('sequence')
+ errors << Kwalify.validate_error(:scalar_conflict, rule, path, 'mapping:') if hash.key?('mapping')
+ if hash.key?('enum')
+ errors << Kwalify.validate_error(:enum_conflict, rule, path, 'range:') if hash.key?('range')
+ errors << Kwalify.validate_error(:enum_conflict, rule, path, 'length:') if hash.key?('length')
+ errors << Kwalify.validate_error(:enum_conflict, rule, path, 'pattern:') if hash.key?('pattern')
end
end
- }
- return validator
+
+ end # end of def validate_hook()
+
+ end # end of class MetaValidator
+
+
+ schema = YAML.load(META_SCHEMA)
+ META_VALIDATOR = MetaValidator.new(schema)
+
+ def self.meta_validator
+ return META_VALIDATOR
end
end
-