class Kwalify::Rule
Attributes
assert[R]
assert_proc[R]
classname[R]
classobj[R]
default[R]
desc[R]
enum[R]
ident[R]
length[R]
mapping[R]
name[R]
parent[RW]
pattern[R]
range[R]
regexp[R]
required[R]
sequence[R]
type[R]
type_class[R]
unique[R]
Public Class Methods
new(hash=nil, parent=nil)
click to toggle source
# File lib/kwalify/rule.rb, line 40 def initialize(hash=nil, parent=nil) _init(hash, "", {}) if hash @parent = parent end
Public Instance Methods
_init(hash, path="", rule_table={})
click to toggle source
# File lib/kwalify/rule.rb, line 46 def _init(hash, path="", rule_table={}) unless hash.is_a?(Hash) #* key=:schema_notmap msg="schema definition is not a mapping." raise Kwalify.schema_error(:schema_notmap, nil, (!path || path.empty? ? "/" : path), nil) end rule = self rule_table[hash.__id__] = rule ## 'type:' entry curr_path = "#{path}/type" _init_type_value(hash['type'], rule, curr_path) ## other entries hash.each do |key, val| curr_path = "#{path}/#{key}" sym = key.intern method = get_init_method(sym) unless method #* key=:key_unknown msg="unknown key." raise schema_error(:key_unknown, rule, curr_path, "#{key}:") end if sym == :sequence || sym == :mapping __send__(method, val, rule, curr_path, rule_table) else __send__(method, val, rule, curr_path) end end _check_confliction(hash, rule, path) return self end
Protected Instance Methods
_inspect(str="", level=0, done={})
click to toggle source
def inspect()
str = ""; level = 0; done = {} _inspect(str, level, done) return str
end
# File lib/kwalify/rule.rb, line 473 def _inspect(str="", level=0, done={}) done[self.__id__] = true str << " " * level << "name: #{@name}\n" unless @name.nil? str << " " * level << "desc: #{@desc}\n" unless @desc.nil? str << " " * level << "type: #{@type}\n" unless @type.nil? str << " " * level << "klass: #{@type_class.name}\n" unless @type_class.nil? str << " " * level << "required: #{@required}\n" unless @required.nil? str << " " * level << "pattern: #{@regexp.inspect}\n" unless @pattern.nil? str << " " * level << "assert: #{@assert}\n" unless @assert.nil? str << " " * level << "ident: #{@ident}\n" unless @ident.nil? str << " " * level << "unique: #{@unique}\n" unless @unique.nil? if !@enum.nil? str << " " * level << "enum:\n" @enum.each do |item| str << " " * (level+1) << "- #{item}\n" end end if !@range.nil? str << " " * level str << "range: { " colon = "" %w[max max-ex min min-ex].each do |key| val = @range[key] unless val.nil? str << colon << "#{key}: #{val.inspect}" colon = ", " end end str << " }\n" end if !@length.nil? str << " " * level str << "length: { " colon = "" %w[max max-ex min min-ex].each do |key| val = @length[key] if !val.nil? str << colon << "#{key}: #{val.inspect}" colon = ", " end end str << " }\n" end @sequence.each do |rule| if done[rule.__id__] str << " " * (level+1) << "- ...\n" else str << " " * (level+1) << "- \n" rule._inspect(str, level+2, done) end end if @sequence @mapping.each do |key, rule| if done[rule.__id__] str << ' ' * (level+1) << '"' << key << "\": ...\n" else str << ' ' * (level+1) << '"' << key << "\":\n" rule._inspect(str, level+2, done) end end if @mapping return str end
get_init_method(sym)
click to toggle source
# File lib/kwalify/rule.rb, line 86 def get_init_method(sym) @_dispatch_table ||= @@dispatch_table return @_dispatch_table[sym] end
Private Instance Methods
_check_confliction(hash, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 427 def _check_confliction(hash, rule, path) if @type == 'seq' #* key=:seq_nosequence msg="type 'seq' requires 'sequence:'." raise schema_error(:seq_nosequence, rule, path, nil) unless hash.key?('sequence') #* key=:seq_conflict msg="not available with sequence." raise schema_error(:seq_conflict, rule, path, 'enum:') if @enum raise schema_error(:seq_conflict, rule, path, 'pattern:') if @pattern raise schema_error(:seq_conflict, rule, path, 'mapping:') if @mapping raise schema_error(:seq_conflict, rule, path, 'range:') if @range raise schema_error(:seq_conflict, rule, path, 'length:') if @length elsif @type == 'map' #* key=:map_nomapping msg="type 'map' requires 'mapping:'." raise schema_error(:map_nomapping, rule, path, nil) unless hash.key?('mapping') #* key=:map_conflict msg="not available with mapping." raise schema_error(:map_conflict, rule, path, 'enum:') if @enum raise schema_error(:map_conflict, rule, path, 'pattern:') if @pattern raise schema_error(:map_conflict, rule, path, 'sequence:') if @sequence raise schema_error(:map_conflict, rule, path, 'range:') if @range raise schema_error(:map_conflict, rule, path, 'length:') if @length else #* key=:scalar_conflict msg="not available with scalar type." raise schema_error(:scalar_conflict, rule, path, 'sequence:') if @sequence raise schema_error(:scalar_conflict, rule, path, 'mapping:') if @mapping if @enum #* key=:enum_conflict msg="not available with 'enum:'." raise schema_error(:enum_conflict, rule, path, 'range:') if @range raise schema_error(:enum_conflict, rule, path, 'length:') if @length raise schema_error(:enum_conflict, rule, path, 'pattern:') if @pattern end unless @default.nil? #* key=:default_conflict msg="not available when 'required:' is true." raise schema_error(:default_conflict, rule, path, 'default:') if @required end end end
_init_assert_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 197 def _init_assert_value(val, rule, path) @assert = val unless val.is_a?(String) #* key=:assert_notstr msg="not a string." raise schema_error(:assert_notstr, rule, path, val) end unless val =~ /\bval\b/ #* key=:assert_noval msg="'val' is not used." raise schema_error(:assert_noval, rule, path, val) end begin @assert_proc = eval "proc { |val| #{val} }" rescue ::SyntaxError => ex #* key=:assert_syntaxerr msg="expression syntax error." raise schema_error(:assert_syntaxerr, rule, path, val) end end
_init_class_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 116 def _init_class_value(val, rule, path) @classname = val unless @type == 'map' #* key=:class_notmap msg="available only with map type." raise schema_error(:class_notmap, rule, path, 'class:') end begin @classobj = Util.get_class(val) rescue NameError @classobj = nil end end
_init_default_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 358 def _init_default_value(val, rule, path) @default = val unless Types.scalar?(val) #* key=:default_nonscalarval msg="not a scalar." raise schema_error(:default_nonscalarval, rule, path, val) end if @type == 'map' || @type == 'seq' #* key=:default_notscalar msg="is available only with a scalar type." raise schema_error(:default_notscalar, rule, File.dirname(path), "default:") end unless val.nil? || val.is_a?(@type_class) #* key=:default_unmatch msg="not a %s." raise schema_error(:default_unmatch, rule, path, val, [Kwalify.word(@type)]) end end
_init_desc_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 135 def _init_desc_value(val, rule, path) @desc = val end
_init_enum_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 172 def _init_enum_value(val, rule, path) @enum = val unless val.is_a?(Array) #* key=:enum_notseq msg="not a sequence." raise schema_error(:enum_notseq, rule, path, val) end if Types.collection_type?(@type) # unless Kwalify.scalar_class?(@type_class) #* key=:enum_notscalar msg="not available with seq or map." raise schema_error(:enum_notscalar, rule, File.dirname(path), 'enum:') end elem_table = {} @enum.each do |elem| unless elem.is_a?(@type_class) #* key=:enum_type_unmatch msg="%s type expected." raise schema_error(:enum_type_unmatch, rule, path, elem, [Kwalify.word(@type)]) end if elem_table[elem] #* key=:enum_duplicate msg="duplicated enum value." raise schema_error(:enum_duplicate, rule, path, elem.to_s) end elem_table[elem] = true end end
_init_ident_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 319 def _init_ident_value(val, rule, path) @ident = val @required = true unless val.is_a?(Boolean) #* key=:ident_notbool msg="not a boolean." raise schema_error(:ident_notbool, rule, path, val) end if @type == 'map' || @type == 'seq' #* key=:ident_notscalar msg="is available only with a scalar type." raise schema_error(:ident_notscalar, rule, File.dirname(path), "ident:") end if File.dirname(path) == "/" #* key=:ident_onroot msg="is not available on root element." raise schema_error(:ident_onroot, rule, "/", "ident:") end unless @parent && @parent.type == 'map' #* key=:ident_notmap msg="is available only with an element of mapping." raise schema_error(:ident_notmap, rule, File.dirname(path), "ident:") end end
_init_length_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 268 def _init_length_value(val, rule, path) @length = val unless val.is_a?(Hash) #* key=:length_notmap msg="not a mapping." raise schema_error(:length_notmap, rule, path, val) end unless @type == 'str' || @type == 'text' #* key=:length_nottext msg="is available only with string or text." raise schema_error(:length_nottext, rule, File.dirname(path), 'length:') end val.each do |k, v| case k when 'max', 'min', 'max-ex', 'min-ex' unless v.is_a?(Integer) #* key=:length_notint msg="not an integer." raise schema_error(:length_notint, rule, "#{path}/#{k}", v) end else #* key=:length_undefined msg="undefined key." raise schema_error(:length_undefined, rule, "#{path}/#{k}", "#{k}:") end end if val.key?('max') && val.key?('max-ex') #* key=:length_twomax msg="both 'max' and 'max-ex' are not available at once." raise schema_error(:length_twomax, rule, path, nil) end if val.key?('min') && val.key?('min-ex') #* key=:length_twomin msg="both 'min' and 'min-ex' are not available at once." raise schema_error(:length_twomin, rule, path, nil) end max, min, max_ex, min_ex = val['max'], val['min'], val['max-ex'], val['min-ex'] if max if min && max < min #* key=:length_maxltmin msg="max '%s' is less than min '%s'." raise validate_error(:length_maxltmin, rule, path, nil, [max, min]) elsif min_ex && max <= min_ex #* key=:length_maxleminex msg="max '%s' is less than or equal to min-ex '%s'." raise validate_error(:length_maxleminex, rule, path, nil, [max, min_ex]) end elsif max_ex if min && max_ex <= min #* key=:length_maxexlemin msg="max-ex '%s' is less than or equal to min '%s'." raise validate_error(:length_maxexlemin, rule, path, nil, [max_ex, min]) elsif min_ex && max_ex <= min_ex #* key=:length_maxexleminex msg="max-ex '%s' is less than or equal to min-ex '%s'." raise validate_error(:length_maxexleminex, rule, path, nil, [max_ex, min_ex]) end end end
_init_mapping_value(val, rule, path, rule_table)
click to toggle source
# File lib/kwalify/rule.rb, line 396 def _init_mapping_value(val, rule, path, rule_table) if !val.nil? && !val.is_a?(Hash) #* key=:mapping_notmap msg="not a mapping." raise schema_error(:mapping_notmap, rule, path, val) elsif val.nil? || (val.empty? && !val.default) #* key=:mapping_noelem msg="required at least one element." raise schema_error(:mapping_noelem, rule, path, val) else @mapping = {} if val.default elem = val.default # hash rule = rule_table[elem.__id__] rule ||= Rule.new(nil, self)._init(elem, "#{path}/=", rule_table) @mapping.default = rule end val.each do |k, v| ##* key=:key_duplicate msg="key duplicated." #raise schema_error(:key_duplicate, rule, path, key) if @mapping.key?(key) v ||= {} rule = rule_table[v.__id__] rule ||= Rule.new(nil, self)._init(v, "#{path}/#{k}", rule_table) if k == '=' @mapping.default = rule else @mapping[k] = rule end end if val end end
_init_name_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 130 def _init_name_value(val, rule, path) @name = val end
_init_pattern_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 149 def _init_pattern_value(val, rule, path) @pattern = val unless val.is_a?(String) || val.is_a?(Regexp) #* key=:pattern_notstr msg="not a string (or regexp)" raise schema_error(:pattern_notstr, rule, path, val) end unless val =~ /\A\/(.*)\/([mi]?[mi]?)\z/ #* key=:pattern_notmatch msg="should be '/..../'." raise schema_error(:pattern_notmatch, rule, path, val) end pat = $1; opt = $2 flag = 0 flag += Regexp::IGNORECASE if opt.include?("i") flag += Regexp::MULTILINE if opt.include?("m") begin @regexp = Regexp.compile(pat, flag) rescue RegexpError => ex #* key=:pattern_syntaxerr msg="has regexp error." raise schema_error(:pattern_syntaxerr, rule, path, val) end end
_init_range_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 216 def _init_range_value(val, rule, path) @range = val unless val.is_a?(Hash) #* key=:range_notmap msg="not a mapping." raise schema_error(:range_notmap, rule, path, val) end if Types.collection_type?(@type) || @type == 'bool' #* key=:range_notscalar msg="is available only with scalar type." raise schema_error(:range_notscalar, rule, File.dirname(path), 'range:') end val.each do |k, v| case k when 'max', 'min', 'max-ex', 'min-ex' unless v.is_a?(@type_class) typename = Kwalify.word(@type) || @type #* key=:range_type_unmatch msg="not a %s." raise schema_error(:range_type_unmatch, rule, "#{path}/#{k}", v, [typename]) end else #* key=:range_undefined msg="undefined key." raise schema_error(:range_undefined, rule, "#{path}/#{k}", "#{k}:") end end if val.key?('max') && val.key?('max-ex') #* key=:range_twomax msg="both 'max' and 'max-ex' are not available at once." raise schema_error(:range_twomax, rule, path, nil) end if val.key?('min') && val.key?('min-ex') #* key=:range_twomin msg="both 'min' and 'min-ex' are not available at once." raise schema_error(:range_twomin, rule, path, nil) end max, min, max_ex, min_ex = val['max'], val['min'], val['max-ex'], val['min-ex'] if max if min && max < min #* key=:range_maxltmin msg="max '%s' is less than min '%s'." raise validate_error(:range_maxltmin, rule, path, nil, [max, min]) elsif min_ex && max <= min_ex #* key=:range_maxleminex msg="max '%s' is less than or equal to min-ex '%s'." raise validate_error(:range_maxleminex, rule, path, nil, [max, min_ex]) end elsif max_ex if min && max_ex <= min #* key=:range_maxexlemin msg="max-ex '%s' is less than or equal to min '%s'." raise validate_error(:range_maxexlemin, rule, path, nil, [max_ex, min]) elsif min_ex && max_ex <= min_ex #* key=:range_maxexleminex msg="max-ex '%s' is less than or equal to min-ex '%s'." raise validate_error(:range_maxexleminex, rule, path, nil, [max_ex, min_ex]) end end end
_init_required_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 140 def _init_required_value(val, rule, path) @required = val unless val.is_a?(Boolean) #|| val.nil? #* key=:required_notbool msg="not a boolean." raise schema_error(:required_notbool, rule, path, val) end end
_init_sequence_value(val, rule, path, rule_table)
click to toggle source
# File lib/kwalify/rule.rb, line 375 def _init_sequence_value(val, rule, path, rule_table) if !val.nil? && !val.is_a?(Array) #* key=:sequence_notseq msg="not a sequence." raise schema_error(:sequence_notseq, rule, path, val) elsif val.nil? || val.empty? #* key=:sequence_noelem msg="required one element." raise schema_error(:sequence_noelem, rule, path, val) elsif val.length > 1 #* key=:sequence_toomany msg="required just one element." raise schema_error(:sequence_toomany, rule, path, val) else elem = val[0] elem ||= {} i = 0 # or 1? *index* rule = rule_table[elem.__id__] rule ||= Rule.new(nil, self)._init(elem, "#{path}/#{i}", rule_table) @sequence = [ rule ] end end
_init_type_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 95 def _init_type_value(val, rule, path) @type = val @type = Types::DEFAULT_TYPE if @type.nil? unless @type.is_a?(String) #* key=:type_notstr msg="not a string." raise schema_error(:type_notstr, rule, path, @type.to_s) end @type_class = Types.type_class(@type) #if @type_class.nil? # begin # @type_class = Kernel.const_get(@type) # rescue NameError # end #end unless @type_class #* key=:type_unknown msg="unknown type." raise schema_error(:type_unknown, rule, path, @type.to_s) end end
_init_unique_value(val, rule, path)
click to toggle source
# File lib/kwalify/rule.rb, line 341 def _init_unique_value(val, rule, path) @unique = val unless val.is_a?(Boolean) #* key=:unique_notbool msg="not a boolean." raise schema_error(:unique_notbool, rule, path, val) end if @type == 'map' || @type == 'seq' #* key=:unique_notscalar msg="is available only with a scalar type." raise schema_error(:unique_notscalar, rule, File.dirname(path), "unique:") end if File.dirname(path) == "/" #* key=:unique_onroot msg="is not available on root element." raise schema_error(:unique_onroot, rule, "/", "unique:") end end