class Csvlint::Csvw::Column

Constants

ALL_VALUES_VALID
DATATYPE_FORMAT_VALIDATION
DATATYPE_PARSER
NO_ADDITIONAL_VALIDATION
NUMERIC_PARSER
REGEXP_VALIDATION

Attributes

about_url[R]
annotations[R]
datatype[R]
default[R]
id[R]
lang[R]
name[R]
null[R]
number[R]
ordered[R]
property_url[R]
required[R]
separator[R]
source_number[R]
suppress_output[R]
text_direction[R]
titles[R]
value_url[R]
virtual[R]

Public Class Methods

from_json(number, column_desc, base_url=nil, lang="und", inherited_properties={}) click to toggle source
# File lib/csvlint/csvw/column.rb, line 32
def self.from_json(number, column_desc, base_url=nil, lang="und", inherited_properties={})
  annotations = {}
  warnings = []
  column_properties = {}
  inherited_properties = inherited_properties.clone

  column_desc.each do |property,value|
    if property == "@type"
      raise Csvlint::Csvw::MetadataError.new("columns[#{number}].@type"), "@type of column is not 'Column'" if value != 'Column'
    else
      v, warning, type = Csvw::PropertyChecker.check_property(property, value, base_url, lang)
      warnings += Array(warning).map{ |w| Csvlint::ErrorMessage.new(w, :metadata, nil, nil, "#{property}: #{value}", nil) } unless warning.nil? || warning.empty?
      if type == :annotation
        annotations[property] = v
      elsif type == :common || type == :column
        column_properties[property] = v
      elsif type == :inherited
        inherited_properties[property] = v
      else
        warnings << Csvlint::ErrorMessage.new(:invalid_property, :metadata, nil, nil, "column: #{property}", nil)
      end
    end
  end

  return self.new(number, column_properties["name"],
    id: column_properties["@id"],
    datatype: inherited_properties["datatype"] || { "@id" => "http://www.w3.org/2001/XMLSchema#string" },
    lang: inherited_properties["lang"] || "und",
    null: inherited_properties["null"] || [""],
    property_url: column_desc["propertyUrl"],
    required: inherited_properties["required"] || false,
    separator: inherited_properties["separator"],
    titles: column_properties["titles"],
    virtual: column_properties["virtual"] || false,
    annotations: annotations,
    warnings: warnings
  )
