anodator 0.0.1
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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +28 -0
- data/LICENSE.txt +20 -0
- data/README.ja.rdoc +33 -0
- data/README.rdoc +41 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/example/example_01.rb +129 -0
- data/lib/anodator/anodator_error.rb +5 -0
- data/lib/anodator/check_result.rb +41 -0
- data/lib/anodator/checker.rb +58 -0
- data/lib/anodator/input_spec.rb +199 -0
- data/lib/anodator/input_spec_item.rb +33 -0
- data/lib/anodator/message.rb +59 -0
- data/lib/anodator/output_spec.rb +164 -0
- data/lib/anodator/rule.rb +97 -0
- data/lib/anodator/rule_set.rb +52 -0
- data/lib/anodator/utils.rb +234 -0
- data/lib/anodator/validator/base.rb +168 -0
- data/lib/anodator/validator/blank_validator.rb +14 -0
- data/lib/anodator/validator/complex_validator.rb +60 -0
- data/lib/anodator/validator/configuration_error.rb +8 -0
- data/lib/anodator/validator/date_validator.rb +151 -0
- data/lib/anodator/validator/format_validator.rb +48 -0
- data/lib/anodator/validator/inclusion_validator.rb +21 -0
- data/lib/anodator/validator/length_validator.rb +37 -0
- data/lib/anodator/validator/numeric_validator.rb +46 -0
- data/lib/anodator/validator/presence_validator.rb +14 -0
- data/lib/anodator/validator.rb +10 -0
- data/lib/anodator.rb +3 -0
- data/spec/anodator/check_result_spec.rb +101 -0
- data/spec/anodator/checker_spec.rb +273 -0
- data/spec/anodator/input_spec_item_spec.rb +100 -0
- data/spec/anodator/input_spec_spec.rb +584 -0
- data/spec/anodator/message_spec.rb +112 -0
- data/spec/anodator/output_spec_spec.rb +355 -0
- data/spec/anodator/rule_set_spec.rb +190 -0
- data/spec/anodator/rule_spec.rb +169 -0
- data/spec/anodator/validator/base_spec.rb +214 -0
- data/spec/anodator/validator/blank_validator_spec.rb +52 -0
- data/spec/anodator/validator/complex_validator_spec.rb +268 -0
- data/spec/anodator/validator/date_validator_spec.rb +350 -0
- data/spec/anodator/validator/format_validator_spec.rb +158 -0
- data/spec/anodator/validator/inclusion_validator_spec.rb +77 -0
- data/spec/anodator/validator/length_validator_spec.rb +236 -0
- data/spec/anodator/validator/numeric_validator_spec.rb +468 -0
- data/spec/anodator/validator/presence_validator_spec.rb +52 -0
- data/spec/anodator/validator_spec.rb +16 -0
- data/spec/anodator_spec.rb +2 -0
- data/spec/spec_helper.rb +12 -0
- metadata +188 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
require "anodator/anodator_error"
|
2
|
+
|
3
|
+
module Anodator
|
4
|
+
class UnknownMessageAttributeError < AnodatorError ; end
|
5
|
+
|
6
|
+
# Message is error message builder.
|
7
|
+
#
|
8
|
+
# Message is generated with formated string for expand several keywords.
|
9
|
+
# Message#expand method is expand keywords by data_provider suppried by parameter.
|
10
|
+
class Message < String
|
11
|
+
# message
|
12
|
+
attr_reader :template
|
13
|
+
|
14
|
+
def initialize(template_message)
|
15
|
+
@template = template_message.to_s
|
16
|
+
|
17
|
+
if @template.split(//).size.zero?
|
18
|
+
raise ArgumentError.new("template_message cannot be blank")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# expand message with data_provider
|
23
|
+
#
|
24
|
+
# message keyword is expressed +[[target_expression::attribute]]+.
|
25
|
+
# data_provider is data source for current check target.
|
26
|
+
#
|
27
|
+
# - target_expression: specify target.
|
28
|
+
# - attribute: actual printed value
|
29
|
+
# - name: target name
|
30
|
+
# - number: target number
|
31
|
+
# - value: target actual data
|
32
|
+
def expand(data_provider)
|
33
|
+
@template.gsub(/\[\[([^:]+)::([^\]]+)\]\]/) do
|
34
|
+
spec_item = data_provider.spec_item_by_expression($1)
|
35
|
+
case $2
|
36
|
+
when "name"
|
37
|
+
spec_item.name
|
38
|
+
when "number"
|
39
|
+
spec_item.number
|
40
|
+
when "value"
|
41
|
+
data_provider[$1]
|
42
|
+
else
|
43
|
+
raise UnknownMessageAttributeError.new("Unknown message attribute '#{$2}'")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_configuration
|
49
|
+
@template.gsub(/\[\[([^:]+)::([^\]]+)\]\]/) do
|
50
|
+
Validator::Base.values.spec_item_by_expression($1)
|
51
|
+
unless %W(name number value).include?($2)
|
52
|
+
raise UnknownMessageAttributeError.new("Unknown message attribute '#{$2}'")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
rescue UnknownTargetExpressionError, UnknownMessageAttributeError => e
|
56
|
+
raise InvalidConfiguration.new(e.to_s)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module Anodator
|
2
|
+
class OutputSpec
|
3
|
+
TARGET_DATA = "DATA"
|
4
|
+
TARGET_ERROR = "ERROR"
|
5
|
+
|
6
|
+
VALID_SYMBOL_ITEMS = [
|
7
|
+
:target_numbers,
|
8
|
+
:target_names,
|
9
|
+
:target_values,
|
10
|
+
:error_message,
|
11
|
+
:error_level,
|
12
|
+
:error_count,
|
13
|
+
:warning_count,
|
14
|
+
:error_and_warning_count,
|
15
|
+
]
|
16
|
+
|
17
|
+
attr_reader :items, :target, :include_no_error
|
18
|
+
attr_accessor :separator, :value_separator
|
19
|
+
|
20
|
+
def initialize(items = [], options = { })
|
21
|
+
@items = items.to_a
|
22
|
+
@target = TARGET_ERROR
|
23
|
+
@include_no_error = false
|
24
|
+
@separator = " "
|
25
|
+
@value_separator = ""
|
26
|
+
|
27
|
+
options.each do |key, opt|
|
28
|
+
case key
|
29
|
+
when :target
|
30
|
+
@target = opt
|
31
|
+
when :include_no_error
|
32
|
+
@include_no_error = !!opt
|
33
|
+
when :separator, :value_separator
|
34
|
+
@separator = opt.to_s
|
35
|
+
else
|
36
|
+
raise ArgumentError.new("unknown option #{key}.")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
unless [TARGET_DATA, TARGET_ERROR].include?(@target)
|
41
|
+
raise ArgumentError.new("unknown target option value #{@target}.")
|
42
|
+
end
|
43
|
+
|
44
|
+
check_items
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_configuration
|
48
|
+
@items.each do |item|
|
49
|
+
if item.is_a? String
|
50
|
+
Validator::Base.values.spec_item_at_by_number(item)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
rescue UnknownTargetExpressionError => e
|
54
|
+
raise InvalidConfiguration.new(e.to_s)
|
55
|
+
end
|
56
|
+
|
57
|
+
def check_items
|
58
|
+
@items.each do |item|
|
59
|
+
if item.is_a? Symbol
|
60
|
+
unless VALID_SYMBOL_ITEMS.include?(item)
|
61
|
+
raise ArgumentError.new("unknown item symbol #{item}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
private :check_items
|
67
|
+
|
68
|
+
def generate(input_spec_with_values, check_results)
|
69
|
+
if @target == TARGET_DATA
|
70
|
+
generate_data(input_spec_with_values, check_results)
|
71
|
+
else # @target == TARGET_ERROR
|
72
|
+
generate_error(input_spec_with_values, check_results)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def generate_data(input_spec_with_values, check_results)
|
77
|
+
buf = []
|
78
|
+
buf << @items.map do |item|
|
79
|
+
if item.is_a? Symbol
|
80
|
+
case item
|
81
|
+
when :error_count
|
82
|
+
next check_results.map { |result|
|
83
|
+
result.error? ? true : nil
|
84
|
+
}.compact.size.to_s
|
85
|
+
when :warning_count
|
86
|
+
next check_results.map { |result|
|
87
|
+
result.warning? ? true : nil
|
88
|
+
}.compact.size.to_s
|
89
|
+
when :error_and_warning_count
|
90
|
+
next check_results.size.to_s
|
91
|
+
else
|
92
|
+
next ""
|
93
|
+
end
|
94
|
+
else # data
|
95
|
+
next input_spec_with_values[item]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
return buf
|
100
|
+
end
|
101
|
+
private :generate_data
|
102
|
+
|
103
|
+
def generate_error(input_spec_with_values, check_results)
|
104
|
+
buf = []
|
105
|
+
|
106
|
+
if check_results.size.zero?
|
107
|
+
if @include_no_error
|
108
|
+
buf << @items.map do |item|
|
109
|
+
if item.is_a? Symbol
|
110
|
+
case item
|
111
|
+
when :error_count, :warning_count, :error_and_warning_count
|
112
|
+
next "0"
|
113
|
+
else
|
114
|
+
next ""
|
115
|
+
end
|
116
|
+
else # data
|
117
|
+
next input_spec_with_values[item]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
else
|
122
|
+
check_results.each do |check_result|
|
123
|
+
buf << @items.map do |item|
|
124
|
+
if item.is_a? Symbol
|
125
|
+
case item
|
126
|
+
when :target_numbers
|
127
|
+
next check_result.target_numbers.join(@separator)
|
128
|
+
when :target_names
|
129
|
+
next check_result.target_numbers.map { |number|
|
130
|
+
input_spec_with_values.spec_item_at_by_number(number).name
|
131
|
+
}.join(@separator)
|
132
|
+
when :target_values
|
133
|
+
next check_result.target_numbers.map { |number|
|
134
|
+
input_spec_with_values[number]
|
135
|
+
}.join(@value_separator)
|
136
|
+
when :error_message
|
137
|
+
next check_result.message
|
138
|
+
when :error_level
|
139
|
+
next check_result.level.to_s
|
140
|
+
when :error_count
|
141
|
+
next check_results.map { |result|
|
142
|
+
result.error? ? true : nil
|
143
|
+
}.compact.size.to_s
|
144
|
+
when :warning_count
|
145
|
+
next check_results.map { |result|
|
146
|
+
result.warning? ? true : nil
|
147
|
+
}.compact.size.to_s
|
148
|
+
when :error_and_warning_count
|
149
|
+
next check_results.size.to_s
|
150
|
+
else
|
151
|
+
next ""
|
152
|
+
end
|
153
|
+
else # data
|
154
|
+
next input_spec_with_values[item]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
return buf
|
161
|
+
end
|
162
|
+
private :generate_error
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require "anodator/message"
|
2
|
+
require "anodator/validator"
|
3
|
+
require "anodator/check_result"
|
4
|
+
|
5
|
+
module Anodator
|
6
|
+
# Check rule
|
7
|
+
#
|
8
|
+
# Rule has target expressions, prerequisite, validator and message.
|
9
|
+
# "Prerequisite" is represented by the Validator.
|
10
|
+
class Rule
|
11
|
+
# Check level ERROR
|
12
|
+
LEVEL_ERROR = 2
|
13
|
+
# Check level WARNING
|
14
|
+
LEVEL_WARNING = 1
|
15
|
+
|
16
|
+
attr_reader :target_expressions, :message, :validator, :prerequisite, :level, :description
|
17
|
+
|
18
|
+
def initialize(target_expressions, message, validator, prerequisite = nil, level = LEVEL_ERROR, description = nil)
|
19
|
+
@target_expressions = target_expressions.to_a
|
20
|
+
@message = message
|
21
|
+
@validator = validator
|
22
|
+
@prerequisite = prerequisite
|
23
|
+
@level = level
|
24
|
+
@description = description
|
25
|
+
|
26
|
+
if @target_expressions.size.zero?
|
27
|
+
raise ArgumentError.new("target expressions cannot be blank")
|
28
|
+
end
|
29
|
+
if @message.nil?
|
30
|
+
raise ArgumentError.new("message cannot be blank")
|
31
|
+
end
|
32
|
+
if @validator.nil?
|
33
|
+
raise ArgumentError.new("validator cannot be blank")
|
34
|
+
end
|
35
|
+
unless [LEVEL_ERROR, LEVEL_WARNING].include?(@level)
|
36
|
+
raise ArgumentError.new("level must be ERROR or WARNING")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# check values depend on prerequisite and validator
|
41
|
+
#
|
42
|
+
# When invalid, return CheckResult object, but when valid
|
43
|
+
# return nil.
|
44
|
+
def check
|
45
|
+
unless @prerequisite.nil?
|
46
|
+
unless @prerequisite.valid?
|
47
|
+
return nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if @validator.valid?
|
52
|
+
return nil
|
53
|
+
else
|
54
|
+
numbers = @target_expressions.map do |target_expression|
|
55
|
+
Validator::Base.values.spec_item_by_expression(target_expression).number
|
56
|
+
end
|
57
|
+
|
58
|
+
CheckResult.new(numbers,
|
59
|
+
@message.expand(Validator::Base.values),
|
60
|
+
@level)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate_configuration
|
65
|
+
@target_expressions.each do |target_expression|
|
66
|
+
Validator::Base.values.spec_item_by_expression(target_expression)
|
67
|
+
end
|
68
|
+
@message.validate_configuration
|
69
|
+
@validator.validate_configuration
|
70
|
+
@prerequisite.validate_configuration unless @prerequisite.nil?
|
71
|
+
rescue UnknownTargetExpressionError => e
|
72
|
+
raise InvalidConfiguration.new(e.to_s)
|
73
|
+
end
|
74
|
+
|
75
|
+
def level_expression
|
76
|
+
if @level == LEVEL_ERROR
|
77
|
+
return "ERROR"
|
78
|
+
elsif @level == LEVEL_WARNING
|
79
|
+
return "WARNING"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_s
|
84
|
+
target_names = @target_expressions.map { |te| Validator::Base.values.spec_item_by_expression(te).name }.join(",")
|
85
|
+
buf =<<_EOD_
|
86
|
+
Description: #{@description.nil? ? "None." : @description}
|
87
|
+
Targets: #{target_names}
|
88
|
+
Message: #{@message.template}
|
89
|
+
Level: #{level_expression}
|
90
|
+
Validator:
|
91
|
+
#{@validator.to_s}
|
92
|
+
Prerequisite:
|
93
|
+
#{@prerequisite.nil? ? " - (None)" : @prerequisite.to_s}
|
94
|
+
_EOD_
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "anodator/rule"
|
2
|
+
|
3
|
+
module Anodator
|
4
|
+
class RuleSet
|
5
|
+
def initialize
|
6
|
+
@rules = []
|
7
|
+
@results = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_rule(rule)
|
11
|
+
if rule.is_a? Rule
|
12
|
+
@rules << rule
|
13
|
+
else
|
14
|
+
raise ArgumentError.new("rule must be Anodator::Rule object")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method :<<, :add_rule
|
19
|
+
|
20
|
+
def check_all
|
21
|
+
@results = []
|
22
|
+
|
23
|
+
if @rules.count.zero?
|
24
|
+
return false
|
25
|
+
else
|
26
|
+
@rules.each do |rule|
|
27
|
+
if result = rule.check
|
28
|
+
@results << result
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def results
|
37
|
+
return @results
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_configuration
|
41
|
+
@rules.each do |rule|
|
42
|
+
rule.validate_configuration
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
@rules.map { |rule|
|
48
|
+
rule.to_s
|
49
|
+
}.join("\n")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,234 @@
|
|
1
|
+
require "csv"
|
2
|
+
|
3
|
+
module Anodator
|
4
|
+
module Utils
|
5
|
+
# load input_spec from csv file
|
6
|
+
#
|
7
|
+
# File encoding: UTF-8
|
8
|
+
# Columns:
|
9
|
+
# - column identification(string)
|
10
|
+
# - column name(string)
|
11
|
+
# - column type(STRING, NUMERIC or DATE, default is STRING)
|
12
|
+
# Arguments:
|
13
|
+
# - file_path: file path for input spec.
|
14
|
+
# Return:
|
15
|
+
# InputSpec instance
|
16
|
+
def self.load_input_spec_from_csv_file(file_path)
|
17
|
+
first = true
|
18
|
+
header = nil
|
19
|
+
spec = []
|
20
|
+
CSV.open(file_path, "r") do |row|
|
21
|
+
# skip header
|
22
|
+
if first
|
23
|
+
header = row
|
24
|
+
first = false
|
25
|
+
next
|
26
|
+
end
|
27
|
+
spec << { :number => row[0], :name => row[1], :type => row[2] }
|
28
|
+
end
|
29
|
+
|
30
|
+
return InputSpec.new(spec)
|
31
|
+
end
|
32
|
+
|
33
|
+
# load output_spec from csv file
|
34
|
+
#
|
35
|
+
# When target is TARGET_ERROR generate output line by one error,
|
36
|
+
# when target is TARGET_DATA generate output line by one data.
|
37
|
+
# When set include_no_error is true and target is TARGET_DATA,
|
38
|
+
# generate output line has no error.
|
39
|
+
#
|
40
|
+
# File encoding: UTF-8
|
41
|
+
# Columns:
|
42
|
+
# - output column identification(string)
|
43
|
+
# - output special column(string)
|
44
|
+
# - target_numbers(for error)
|
45
|
+
# - target_names(for one error)
|
46
|
+
# - target_values(for one error)
|
47
|
+
# - error_message(for one error)
|
48
|
+
# - error_level(for one error)
|
49
|
+
# - error_count(for one error)
|
50
|
+
# - warning_count(for one data)
|
51
|
+
# - error_and_warning_count(for one data)
|
52
|
+
# Arguments:
|
53
|
+
# - file_path: file path for output spec.
|
54
|
+
# - target: OutputSpec::TARGET_ERROR or OutputSpec::TARGET_DATA
|
55
|
+
# - include_no_error: true or false(default false)
|
56
|
+
# Return:
|
57
|
+
# OutputSpec instance
|
58
|
+
def self.load_output_spec_from_csv_file(file_path,
|
59
|
+
target = Anodator::OutputSpec::TARGET_ERROR,
|
60
|
+
include_no_error = false)
|
61
|
+
first = true
|
62
|
+
header = nil
|
63
|
+
spec = []
|
64
|
+
CSV.open(file_path, "r") do |row|
|
65
|
+
# skip header
|
66
|
+
if first
|
67
|
+
header = row
|
68
|
+
first = false
|
69
|
+
next
|
70
|
+
end
|
71
|
+
if row.first.nil? || row.first.split(//).length.zero?
|
72
|
+
spec << row.last.to_sym
|
73
|
+
else
|
74
|
+
spec << row.first.to_s
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
return Anodator::OutputSpec.new(spec, :target => target, :include_no_error => include_no_error)
|
79
|
+
end
|
80
|
+
|
81
|
+
# options reader for option values for validator specs
|
82
|
+
#
|
83
|
+
# When value is 'true' or 'false', convert true or false instance.
|
84
|
+
# The others set to string.
|
85
|
+
#
|
86
|
+
# Arguments:
|
87
|
+
# - row: validator line string
|
88
|
+
# - options: default options
|
89
|
+
# - options_index_from: index for option column be started on row(default: 4)
|
90
|
+
# Return:
|
91
|
+
# Hash
|
92
|
+
def self.options_reader(row, options = { }, options_index_from = 4)
|
93
|
+
if row.size > options_index_from
|
94
|
+
row[options_index_from..-1].each do |column|
|
95
|
+
next if column.nil?
|
96
|
+
key, value = column.split(":", 2)
|
97
|
+
case value
|
98
|
+
when "true", "false"
|
99
|
+
options[key.to_sym] = eval(value)
|
100
|
+
else
|
101
|
+
options[key.to_sym] = value
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
return options
|
107
|
+
end
|
108
|
+
|
109
|
+
# load validators from csv file
|
110
|
+
#
|
111
|
+
# File encoding: UTF-8
|
112
|
+
# Columns:
|
113
|
+
# - validator identification(string)
|
114
|
+
# - validation name(string)
|
115
|
+
# - validator type(string)
|
116
|
+
# - target expression(string)
|
117
|
+
# - options...
|
118
|
+
# Return:
|
119
|
+
# Hash for validators(key is identification, value is validator)
|
120
|
+
def self.load_validators_from_csv_file(file_path)
|
121
|
+
first = true
|
122
|
+
header = nil
|
123
|
+
validators = { }
|
124
|
+
|
125
|
+
CSV.open(file_path, "r") do |row|
|
126
|
+
# skip header
|
127
|
+
if first
|
128
|
+
header = row
|
129
|
+
first = false
|
130
|
+
next
|
131
|
+
end
|
132
|
+
|
133
|
+
if validators.keys.include?(row[0])
|
134
|
+
raise ArgumentError.new("Duplicated validator number '#{row[0]}'!")
|
135
|
+
end
|
136
|
+
|
137
|
+
options = options_reader(row, { :description => row[1] })
|
138
|
+
|
139
|
+
validator = nil
|
140
|
+
|
141
|
+
case row[2]
|
142
|
+
when "presence"
|
143
|
+
validator = Validator::PresenceValidator
|
144
|
+
when "blank"
|
145
|
+
validator = Validator::BlankValidator
|
146
|
+
when "date"
|
147
|
+
validator = Validator::DateValidator
|
148
|
+
when "format"
|
149
|
+
validator = Validator::FormatValidator
|
150
|
+
when "inclusion"
|
151
|
+
validator = Validator::InclusionValidator
|
152
|
+
unless options[:in].nil?
|
153
|
+
options[:in] = options[:in].split(",")
|
154
|
+
end
|
155
|
+
when "length"
|
156
|
+
validator = Validator::LengthValidator
|
157
|
+
when "numeric"
|
158
|
+
validator = Validator::NumericValidator
|
159
|
+
when "complex"
|
160
|
+
options[:validators] = row[3].split(",").map do |validator_number|
|
161
|
+
validators[validator_number]
|
162
|
+
end
|
163
|
+
validators[row[0]] = Validator::ComplexValidator.new(options)
|
164
|
+
else
|
165
|
+
raise ArgumentError.new("Unknown validator type '#{row[2]}'!")
|
166
|
+
end
|
167
|
+
|
168
|
+
if validator
|
169
|
+
validators[row[0]] = validator.new(row[3], options)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
return validators
|
174
|
+
end
|
175
|
+
|
176
|
+
# load rule_set from csv file
|
177
|
+
#
|
178
|
+
# File encoding: UTF-8
|
179
|
+
# Columns:
|
180
|
+
# - rule identification(string)
|
181
|
+
# - rule description(string)
|
182
|
+
# - target expression(column identification or column name)
|
183
|
+
# - validator identification
|
184
|
+
# - prerequisite validator identification(allow blank)
|
185
|
+
# - error level(ERROR or WARNING)
|
186
|
+
# - error message holder(string)
|
187
|
+
# Return:
|
188
|
+
# RuleSet instance
|
189
|
+
def self.load_rule_from_csv_file(file_path, validators)
|
190
|
+
first = true
|
191
|
+
header = nil
|
192
|
+
rule_set = RuleSet.new
|
193
|
+
|
194
|
+
CSV.open(file_path, "r") do |row|
|
195
|
+
# skip header
|
196
|
+
if first
|
197
|
+
header = row
|
198
|
+
first = false
|
199
|
+
next
|
200
|
+
end
|
201
|
+
|
202
|
+
description = row[1]
|
203
|
+
target_expression = row[2].split(",")
|
204
|
+
validator = validators[row[3]]
|
205
|
+
prerequisite = validators[row[4]]
|
206
|
+
if validator.nil?
|
207
|
+
raise "Unknown validator identifier '#{row[3]}'"
|
208
|
+
end
|
209
|
+
if !row[4].nil? && prerequisite.nil?
|
210
|
+
raise "Unknown validator identifier '#{row[4]}'"
|
211
|
+
end
|
212
|
+
level = case row[5]
|
213
|
+
when "ERROR"
|
214
|
+
Rule::LEVEL_ERROR
|
215
|
+
when "WARNING"
|
216
|
+
Rule::LEVEL_WARNING
|
217
|
+
else
|
218
|
+
raise "Unknown error type '#{row[5]}'"
|
219
|
+
end
|
220
|
+
message = Message.new(row[6])
|
221
|
+
|
222
|
+
rule_set <<
|
223
|
+
Rule.new(target_expression,
|
224
|
+
message,
|
225
|
+
validator,
|
226
|
+
prerequisite,
|
227
|
+
level,
|
228
|
+
description)
|
229
|
+
end
|
230
|
+
|
231
|
+
return rule_set
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|