end
new(number, name, id: nil, about_url: nil, datatype: { "@id" => "http://www.w3.org/2001/XMLSchema click to toggle source
# File lib/csvlint/csvw/column.rb, line 8
def initialize(number, name, id: nil, about_url: nil, datatype: { "@id" => "http://www.w3.org/2001/XMLSchema#string" }, default: "", lang: "und", null: [""], ordered: false, property_url: nil, required: false, separator: nil, source_number: nil, suppress_output: false, text_direction: :inherit, titles: {}, value_url: nil, virtual: false, annotations: [], warnings: [])
  @number = number
  @name = name
  @id = id
  @about_url = about_url
  @datatype = datatype
  @default = default
  @lang = lang
  @null = null
  @ordered = ordered
  @property_url = property_url
  @required = required
  @separator = separator
  @source_number = source_number || number
  @suppress_output = suppress_output
  @text_direction = text_direction
  @titles = titles
  @value_url = value_url
  @virtual = virtual
  @annotations = annotations
  reset
  @warnings += warnings
end

Private Class Methods

create_date_parser(type, warning) click to toggle source
# File lib/csvlint/csvw/column.rb, line 111
def create_date_parser(type, warning)
  return lambda { |value, format|
    format = Csvlint::Csvw::DateFormat.new(nil, type) if format.nil?
    v = format.parse(value)
    return nil, warning if v.nil?
    return v, nil
  }
end
create_regexp_based_parser(regexp, warning) click to toggle source
# File lib/csvlint/csvw/column.rb, line 120
def create_regexp_based_parser(regexp, warning)
  return lambda { |value, format|
    return nil, warning unless value =~ regexp
    return value, nil
  }
end
languages_match(l1, l2) click to toggle source
# File lib/csvlint/csvw/column.rb, line 127
def languages_match(l1, l2)
  return true if l1 == l2 || l1 == "und" || l2 == "und"
  return true if l1 =~ Regexp.new("^#{l2}-") || l2 =~ Regexp.new("^#{l1}-")
  return false
end

Public Instance Methods

parse(string_value, row=nil) click to toggle source
# File lib/csvlint/csvw/column.rb, line 92
def parse(string_value, row=nil)
  return nil if null.include? string_value
  string_values = @separator.nil? ? [string_value] : string_value.split(@separator)
  values = []
  string_values.each do |s|
    value, warning = DATATYPE_PARSER[@datatype["base"] || @datatype["@id"]].call(s, @datatype["format"])
    if warning.nil?
      values << value
    else
      build_errors(warning, :schema, row, @number, s, @datatype)
      values << s
    end
  end
  return values
end
validate(string_value, row=nil) click to toggle source
# File lib/csvlint/csvw/column.rb, line 78
def validate(string_value, row=nil)
  reset
  values = parse(string_value || "", row)
  # STDERR.puts "#{name} - #{string_value.inspect} - #{values.inspect}"
  values.each do |value|
    validate_required(value, row)
    validate_format(value, row)
    validate_length(value, row)
    validate_value(value, row)
  end unless values.nil?
  validate_required(values, row) if values.nil?
  return valid?
end
validate_header(header) click to toggle source
# File lib/csvlint/csvw/column.rb, line 71
def validate_header(header)
  reset
  valid_headers = @titles ? @titles.map{ |l,v| v if Column.languages_match(l, lang) }.flatten : []
  build_errors(:invalid_header, :schema, 1, @number, header, @titles) unless valid_headers.include? header
  return valid?
end

Private Instance Methods

validate_format(value, row) click to toggle source
# File lib/csvlint/csvw/column.rb, line 150
def validate_format(value, row)
  if datatype["format"]
    build_errors(:format, :schema, row, number, value, { "format" => datatype["format"] }) unless DATATYPE_FORMAT_VALIDATION[datatype["base"]].call(value, datatype["format"])
  end
end
validate_length(value, row) click to toggle source
# File lib/csvlint/csvw/column.rb, line 138
def validate_length(value, row)
  if datatype["length"] || datatype["minLength"] || datatype["maxLength"]
    length = value.length
    length = value.gsub(/==?$/,"").length * 3 / 4 if datatype["@id"] == "http://www.w3.org/2001/XMLSchema#base64Binary" || datatype["base"] == "http://www.w3.org/2001/XMLSchema#base64Binary"
    length = value.length / 2 if datatype["@id"] == "http://www.w3.org/2001/XMLSchema#hexBinary" || datatype["base"] == "http://www.w3.org/2001/XMLSchema#hexBinary"

    build_errors(:min_length, :schema, row, number, value, { "minLength" => datatype["minLength"] }) if datatype["minLength"] && length < datatype["minLength"]
    build_errors(:max_length, :schema, row, number, value, { "maxLength" => datatype["maxLength"] }) if datatype["maxLength"] && length > datatype["maxLength"]
    build_errors(:length, :schema, row, number, value, { "length" => datatype["length"] }) if datatype["length"] && length != datatype["length"]
  end
end
validate_required(value, row) click to toggle source
# File lib/csvlint/csvw/column.rb, line 134
def validate_required(value, row)
  build_errors(:required, :schema, row, number, value, { "required" => @required }) if @required && value.nil?
end
validate_value(value, row) click to toggle source
# File lib/csvlint/csvw/column.rb, line 156
def validate_value(value, row)
  build_errors(:min_inclusive, :schema, row, number, value, { "minInclusive" => datatype["minInclusive"] }) if datatype["minInclusive"] && value < datatype["minInclusive"]
  build_errors(:max_inclusive, :schema, row, number, value, { "maxInclusive" => datatype["maxInclusive"] }) if datatype["maxInclusive"] && value > datatype["maxInclusive"]
  build_errors(:min_exclusive, :schema, row, number, value, { "minExclusive" => datatype["minExclusive"] }) if datatype["minExclusive"] && value <= datatype["minExclusive"]
  build_errors(:max_exclusive, :schema, row, number, value, { "maxExclusive" => datatype["maxExclusive"] }) if datatype["maxExclusive"] && value >= datatype["maxExclusive"]
end