csvlint 1.0.0 → 1.1.0

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +4 -0
  3. data/.github/workflows/push.yml +14 -2
  4. data/.ruby-version +1 -1
  5. data/.standard_todo.yml +43 -0
  6. data/Dockerfile +16 -0
  7. data/Gemfile +2 -2
  8. data/README.md +9 -9
  9. data/Rakefile +7 -7
  10. data/csvlint.gemspec +14 -16
  11. data/docker_notes_for_windows.txt +20 -0
  12. data/features/step_definitions/cli_steps.rb +11 -11
  13. data/features/step_definitions/information_steps.rb +4 -4
  14. data/features/step_definitions/parse_csv_steps.rb +11 -11
  15. data/features/step_definitions/schema_validation_steps.rb +10 -10
  16. data/features/step_definitions/sources_steps.rb +1 -1
  17. data/features/step_definitions/validation_errors_steps.rb +19 -19
  18. data/features/step_definitions/validation_info_steps.rb +9 -9
  19. data/features/step_definitions/validation_warnings_steps.rb +11 -11
  20. data/features/support/aruba.rb +6 -6
  21. data/features/support/earl_formatter.rb +39 -39
  22. data/features/support/env.rb +10 -11
  23. data/features/support/load_tests.rb +107 -103
  24. data/features/support/webmock.rb +2 -2
  25. data/lib/csvlint/cli.rb +133 -130
  26. data/lib/csvlint/csvw/column.rb +279 -280
  27. data/lib/csvlint/csvw/date_format.rb +90 -92
  28. data/lib/csvlint/csvw/metadata_error.rb +1 -3
  29. data/lib/csvlint/csvw/number_format.rb +40 -32
  30. data/lib/csvlint/csvw/property_checker.rb +714 -717
  31. data/lib/csvlint/csvw/table.rb +49 -52
  32. data/lib/csvlint/csvw/table_group.rb +24 -23
  33. data/lib/csvlint/error_collector.rb +2 -0
  34. data/lib/csvlint/error_message.rb +0 -1
  35. data/lib/csvlint/field.rb +153 -141
  36. data/lib/csvlint/schema.rb +34 -42
  37. data/lib/csvlint/validate.rb +161 -143
  38. data/lib/csvlint/version.rb +1 -1
  39. data/lib/csvlint.rb +22 -23
  40. data/spec/csvw/column_spec.rb +15 -16
  41. data/spec/csvw/date_format_spec.rb +5 -7
  42. data/spec/csvw/number_format_spec.rb +2 -4
  43. data/spec/csvw/table_group_spec.rb +103 -105
  44. data/spec/csvw/table_spec.rb +71 -73
  45. data/spec/field_spec.rb +116 -121
  46. data/spec/schema_spec.rb +129 -139
  47. data/spec/spec_helper.rb +6 -6
  48. data/spec/validator_spec.rb +167 -190
  49. metadata +22 -55
@@ -1,813 +1,810 @@
1
1
  module Csvlint
2
2
  module Csvw
3
3
  class PropertyChecker
4
-
5
4
  class << self
6
-
7
5
  def check_property(property, value, base_url, lang)
8
6
  if PROPERTIES.include? property
9
- return PROPERTIES[property].call(value, base_url, lang)
7
+ PROPERTIES[property].call(value, base_url, lang)
10
8
  elsif property =~ /^([a-z]+):/ && NAMESPACES.include?(property.split(":")[0])
11
9
  value, warnings = check_common_property_value(value, base_url, lang)
12
- return value, warnings, :annotation
10
+ [value, warnings, :annotation]
13
11
  else
14
12
  # property name must be an absolute URI
15
13
  begin
16
14
  return value, :invalid_property, nil if URI(property).scheme.nil?
17
15
  value, warnings = check_common_property_value(value, base_url, lang)
18
- return value, warnings, :annotation
16
+ [value, warnings, :annotation]
19
17
  rescue
20
- return value, :invalid_property, nil
18
+ [value, :invalid_property, nil]
21
19
  end
22
20
  end
23
21
  end
24
22
 
25
23
  private
26
- def check_common_property_value(value, base_url, lang)
27
- case value
28
- when Hash
29
- value = value.clone
30
- warnings = []
31
- value.each do |p,v|
32
- case p
33
- when "@context"
34
- raise Csvlint::Csvw::MetadataError.new(p), "common property has @context property"
35
- when "@list"
36
- raise Csvlint::Csvw::MetadataError.new(p), "common property has @list property"
37
- when "@set"
38
- raise Csvlint::Csvw::MetadataError.new(p), "common property has @set property"
39
- when "@type"
40
- if value["@value"] && BUILT_IN_DATATYPES.include?(v)
41
- elsif !value["@value"] && BUILT_IN_TYPES.include?(v)
42
- elsif v =~ /^([a-z]+):/ && NAMESPACES.include?(v.split(":")[0])
43
- else
44
- # must be an absolute URI
45
- begin
46
- raise Csvlint::Csvw::MetadataError.new(), "common property has invalid @type (#{v})" if URI(v).scheme.nil?
47
- rescue
48
- raise Csvlint::Csvw::MetadataError.new(), "common property has invalid @type (#{v})"
49
- end
50
- end
51
- when "@id"
52
- unless base_url.nil?
53
- begin
54
- v = URI.join(base_url, v)
55
- rescue
56
- raise Csvlint::Csvw::MetadataError.new(), "common property has invalid @id (#{v})"
57
- end
58
- end
59
- when "@value"
60
- raise Csvlint::Csvw::MetadataError.new(), "common property with @value has both @language and @type" if value["@type"] && value["@language"]
61
- raise Csvlint::Csvw::MetadataError.new(), "common property with @value has properties other than @language or @type" unless value.except("@type").except("@language").except("@value").empty?
62
- when "@language"
63
- raise Csvlint::Csvw::MetadataError.new(), "common property with @language lacks a @value" unless value["@value"]
64
- raise Csvlint::Csvw::MetadataError.new(), "common property has invalid @language (#{v})" unless v =~ BCP47_LANGUAGE_REGEXP || v.nil?
24
+
25
+ def check_common_property_value(value, base_url, lang)
26
+ case value
27
+ when Hash
28
+ value = value.clone
29
+ warnings = []
30
+ value.each do |p, v|
31
+ case p
32
+ when "@context"
33
+ raise Csvlint::Csvw::MetadataError.new(p), "common property has @context property"
34
+ when "@list"
35
+ raise Csvlint::Csvw::MetadataError.new(p), "common property has @list property"
36
+ when "@set"
37
+ raise Csvlint::Csvw::MetadataError.new(p), "common property has @set property"
38
+ when "@type"
39
+ if value["@value"] && BUILT_IN_DATATYPES.include?(v)
40
+ elsif !value["@value"] && BUILT_IN_TYPES.include?(v)
41
+ elsif ((v.is_a? String) && (v =~ /^([a-z]+):/)) && NAMESPACES.include?(v.split(":")[0])
65
42
  else
66
- if p[0] == "@"
67
- raise Csvlint::Csvw::MetadataError.new(), "common property has property other than @id, @type, @value or @language beginning with @ (#{p})"
68
- else
69
- v, w = check_common_property_value(v, base_url, lang)
70
- warnings += Array(w)
43
+ # must be an absolute URI
44
+ begin
45
+ raise Csvlint::Csvw::MetadataError.new, "common property has invalid @type (#{v})" if URI(v).scheme.nil?
46
+ rescue
47
+ raise Csvlint::Csvw::MetadataError.new, "common property has invalid @type (#{v})"
71
48
  end
72
49
  end
73
- value[p] = v
74
- end
75
- return value, warnings
76
- when String
77
- if lang == "und"
78
- return value, nil
50
+ when "@id"
51
+ unless base_url.nil?
52
+ begin
53
+ v = URI.join(base_url, v)
54
+ rescue
55
+ raise Csvlint::Csvw::MetadataError.new, "common property has invalid @id (#{v})"
56
+ end
57
+ end
58
+ when "@value"
59
+ raise Csvlint::Csvw::MetadataError.new, "common property with @value has both @language and @type" if value["@type"] && value["@language"]
60
+ raise Csvlint::Csvw::MetadataError.new, "common property with @value has properties other than @language or @type" unless value.except("@type").except("@language").except("@value").empty?
61
+ when "@language"
62
+ raise Csvlint::Csvw::MetadataError.new, "common property with @language lacks a @value" unless value["@value"]
63
+ raise Csvlint::Csvw::MetadataError.new, "common property has invalid @language (#{v})" unless ((v.is_a? String) && (v =~ BCP47_LANGUAGE_REGEXP)) || v.nil?
79
64
  else
80
- return { "@value" => value, "@language" => lang }, nil
81
- end
82
- when Array
83
- values = []
84
- warnings = []
85
- value.each do |v|
86
- v, w = check_common_property_value(v, base_url, lang)
87
- warnings += Array(w)
88
- values << v
65
+ if p[0] == "@"
66
+ raise Csvlint::Csvw::MetadataError.new, "common property has property other than @id, @type, @value or @language beginning with @ (#{p})"
67
+ else
68
+ v, w = check_common_property_value(v, base_url, lang)
69
+ warnings += Array(w)
70
+ end
89
71
  end
90
- return values, warnings
72
+ value[p] = v
73
+ end
74
+ [value, warnings]
75
+ when String
76
+ if lang == "und"
77
+ [value, nil]
91
78
  else
92
- return value, nil
79
+ [{"@value" => value, "@language" => lang}, nil]
80
+ end
81
+ when Array
82
+ values = []
83
+ warnings = []
84
+ value.each do |v|
85
+ v, w = check_common_property_value(v, base_url, lang)
86
+ warnings += Array(w)
87
+ values << v
93
88
  end
89
+ [values, warnings]
90
+ else
91
+ [value, nil]
94
92
  end
93
+ end
95
94
 
96
- def convert_value_facet(value, property, datatype)
97
- if value[property]
98
- if DATE_FORMAT_DATATYPES.include?(datatype)
99
- format = Csvlint::Csvw::DateFormat.new(nil, datatype)
100
- v = format.parse(value[property])
101
- if v.nil?
102
- value.delete(property)
103
- return [":invalid_#{property}".to_sym]
104
- else
105
- value[property] = v
106
- return []
107
- end
108
- elsif NUMERIC_FORMAT_DATATYPES.include?(datatype)
109
- return []
95
+ def convert_value_facet(value, property, datatype)
96
+ if value[property]
97
+ if DATE_FORMAT_DATATYPES.include?(datatype)
98
+ format = Csvlint::Csvw::DateFormat.new(nil, datatype)
99
+ v = format.parse(value[property])
100
+ if v.nil?
101
+ value.delete(property)
102
+ return [":invalid_#{property}".to_sym]
110
103
  else
111
- raise Csvlint::Csvw::MetadataError.new("datatype.#{property}"), "#{property} is only allowed for numeric, date/time and duration types"
104
+ value[property] = v
105
+ return []
112
106
  end
107
+ elsif NUMERIC_FORMAT_DATATYPES.include?(datatype)
108
+ return []
109
+ else
110
+ raise Csvlint::Csvw::MetadataError.new("datatype.#{property}"), "#{property} is only allowed for numeric, date/time and duration types"
113
111
  end
114
- return []
115
112
  end
113
+ []
114
+ end
116
115
 
117
- def array_property(type)
118
- return lambda { |value, base_url, lang|
119
- return value, nil, type if value.instance_of? Array
120
- return false, :invalid_value, type
121
- }
122
- end
116
+ def array_property(type)
117
+ lambda { |value, base_url, lang|
118
+ return value, nil, type if value.instance_of? Array
119
+ return false, :invalid_value, type
120
+ }
121
+ end
123
122
 
124
- def boolean_property(type)
125
- return lambda { |value, base_url, lang|
126
- return value, nil, type if value == true || value == false
127
- return false, :invalid_value, type
128
- }
129
- end
123
+ def boolean_property(type)
124
+ lambda { |value, base_url, lang|
125
+ return value, nil, type if value == true || value == false
126
+ return false, :invalid_value, type
127
+ }
128
+ end
130
129
 
131
- def string_property(type)
132
- return lambda { |value, base_url, lang|
133
- return value, nil, type if value.instance_of? String
134
- return "", :invalid_value, type
135
- }
136
- end
130
+ def string_property(type)
131
+ lambda { |value, base_url, lang|
132
+ return value, nil, type if value.instance_of? String
133
+ return "", :invalid_value, type
134
+ }
135
+ end
137
136
 
138
- def uri_template_property(type)
139
- return lambda { |value, base_url, lang|
140
- return URITemplate.new(value), nil, type if value.instance_of? String
141
- return URITemplate.new(""), :invalid_value, type
142
- }
143
- end
137
+ def uri_template_property(type)
138
+ lambda { |value, base_url, lang|
139
+ return URITemplate.new(value), nil, type if value.instance_of? String
140
+ return URITemplate.new(""), :invalid_value, type
141
+ }
142
+ end
144
143
 
145
- def numeric_property(type)
146
- return lambda { |value, base_url, lang|
147
- return value, nil, type if value.kind_of?(Integer) && value >= 0
148
- return nil, :invalid_value, type
149
- }
150
- end
144
+ def numeric_property(type)
145
+ lambda { |value, base_url, lang|
146
+ return value, nil, type if value.is_a?(Integer) && value >= 0
147
+ return nil, :invalid_value, type
148
+ }
149
+ end
151
150
 
152
- def link_property(type)
153
- return lambda { |value, base_url, lang|
154
- raise Csvlint::Csvw::MetadataError.new(), "URL #{value} starts with _:" if value.to_s =~ /^_:/
155
- return (base_url.nil? ? URI(value) : URI.join(base_url, value)), nil, type if value.instance_of? String
156
- return base_url, :invalid_value, type
157
- }
158
- end
151
+ def link_property(type)
152
+ lambda { |value, base_url, lang|
153
+ raise Csvlint::Csvw::MetadataError.new, "URL #{value} starts with _:" if /^_:/.match?(value.to_s)
154
+ return (base_url.nil? ? URI(value) : URI.join(base_url, value)), nil, type if value.instance_of? String
155
+ return base_url, :invalid_value, type
156
+ }
157
+ end
159
158
 
160
- def language_property(type)
161
- return lambda { |value, base_url, lang|
162
- return value, nil, type if value =~ BCP47_REGEXP
163
- return nil, :invalid_value, type
164
- }
165
- end
159
+ def language_property(type)
160
+ lambda { |value, base_url, lang|
161
+ return value, nil, type if BCP47_REGEXP.match?(value)
162
+ return nil, :invalid_value, type
163
+ }
164
+ end
166
165
 
167
- def natural_language_property(type)
168
- return lambda { |value, base_url, lang|
169
- warnings = []
170
- if value.instance_of? String
171
- return { lang => [ value ] }, nil, type
172
- elsif value.instance_of? Array
173
- valid_titles = []
174
- value.each do |title|
175
- if title.instance_of? String
176
- valid_titles << title
177
- else
178
- warnings << :invalid_value
179
- end
166
+ def natural_language_property(type)
167
+ lambda { |value, base_url, lang|
168
+ warnings = []
169
+ if value.instance_of? String
170
+ return {lang => [value]}, nil, type
171
+ elsif value.instance_of? Array
172
+ valid_titles = []
173
+ value.each do |title|
174
+ if title.instance_of? String
175
+ valid_titles << title
176
+ else
177
+ warnings << :invalid_value
180
178
  end
181
- return { lang => valid_titles }, warnings, type
182
- elsif value.instance_of? Hash
183
- value = value.clone
184
- value.each do |l,v|
185
- if l =~ BCP47_REGEXP
186
- valid_titles = []
187
- Array(v).each do |title|
188
- if title.instance_of? String
189
- valid_titles << title
190
- else
191
- warnings << :invalid_value
192
- end
179
+ end
180
+ return {lang => valid_titles}, warnings, type
181
+ elsif value.instance_of? Hash
182
+ value = value.clone
183
+ value.each do |l, v|
184
+ if BCP47_REGEXP.match?(l)
185
+ valid_titles = []
186
+ Array(v).each do |title|
187
+ if title.instance_of? String
188
+ valid_titles << title
189
+ else
190
+ warnings << :invalid_value
193
191
  end
194
- value[l] = valid_titles
195
- else
196
- value.delete(l)
197
- warnings << :invalid_language
198
192
  end
193
+ value[l] = valid_titles
194
+ else
195
+ value.delete(l)
196
+ warnings << :invalid_language
199
197
  end
200
- warnings << :invalid_value if value.empty?
201
- return value, warnings, type
202
- else
203
- return {}, :invalid_value, type
204
198
  end
205
- }
206
- end
207
-
208
- def column_reference_property(type)
209
- return lambda { |value, base_url, lang|
210
- return Array(value), nil, type
211
- }
212
- end
213
-
199
+ warnings << :invalid_value if value.empty?
200
+ return value, warnings, type
201
+ else
202
+ return {}, :invalid_value, type
203
+ end
204
+ }
205
+ end
214
206
 
207
+ def column_reference_property(type)
208
+ lambda { |value, base_url, lang|
209
+ return Array(value), nil, type
210
+ }
211
+ end
215
212
  end
216
213
 
217
- PROPERTIES = {
218
- # context properties
219
- "@language" => language_property(:context),
220
- "@base" => link_property(:context),
221
- # common properties
222
- "@id" => link_property(:common),
223
- "notes" => lambda { |value, base_url, lang|
224
- return false, :invalid_value, :common unless value.instance_of? Array
225
- values = []
214
+ PROPERTIES = {
215
+ # context properties
216
+ "@language" => language_property(:context),
217
+ "@base" => link_property(:context),
218
+ # common properties
219
+ "@id" => link_property(:common),
220
+ "notes" => lambda { |value, base_url, lang|
221
+ return false, :invalid_value, :common unless value.instance_of? Array
222
+ values = []
223
+ warnings = []
224
+ value.each do |v|
225
+ v, w = check_common_property_value(v, base_url, lang)
226
+ values << v
227
+ warnings += w
228
+ end
229
+ return values, warnings, :common
230
+ },
231
+ "suppressOutput" => boolean_property(:common),
232
+ "dialect" => lambda { |value, base_url, lang|
233
+ if value.instance_of? Hash
234
+ value = value.clone
226
235
  warnings = []
227
- value.each do |v|
228
- v, w = check_common_property_value(v, base_url, lang)
229
- values << v
230
- warnings += w
231
- end
232
- return values, warnings, :common
233
- },
234
- "suppressOutput" => boolean_property(:common),
235
- "dialect" => lambda { |value, base_url, lang|
236
- if value.instance_of? Hash
237
- value = value.clone
238
- warnings = []
239
- value.each do |p,v|
240
- if p == "@id"
241
- raise Csvlint::Csvw::MetadataError.new("dialect.@id"), "@id starts with _:" if v =~ /^_:/
242
- elsif p == "@type"
243
- raise Csvlint::Csvw::MetadataError.new("dialect.@type"), "@type of dialect is not 'Dialect'" if v != 'Dialect'
236
+ value.each do |p, v|
237
+ if p == "@id"
238
+ raise Csvlint::Csvw::MetadataError.new("dialect.@id"), "@id starts with _:" if /^_:/.match?(v)
239
+ elsif p == "@type"
240
+ raise Csvlint::Csvw::MetadataError.new("dialect.@type"), "@type of dialect is not 'Dialect'" if v != "Dialect"
241
+ else
242
+ v, warning, type = check_property(p, v, base_url, lang)
243
+ if type == :dialect && (warning.nil? || warning.empty?)
244
+ value[p] = v
244
245
  else
245
- v, warning, type = check_property(p, v, base_url, lang)
246
- if type == :dialect && (warning.nil? || warning.empty?)
247
- value[p] = v
248
- else
249
- value.delete(p)
250
- warnings << :invalid_property unless type == :dialect
251
- warnings += Array(warning)
252
- end
246
+ value.delete(p)
247
+ warnings << :invalid_property unless type == :dialect
248
+ warnings += Array(warning)
253
249
  end
254
250
  end
255
- return value, warnings, :common
256
- else
257
- return {}, :invalid_value, :common
258
251
  end
259
- },
260
- # inherited properties
261
- "null" => lambda { |value, base_url, lang|
262
- case value
263
- when String
264
- return [value], nil, :inherited
265
- when Array
266
- values = []
267
- warnings = []
268
- value.each do |v|
269
- if v.instance_of? String
270
- values << v
271
- else
272
- warnings << :invalid_value
273
- end
252
+ return value, warnings, :common
253
+ else
254
+ return {}, :invalid_value, :common
255
+ end
256
+ },
257
+ # inherited properties
258
+ "null" => lambda { |value, base_url, lang|
259
+ case value
260
+ when String
261
+ return [value], nil, :inherited
262
+ when Array
263
+ values = []
264
+ warnings = []
265
+ value.each do |v|
266
+ if v.instance_of? String
267
+ values << v
268
+ else
269
+ warnings << :invalid_value
274
270
  end
275
- return values, warnings, :inherited
276
- else
277
- return [""], :invalid_value, :inherited
278
271
  end
279
- },
280
- "default" => string_property(:inherited),
281
- "separator" => lambda { |value, base_url, lang|
282
- return value, nil, :inherited if value.instance_of?(String) || value.nil?
283
- return nil, :invalid_value, :inherited
284
- },
285
- "lang" => language_property(:inherited),
286
- "datatype" => lambda { |value, base_url, lang|
287
- value = value.clone
288
- warnings = []
289
- if value.instance_of? Hash
290
- if value["@id"]
291
- raise Csvlint::Csvw::MetadataError.new("datatype.@id"), "datatype @id must not be the id of a built-in datatype (#{value["@id"]})" if BUILT_IN_DATATYPES.values.include?(value["@id"])
292
- v,w,t = PROPERTIES["@id"].call(value["@id"], base_url, lang)
293
- unless w.nil?
294
- warnings << w
295
- value.delete("@id")
296
- end
272
+ return values, warnings, :inherited
273
+ else
274
+ return [""], :invalid_value, :inherited
275
+ end
276
+ },
277
+ "default" => string_property(:inherited),
278
+ "separator" => lambda { |value, base_url, lang|
279
+ return value, nil, :inherited if value.instance_of?(String) || value.nil?
280
+ return nil, :invalid_value, :inherited
281
+ },
282
+ "lang" => language_property(:inherited),
283
+ "datatype" => lambda { |value, base_url, lang|
284
+ value = value.clone
285
+ warnings = []
286
+ if value.instance_of? Hash
287
+ if value["@id"]
288
+ raise Csvlint::Csvw::MetadataError.new("datatype.@id"), "datatype @id must not be the id of a built-in datatype (#{value["@id"]})" if BUILT_IN_DATATYPES.values.include?(value["@id"])
289
+ v, w, t = PROPERTIES["@id"].call(value["@id"], base_url, lang)
290
+ unless w.nil?
291
+ warnings << w
292
+ value.delete("@id")
297
293
  end
294
+ end
298
295
 
299
- if value["base"]
300
- if BUILT_IN_DATATYPES.include? value["base"]
301
- value["base"] = BUILT_IN_DATATYPES[value["base"]]
302
- else
303
- value["base"] = BUILT_IN_DATATYPES["string"]
304
- warnings << :invalid_datatype_base
305
- end
296
+ if value["base"]
297
+ if BUILT_IN_DATATYPES.include? value["base"]
298
+ value["base"] = BUILT_IN_DATATYPES[value["base"]]
306
299
  else
307
300
  value["base"] = BUILT_IN_DATATYPES["string"]
301
+ warnings << :invalid_datatype_base
308
302
  end
309
- elsif BUILT_IN_DATATYPES.include? value
310
- value = { "@id" => BUILT_IN_DATATYPES[value] }
311
303
  else
312
- value = { "@id" => BUILT_IN_DATATYPES["string"] }
313
- warnings << :invalid_value
304
+ value["base"] = BUILT_IN_DATATYPES["string"]
314
305
  end
306
+ elsif BUILT_IN_DATATYPES.include? value
307
+ value = {"@id" => BUILT_IN_DATATYPES[value]}
308
+ else
309
+ value = {"@id" => BUILT_IN_DATATYPES["string"]}
310
+ warnings << :invalid_value
311
+ end
315
312
 
316
- unless STRING_DATATYPES.include?(value["base"]) || BINARY_DATATYPES.include?(value["base"])
317
- raise Csvlint::Csvw::MetadataError.new("datatype.length"), "datatypes based on #{value["base"]} cannot have a length facet" if value["length"]
318
- raise Csvlint::Csvw::MetadataError.new("datatype.minLength"), "datatypes based on #{value["base"]} cannot have a minLength facet" if value["minLength"]
319
- raise Csvlint::Csvw::MetadataError.new("datatype.maxLength"), "datatypes based on #{value["base"]} cannot have a maxLength facet" if value["maxLength"]
320
- end
313
+ unless STRING_DATATYPES.include?(value["base"]) || BINARY_DATATYPES.include?(value["base"])
314
+ raise Csvlint::Csvw::MetadataError.new("datatype.length"), "datatypes based on #{value["base"]} cannot have a length facet" if value["length"]
315
+ raise Csvlint::Csvw::MetadataError.new("datatype.minLength"), "datatypes based on #{value["base"]} cannot have a minLength facet" if value["minLength"]
316
+ raise Csvlint::Csvw::MetadataError.new("datatype.maxLength"), "datatypes based on #{value["base"]} cannot have a maxLength facet" if value["maxLength"]
317
+ end
321
318
 
322
- if value["minimum"]
323
- value["minInclusive"] = value["minimum"]
324
- value.delete("minimum")
325
- end
326
- if value["maximum"]
327
- value["maxInclusive"] = value["maximum"]
328
- value.delete("maximum")
329
- end
319
+ if value["minimum"]
320
+ value["minInclusive"] = value["minimum"]
321
+ value.delete("minimum")
322
+ end
323
+ if value["maximum"]
324
+ value["maxInclusive"] = value["maximum"]
325
+ value.delete("maximum")
326
+ end
330
327
 
331
- warnings += convert_value_facet(value, "minInclusive", value["base"])
332
- warnings += convert_value_facet(value, "minExclusive", value["base"])
333
- warnings += convert_value_facet(value, "maxInclusive", value["base"])
334
- warnings += convert_value_facet(value, "maxExclusive", value["base"])
335
-
336
- minInclusive = value["minInclusive"].is_a?(Hash) ? value["minInclusive"][:dateTime] : value["minInclusive"]
337
- maxInclusive = value["maxInclusive"].is_a?(Hash) ? value["maxInclusive"][:dateTime] : value["maxInclusive"]
338
- minExclusive = value["minExclusive"].is_a?(Hash) ? value["minExclusive"][:dateTime] : value["minExclusive"]
339
- maxExclusive = value["maxExclusive"].is_a?(Hash) ? value["maxExclusive"][:dateTime] : value["maxExclusive"]
340
-
341
- raise Csvlint::Csvw::MetadataError.new(""), "datatype cannot specify both minimum/minInclusive (#{minInclusive}) and minExclusive (#{minExclusive}" if minInclusive && minExclusive
342
- raise Csvlint::Csvw::MetadataError.new(""), "datatype cannot specify both maximum/maxInclusive (#{maxInclusive}) and maxExclusive (#{maxExclusive}" if maxInclusive && maxExclusive
343
- raise Csvlint::Csvw::MetadataError.new(""), "datatype minInclusive (#{minInclusive}) cannot be more than maxInclusive (#{maxInclusive}" if minInclusive && maxInclusive && minInclusive > maxInclusive
344
- raise Csvlint::Csvw::MetadataError.new(""), "datatype minInclusive (#{minInclusive}) cannot be more than or equal to maxExclusive (#{maxExclusive}" if minInclusive && maxExclusive && minInclusive >= maxExclusive
345
- raise Csvlint::Csvw::MetadataError.new(""), "datatype minExclusive (#{minExclusive}) cannot be more than or equal to maxExclusive (#{maxExclusive}" if minExclusive && maxExclusive && minExclusive > maxExclusive
346
- raise Csvlint::Csvw::MetadataError.new(""), "datatype minExclusive (#{minExclusive}) cannot be more than maxInclusive (#{maxInclusive}" if minExclusive && maxInclusive && minExclusive >= maxInclusive
347
-
348
- raise Csvlint::Csvw::MetadataError.new(""), "datatype length (#{value["length"]}) cannot be less than minLength (#{value["minLength"]}" if value["length"] && value["minLength"] && value["length"] < value["minLength"]
349
- raise Csvlint::Csvw::MetadataError.new(""), "datatype length (#{value["length"]}) cannot be more than maxLength (#{value["maxLength"]}" if value["length"] && value["maxLength"] && value["length"] > value["maxLength"]
350
- raise Csvlint::Csvw::MetadataError.new(""), "datatype minLength (#{value["minLength"]}) cannot be more than maxLength (#{value["maxLength"]}" if value["minLength"] && value["maxLength"] && value["minLength"] > value["maxLength"]
351
-
352
- if value["format"]
353
- if REGEXP_FORMAT_DATATYPES.include?(value["base"])
354
- begin
355
- value["format"] = Regexp.new(value["format"])
356
- rescue RegexpError
357
- value.delete("format")
358
- warnings << :invalid_regex
359
- end
360
- elsif NUMERIC_FORMAT_DATATYPES.include?(value["base"])
361
- value["format"] = { "pattern" => value["format"] } if value["format"].instance_of? String
362
- begin
363
- value["format"] = Csvlint::Csvw::NumberFormat.new(value["format"]["pattern"], value["format"]["groupChar"], value["format"]["decimalChar"] || ".", INTEGER_FORMAT_DATATYPES.include?(value["base"]))
364
- rescue Csvlint::Csvw::NumberFormatError
365
- value["format"] = Csvlint::Csvw::NumberFormat.new(nil, value["format"]["groupChar"], value["format"]["decimalChar"] || ".", INTEGER_FORMAT_DATATYPES.include?(value["base"]))
366
- warnings << :invalid_number_format
367
- end
368
- elsif value["base"] == "http://www.w3.org/2001/XMLSchema#boolean"
369
- if value["format"].instance_of? String
370
- value["format"] = value["format"].split("|")
371
- unless value["format"].length == 2
372
- value.delete("format")
373
- warnings << :invalid_boolean_format
374
- end
375
- else
328
+ warnings += convert_value_facet(value, "minInclusive", value["base"])
329
+ warnings += convert_value_facet(value, "minExclusive", value["base"])
330
+ warnings += convert_value_facet(value, "maxInclusive", value["base"])
331
+ warnings += convert_value_facet(value, "maxExclusive", value["base"])
332
+
333
+ minInclusive = value["minInclusive"].is_a?(Hash) ? value["minInclusive"][:dateTime] : value["minInclusive"]
334
+ maxInclusive = value["maxInclusive"].is_a?(Hash) ? value["maxInclusive"][:dateTime] : value["maxInclusive"]
335
+ minExclusive = value["minExclusive"].is_a?(Hash) ? value["minExclusive"][:dateTime] : value["minExclusive"]
336
+ maxExclusive = value["maxExclusive"].is_a?(Hash) ? value["maxExclusive"][:dateTime] : value["maxExclusive"]
337
+
338
+ raise Csvlint::Csvw::MetadataError.new(""), "datatype cannot specify both minimum/minInclusive (#{minInclusive}) and minExclusive (#{minExclusive}" if minInclusive && minExclusive
339
+ raise Csvlint::Csvw::MetadataError.new(""), "datatype cannot specify both maximum/maxInclusive (#{maxInclusive}) and maxExclusive (#{maxExclusive}" if maxInclusive && maxExclusive
340
+ raise Csvlint::Csvw::MetadataError.new(""), "datatype minInclusive (#{minInclusive}) cannot be more than maxInclusive (#{maxInclusive}" if minInclusive && maxInclusive && minInclusive > maxInclusive
341
+ raise Csvlint::Csvw::MetadataError.new(""), "datatype minInclusive (#{minInclusive}) cannot be more than or equal to maxExclusive (#{maxExclusive}" if minInclusive && maxExclusive && minInclusive >= maxExclusive
342
+ raise Csvlint::Csvw::MetadataError.new(""), "datatype minExclusive (#{minExclusive}) cannot be more than or equal to maxExclusive (#{maxExclusive}" if minExclusive && maxExclusive && minExclusive > maxExclusive
343
+ raise Csvlint::Csvw::MetadataError.new(""), "datatype minExclusive (#{minExclusive}) cannot be more than maxInclusive (#{maxInclusive}" if minExclusive && maxInclusive && minExclusive >= maxInclusive
344
+
345
+ raise Csvlint::Csvw::MetadataError.new(""), "datatype length (#{value["length"]}) cannot be less than minLength (#{value["minLength"]}" if value["length"] && value["minLength"] && value["length"] < value["minLength"]
346
+ raise Csvlint::Csvw::MetadataError.new(""), "datatype length (#{value["length"]}) cannot be more than maxLength (#{value["maxLength"]}" if value["length"] && value["maxLength"] && value["length"] > value["maxLength"]
347
+ raise Csvlint::Csvw::MetadataError.new(""), "datatype minLength (#{value["minLength"]}) cannot be more than maxLength (#{value["maxLength"]}" if value["minLength"] && value["maxLength"] && value["minLength"] > value["maxLength"]
348
+
349
+ if value["format"]
350
+ if REGEXP_FORMAT_DATATYPES.include?(value["base"])
351
+ begin
352
+ value["format"] = Regexp.new(value["format"])
353
+ rescue RegexpError
354
+ value.delete("format")
355
+ warnings << :invalid_regex
356
+ end
357
+ elsif NUMERIC_FORMAT_DATATYPES.include?(value["base"])
358
+ value["format"] = {"pattern" => value["format"]} if value["format"].instance_of? String
359
+ begin
360
+ value["format"] = Csvlint::Csvw::NumberFormat.new(value["format"]["pattern"], value["format"]["groupChar"], value["format"]["decimalChar"] || ".", INTEGER_FORMAT_DATATYPES.include?(value["base"]))
361
+ rescue Csvlint::Csvw::NumberFormatError
362
+ value["format"] = Csvlint::Csvw::NumberFormat.new(nil, value["format"]["groupChar"], value["format"]["decimalChar"] || ".", INTEGER_FORMAT_DATATYPES.include?(value["base"]))
363
+ warnings << :invalid_number_format
364
+ end
365
+ elsif value["base"] == "http://www.w3.org/2001/XMLSchema#boolean"
366
+ if value["format"].instance_of? String
367
+ value["format"] = value["format"].split("|")
368
+ unless value["format"].length == 2
376
369
  value.delete("format")
377
370
  warnings << :invalid_boolean_format
378
371
  end
379
- elsif DATE_FORMAT_DATATYPES.include?(value["base"])
380
- if value["format"].instance_of? String
381
- begin
382
- value["format"] = Csvlint::Csvw::DateFormat.new(value["format"])
383
- rescue Csvlint::CsvDateFormatError
384
- value.delete("format")
385
- warnings << :invalid_date_format
386
- end
387
- else
372
+ else
373
+ value.delete("format")
374
+ warnings << :invalid_boolean_format
375
+ end
376
+ elsif DATE_FORMAT_DATATYPES.include?(value["base"])
377
+ if value["format"].instance_of? String
378
+ begin
379
+ value["format"] = Csvlint::Csvw::DateFormat.new(value["format"])
380
+ rescue Csvlint::CsvDateFormatError
388
381
  value.delete("format")
389
382
  warnings << :invalid_date_format
390
383
  end
384
+ else
385
+ value.delete("format")
386
+ warnings << :invalid_date_format
391
387
  end
392
388
  end
393
- return value, warnings, :inherited
394
- },
395
- "required" => boolean_property(:inherited),
396
- "ordered" => boolean_property(:inherited),
397
- "aboutUrl" => uri_template_property(:inherited),
398
- "propertyUrl" => uri_template_property(:inherited),
399
- "valueUrl" => uri_template_property(:inherited),
400
- "textDirection" => lambda { |value, base_url, lang|
401
- value = value.to_sym
402
- return value, nil, :inherited if [:ltr, :rtl, :auto, :inherit].include? value
403
- return :inherit, :invalid_value, :inherited
404
- },
405
- # column level properties
406
- "virtual" => boolean_property(:column),
407
- "titles" => natural_language_property(:column),
408
- "name" => lambda { |value, base_url, lang|
409
- return value, nil, :column if value.instance_of?(String) && value =~ NAME_REGEXP
410
- return nil, :invalid_value, :column
411
- },
412
- # table level properties
413
- "transformations" => lambda { |value, base_url, lang|
414
- transformations = []
415
- warnings = []
416
- if value.instance_of? Array
417
- value.each_with_index do |transformation,i|
418
- if transformation.instance_of? Hash
419
- transformation = transformation.clone
420
- transformation.each do |p,v|
421
- if p == "@id"
422
- raise Csvlint::Csvw::MetadataError.new("transformations[#{i}].@id"), "@id starts with _:" if v =~ /^_:/
423
- elsif p == "@type"
424
- raise Csvlint::Csvw::MetadataError.new("transformations[#{i}].@type"), "@type of transformation is not 'Template'" if v != 'Template'
425
- elsif p == "url"
426
- elsif p == "titles"
427
- else
428
- v, warning, type = check_property(p, v, base_url, lang)
429
- unless type == :transformation && (warning.nil? || warning.empty?)
430
- value.delete(p)
431
- warnings << :invalid_property unless type == :transformation
432
- warnings += Array(warning)
433
- end
389
+ end
390
+ return value, warnings, :inherited
391
+ },
392
+ "required" => boolean_property(:inherited),
393
+ "ordered" => boolean_property(:inherited),
394
+ "aboutUrl" => uri_template_property(:inherited),
395
+ "propertyUrl" => uri_template_property(:inherited),
396
+ "valueUrl" => uri_template_property(:inherited),
397
+ "textDirection" => lambda { |value, base_url, lang|
398
+ value = value.to_sym
399
+ return value, nil, :inherited if [:ltr, :rtl, :auto, :inherit].include? value
400
+ return :inherit, :invalid_value, :inherited
401
+ },
402
+ # column level properties
403
+ "virtual" => boolean_property(:column),
404
+ "titles" => natural_language_property(:column),
405
+ "name" => lambda { |value, base_url, lang|
406
+ return value, nil, :column if value.instance_of?(String) && value =~ NAME_REGEXP
407
+ return nil, :invalid_value, :column
408
+ },
409
+ # table level properties
410
+ "transformations" => lambda { |value, base_url, lang|
411
+ transformations = []
412
+ warnings = []
413
+ if value.instance_of? Array
414
+ value.each_with_index do |transformation, i|
415
+ if transformation.instance_of? Hash
416
+ transformation = transformation.clone
417
+ transformation.each do |p, v|
418
+ if p == "@id"
419
+ raise Csvlint::Csvw::MetadataError.new("transformations[#{i}].@id"), "@id starts with _:" if /^_:/.match?(v)
420
+ elsif p == "@type"
421
+ raise Csvlint::Csvw::MetadataError.new("transformations[#{i}].@type"), "@type of transformation is not 'Template'" if v != "Template"
422
+ elsif p == "url"
423
+ elsif p == "titles"
424
+ else
425
+ v, warning, type = check_property(p, v, base_url, lang)
426
+ unless type == :transformation && (warning.nil? || warning.empty?)
427
+ value.delete(p)
428
+ warnings << :invalid_property unless type == :transformation
429
+ warnings += Array(warning)
434
430
  end
435
431
  end
436
- transformations << transformation
437
- else
438
- warnings << :invalid_transformation
439
432
  end
433
+ transformations << transformation
434
+ else
435
+ warnings << :invalid_transformation
440
436
  end
441
- else
442
- warnings << :invalid_value
443
437
  end
444
- return transformations, warnings, :table
445
- },
446
- "tableDirection" => lambda { |value, base_url, lang|
447
- value = value.to_sym
448
- return value, nil, :table if [:ltr, :rtl, :auto].include? value
449
- return :auto, :invalid_value, :table
450
- },
451
- "tableSchema" => lambda { |value, base_url, lang|
452
- schema_base_url = base_url
453
- schema_lang = lang
454
- if value.instance_of? String
455
- schema_url = URI.join(base_url, value).to_s
456
- schema_base_url = schema_url
457
- schema_ref = schema_url.start_with?("file:") ? File.new(schema_url[5..-1]) : schema_url
458
- schema = JSON.parse( URI.open(schema_ref).read )
459
- schema["@id"] = schema["@id"] ? URI.join(schema_url, schema["@id"]).to_s : schema_url
460
- if schema["@context"]
461
- if schema["@context"].instance_of?(Array) && schema["@context"].length > 1
462
- schema_base_url = schema["@context"][1]["@base"] ? URI.join(schema_base_url, schema["@context"][1]["@base"]).to_s : schema_base_url
463
- schema_lang = schema["@context"][1]["@language"] || schema_lang
464
- end
465
- schema.delete("@context")
438
+ else
439
+ warnings << :invalid_value
440
+ end
441
+ return transformations, warnings, :table
442
+ },
443
+ "tableDirection" => lambda { |value, base_url, lang|
444
+ value = value.to_sym
445
+ return value, nil, :table if [:ltr, :rtl, :auto].include? value
446
+ return :auto, :invalid_value, :table
447
+ },
448
+ "tableSchema" => lambda { |value, base_url, lang|
449
+ schema_base_url = base_url
450
+ schema_lang = lang
451
+ if value.instance_of? String
452
+ schema_url = URI.join(base_url, value).to_s
453
+ schema_base_url = schema_url
454
+ schema_ref = schema_url.start_with?("file:") ? File.new(schema_url[5..-1]) : schema_url
455
+ schema = JSON.parse(URI.open(schema_ref).read)
456
+ schema["@id"] = schema["@id"] ? URI.join(schema_url, schema["@id"]).to_s : schema_url
457
+ if schema["@context"]
458
+ if schema["@context"].instance_of?(Array) && schema["@context"].length > 1
459
+ schema_base_url = schema["@context"][1]["@base"] ? URI.join(schema_base_url, schema["@context"][1]["@base"]).to_s : schema_base_url
460
+ schema_lang = schema["@context"][1]["@language"] || schema_lang
466
461
  end
467
- elsif value.instance_of? Hash
468
- schema = value.clone
469
- else
470
- return {}, :invalid_value, :table
462
+ schema.delete("@context")
471
463
  end
472
- warnings = []
473
- schema.each do |p,v|
474
- if p == "@id"
475
- raise Csvlint::Csvw::MetadataError.new("tableSchema.@id"), "@id starts with _:" if v =~ /^_:/
476
- elsif p == "@type"
477
- raise Csvlint::Csvw::MetadataError.new("tableSchema.@type"), "@type of schema is not 'Schema'" if v != 'Schema'
464
+ elsif value.instance_of? Hash
465
+ schema = value.clone
466
+ else
467
+ return {}, :invalid_value, :table
468
+ end
469
+ warnings = []
470
+ schema.each do |p, v|
471
+ if p == "@id"
472
+ raise Csvlint::Csvw::MetadataError.new("tableSchema.@id"), "@id starts with _:" if /^_:/.match?(v)
473
+ elsif p == "@type"
474
+ raise Csvlint::Csvw::MetadataError.new("tableSchema.@type"), "@type of schema is not 'Schema'" if v != "Schema"
475
+ else
476
+ v, warning, type = check_property(p, v, schema_base_url, schema_lang)
477
+ if (type == :schema || type == :inherited) && (warning.nil? || warning.empty?)
478
+ schema[p] = v
478
479
  else
479
- v, warning, type = check_property(p, v, schema_base_url, schema_lang)
480
- if (type == :schema || type == :inherited) && (warning.nil? || warning.empty?)
481
- schema[p] = v
482
- else
483
- schema.delete(p)
484
- warnings << :invalid_property unless (type == :schema || type == :inherited)
485
- warnings += Array(warning)
486
- end
480
+ schema.delete(p)
481
+ warnings << :invalid_property unless type == :schema || type == :inherited
482
+ warnings += Array(warning)
487
483
  end
488
484
  end
489
- return schema, warnings, :table
490
- },
491
- "url" => link_property(:table),
492
- # dialect properties
493
- "commentPrefix" => string_property(:dialect),
494
- "delimiter" => string_property(:dialect),
495
- "doubleQuote" => boolean_property(:dialect),
496
- "encoding" => lambda { |value, base_url, lang|
497
- return value, nil, :dialect if VALID_ENCODINGS.include? value
498
- return nil, :invalid_value, :dialect
499
- },
500
- "header" => boolean_property(:dialect),
501
- "headerRowCount" => numeric_property(:dialect),
502
- "lineTerminators" => array_property(:dialect),
503
- "quoteChar" => string_property(:dialect),
504
- "skipBlankRows" => boolean_property(:dialect),
505
- "skipColumns" => numeric_property(:dialect),
506
- "skipInitialSpace" => boolean_property(:dialect),
507
- "skipRows" => numeric_property(:dialect),
508
- "trim" => lambda { |value, base_url, lang|
509
- value = :true if value == true || value == "true"
510
- value = :false if value == false || value == "false"
511
- value = :start if value == "start"
512
- value = :end if value == "end"
513
- return value, nil, :dialect if [:true, :false, :start, :end].include? value
514
- return true, :invalid_value, :dialect
515
- },
516
- # schema properties
517
- "columns" => lambda { |value, base_url, lang| return value, nil, :schema },
518
- "primaryKey" => column_reference_property(:schema),
519
- "foreignKeys" => lambda { |value, base_url, lang|
520
- foreign_keys = []
521
- warnings = []
522
- if value.instance_of? Array
523
- value.each_with_index do |foreign_key,i|
524
- if foreign_key.instance_of? Hash
525
- foreign_key = foreign_key.clone
526
- foreign_key.each do |p,v|
527
- v, warning, type = check_property(p, v, base_url, lang)
528
- if type == :foreign_key && (warning.nil? || warning.empty?)
529
- foreign_key[p] = v
530
- elsif p =~ /:/
531
- raise Csvlint::Csvw::MetadataError.new("foreignKey.#{p}"), "foreignKey includes a prefixed (common) property"
532
- else
533
- foreign_key.delete(p)
534
- warnings << :invalid_property unless type == :foreign_key
535
- warnings += Array(warning)
536
- end
537
- end
538
- foreign_keys << foreign_key
539
- else
540
- warnings << :invalid_foreign_key
541
- end
542
- end
543
- else
544
- warnings << :invalid_value
545
- end
546
- return foreign_keys, warnings, :schema
547
- },
548
- "rowTitles" => column_reference_property(:schema),
549
- # transformation properties
550
- "targetFormat" => lambda { |value, base_url, lang| return value, nil, :transformation },
551
- "scriptFormat" => lambda { |value, base_url, lang| return value, nil, :transformation },
552
- "source" => lambda { |value, base_url, lang| return value, nil, :transformation },
553
- # foreignKey properties
554
- "columnReference" => column_reference_property(:foreign_key),
555
- "reference" => lambda { |value, base_url, lang|
556
- if value.instance_of? Hash
557
- value = value.clone
558
- warnings = []
559
- value.each do |p,v|
560
- if ["resource", "schemaReference", "columnReference"].include? p
485
+ end
486
+ return schema, warnings, :table
487
+ },
488
+ "url" => link_property(:table),
489
+ # dialect properties
490
+ "commentPrefix" => string_property(:dialect),
491
+ "delimiter" => string_property(:dialect),
492
+ "doubleQuote" => boolean_property(:dialect),
493
+ "encoding" => lambda { |value, base_url, lang|
494
+ return value, nil, :dialect if VALID_ENCODINGS.include? value
495
+ return nil, :invalid_value, :dialect
496
+ },
497
+ "header" => boolean_property(:dialect),
498
+ "headerRowCount" => numeric_property(:dialect),
499
+ "lineTerminators" => array_property(:dialect),
500
+ "quoteChar" => string_property(:dialect),
501
+ "skipBlankRows" => boolean_property(:dialect),
502
+ "skipColumns" => numeric_property(:dialect),
503
+ "skipInitialSpace" => boolean_property(:dialect),
504
+ "skipRows" => numeric_property(:dialect),
505
+ "trim" => lambda { |value, base_url, lang|
506
+ value = :true if value == true || value == "true"
507
+ value = :false if value == false || value == "false"
508
+ value = :start if value == "start"
509
+ value = :end if value == "end"
510
+ return value, nil, :dialect if [:true, :false, :start, :end].include? value
511
+ return true, :invalid_value, :dialect
512
+ },
513
+ # schema properties
514
+ "columns" => lambda { |value, base_url, lang| return value, nil, :schema },
515
+ "primaryKey" => column_reference_property(:schema),
516
+ "foreignKeys" => lambda { |value, base_url, lang|
517
+ foreign_keys = []
518
+ warnings = []
519
+ if value.instance_of? Array
520
+ value.each_with_index do |foreign_key, i|
521
+ if foreign_key.instance_of? Hash
522
+ foreign_key = foreign_key.clone
523
+ foreign_key.each do |p, v|
561
524
  v, warning, type = check_property(p, v, base_url, lang)
562
- if warning.nil? || warning.empty?
563
- value[p] = v
525
+ if type == :foreign_key && (warning.nil? || warning.empty?)
526
+ foreign_key[p] = v
527
+ elsif /:/.match?(p)
528
+ raise Csvlint::Csvw::MetadataError.new("foreignKey.#{p}"), "foreignKey includes a prefixed (common) property"
564
529
  else
565
- value.delete(p)
530
+ foreign_key.delete(p)
531
+ warnings << :invalid_property unless type == :foreign_key
566
532
  warnings += Array(warning)
567
533
  end
568
- elsif p =~ /:/
569
- raise Csvlint::Csvw::MetadataError.new("foreignKey.reference.#{p}"), "foreignKey reference includes a prefixed (common) property"
534
+ end
535
+ foreign_keys << foreign_key
536
+ else
537
+ warnings << :invalid_foreign_key
538
+ end
539
+ end
540
+ else
541
+ warnings << :invalid_value
542
+ end
543
+ return foreign_keys, warnings, :schema
544
+ },
545
+ "rowTitles" => column_reference_property(:schema),
546
+ # transformation properties
547
+ "targetFormat" => lambda { |value, base_url, lang| return value, nil, :transformation },
548
+ "scriptFormat" => lambda { |value, base_url, lang| return value, nil, :transformation },
549
+ "source" => lambda { |value, base_url, lang| return value, nil, :transformation },
550
+ # foreignKey properties
551
+ "columnReference" => column_reference_property(:foreign_key),
552
+ "reference" => lambda { |value, base_url, lang|
553
+ if value.instance_of? Hash
554
+ value = value.clone
555
+ warnings = []
556
+ value.each do |p, v|
557
+ if ["resource", "schemaReference", "columnReference"].include? p
558
+ v, warning, type = check_property(p, v, base_url, lang)
559
+ if warning.nil? || warning.empty?
560
+ value[p] = v
570
561
  else
571
562
  value.delete(p)
572
- warnings << :invalid_property
563
+ warnings += Array(warning)
573
564
  end
565
+ elsif /:/.match?(p)
566
+ raise Csvlint::Csvw::MetadataError.new("foreignKey.reference.#{p}"), "foreignKey reference includes a prefixed (common) property"
567
+ else
568
+ value.delete(p)
569
+ warnings << :invalid_property
574
570
  end
575
- raise Csvlint::Csvw::MetadataError.new("foreignKey.reference.columnReference"), "foreignKey reference columnReference is missing" unless value["columnReference"]
576
- raise Csvlint::Csvw::MetadataError.new("foreignKey.reference"), "foreignKey reference does not have either resource or schemaReference" unless value["resource"] || value["schemaReference"]
577
- raise Csvlint::Csvw::MetadataError.new("foreignKey.reference"), "foreignKey reference has both resource and schemaReference" if value["resource"] && value["schemaReference"]
578
- return value, warnings, :foreign_key
579
- else
580
- raise Csvlint::Csvw::MetadataError.new("foreignKey.reference"), "foreignKey reference is not an object"
581
571
  end
582
- },
583
- # foreignKey reference properties
584
- "resource" => lambda { |value, base_url, lang| return value, nil, :foreign_key_reference },
585
- "schemaReference" => lambda { |value, base_url, lang|
586
- return URI.join(base_url, value).to_s, nil, :foreign_key_reference
587
- }
588
- }
589
-
590
- NAMESPACES = {
591
- "dcat" => "http://www.w3.org/ns/dcat#",
592
- "qb" => "http://purl.org/linked-data/cube#",
593
- "grddl" => "http://www.w3.org/2003/g/data-view#",
594
- "ma" => "http://www.w3.org/ns/ma-ont#",
595
- "org" => "http://www.w3.org/ns/org#",
596
- "owl" => "http://www.w3.org/2002/07/owl#",
597
- "prov" => "http://www.w3.org/ns/prov#",
598
- "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
599
- "rdfa" => "http://www.w3.org/ns/rdfa#",
600
- "rdfs" => "http://www.w3.org/2000/01/rdf-schema#",
601
- "rif" => "http://www.w3.org/2007/rif#",
602
- "rr" => "http://www.w3.org/ns/r2rml#",
603
- "sd" => "http://www.w3.org/ns/sparql-service-description#",
604
- "skos" => "http://www.w3.org/2004/02/skos/core#",
605
- "skosxl" => "http://www.w3.org/2008/05/skos-xl#",
606
- "wdr" => "http://www.w3.org/2007/05/powder#",
607
- "void" => "http://rdfs.org/ns/void#",
608
- "wdrs" => "http://www.w3.org/2007/05/powder-s#",
609
- "xhv" => "http://www.w3.org/1999/xhtml/vocab#",
610
- "xml" => "http://www.w3.org/XML/1998/namespace",
611
- "xsd" => "http://www.w3.org/2001/XMLSchema#",
612
- "csvw" => "http://www.w3.org/ns/csvw#",
613
- "cnt" => "http://www.w3.org/2008/content",
614
- "earl" => "http://www.w3.org/ns/earl#",
615
- "ht" => "http://www.w3.org/2006/http#",
616
- "oa" => "http://www.w3.org/ns/oa#",
617
- "ptr" => "http://www.w3.org/2009/pointers#",
618
- "cc" => "http://creativecommons.org/ns#",
619
- "ctag" => "http://commontag.org/ns#",
620
- "dc" => "http://purl.org/dc/terms/",
621
- "dcterms" => "http://purl.org/dc/terms/",
622
- "dc11" => "http://purl.org/dc/elements/1.1/",
623
- "foaf" => "http://xmlns.com/foaf/0.1/",
624
- "gr" => "http://purl.org/goodrelations/v1#",
625
- "ical" => "http://www.w3.org/2002/12/cal/icaltzd#",
626
- "og" => "http://ogp.me/ns#",
627
- "rev" => "http://purl.org/stuff/rev#",
628
- "sioc" => "http://rdfs.org/sioc/ns#",
629
- "v" => "http://rdf.data-vocabulary.org/#",
630
- "vcard" => "http://www.w3.org/2006/vcard/ns#",
631
- "schema" => "http://schema.org/"
632
- }
633
-
634
- BCP47_REGULAR_REGEXP = "(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)"
635
- BCP47_IRREGULAR_REGEXP = "(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)"
636
- BCP47_GRANDFATHERED_REGEXP = "(?<grandfathered>" + BCP47_IRREGULAR_REGEXP + "|" + BCP47_REGULAR_REGEXP + ")"
637
- BCP47_PRIVATE_USE_REGEXP = "(?<privateUse>x(-[A-Za-z0-9]{1,8})+)"
638
- BCP47_SINGLETON_REGEXP = "[0-9A-WY-Za-wy-z]"
639
- BCP47_EXTENSION_REGEXP = "(?<extension>" + BCP47_SINGLETON_REGEXP + "(-[A-Za-z0-9]{2,8})+)"
640
- BCP47_VARIANT_REGEXP = "(?<variant>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3})"
641
- BCP47_REGION_REGEXP = "(?<region>[A-Za-z]{2}|[0-9]{3})"
642
- BCP47_SCRIPT_REGEXP = "(?<script>[A-Za-z]{4})"
643
- BCP47_EXTLANG_REGEXP = "(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2})"
644
- BCP47_LANGUAGE_REGEXP = "(?<language>([A-Za-z]{2,3}(-" + BCP47_EXTLANG_REGEXP + ")?)|[A-Za-z]{4}|[A-Za-z]{5,8})"
645
- BCP47_LANGTAG_REGEXP = "(" + BCP47_LANGUAGE_REGEXP + "(-" + BCP47_SCRIPT_REGEXP + ")?" + "(-" + BCP47_REGION_REGEXP + ")?" + "(-" + BCP47_VARIANT_REGEXP + ")*" + "(-" + BCP47_EXTENSION_REGEXP + ")*" + "(-" + BCP47_PRIVATE_USE_REGEXP + ")?" + ")"
646
- BCP47_LANGUAGETAG_REGEXP = "^(" + BCP47_GRANDFATHERED_REGEXP + "|" + BCP47_LANGTAG_REGEXP + "|" + BCP47_PRIVATE_USE_REGEXP + ")$"
647
- BCP47_REGEXP = Regexp.new(BCP47_LANGUAGETAG_REGEXP)
648
-
649
- NAME_REGEXP = /^([A-Za-z0-9]|(%[A-F0-9][A-F0-9]))([A-Za-z0-9_]|(%[A-F0-9][A-F0-9]))*$/
650
-
651
- BUILT_IN_TYPES = ["TableGroup", "Table", "Schema", "Column", "Dialect", "Template", "Datatype"]
652
-
653
- REGEXP_FORMAT_DATATYPES = [
654
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral",
655
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML",
656
- "http://www.w3.org/ns/csvw#JSON",
657
- "http://www.w3.org/2001/XMLSchema#anyAtomicType",
658
- "http://www.w3.org/2001/XMLSchema#anyURI",
659
- "http://www.w3.org/2001/XMLSchema#base64Binary",
660
- "http://www.w3.org/2001/XMLSchema#duration",
661
- "http://www.w3.org/2001/XMLSchema#dayTimeDuration",
662
- "http://www.w3.org/2001/XMLSchema#yearMonthDuration",
663
- "http://www.w3.org/2001/XMLSchema#hexBinary",
664
- "http://www.w3.org/2001/XMLSchema#QName",
665
- "http://www.w3.org/2001/XMLSchema#string",
666
- "http://www.w3.org/2001/XMLSchema#normalizedString",
667
- "http://www.w3.org/2001/XMLSchema#token",
668
- "http://www.w3.org/2001/XMLSchema#language",
669
- "http://www.w3.org/2001/XMLSchema#Name",
670
- "http://www.w3.org/2001/XMLSchema#NMTOKEN"
671
- ]
672
-
673
- STRING_DATATYPES = [
674
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral",
675
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML",
676
- "http://www.w3.org/ns/csvw#JSON",
677
- "http://www.w3.org/2001/XMLSchema#string",
678
- "http://www.w3.org/2001/XMLSchema#normalizedString",
679
- "http://www.w3.org/2001/XMLSchema#token",
680
- "http://www.w3.org/2001/XMLSchema#language",
681
- "http://www.w3.org/2001/XMLSchema#Name",
682
- "http://www.w3.org/2001/XMLSchema#NMTOKEN"
683
- ]
684
-
685
- BINARY_DATATYPES = [
686
- "http://www.w3.org/2001/XMLSchema#base64Binary",
687
- "http://www.w3.org/2001/XMLSchema#hexBinary"
688
- ]
689
-
690
- INTEGER_FORMAT_DATATYPES = [
691
- "http://www.w3.org/2001/XMLSchema#integer",
692
- "http://www.w3.org/2001/XMLSchema#long",
693
- "http://www.w3.org/2001/XMLSchema#int",
694
- "http://www.w3.org/2001/XMLSchema#short",
695
- "http://www.w3.org/2001/XMLSchema#byte",
696
- "http://www.w3.org/2001/XMLSchema#nonNegativeInteger",
697
- "http://www.w3.org/2001/XMLSchema#positiveInteger",
698
- "http://www.w3.org/2001/XMLSchema#unsignedLong",
699
- "http://www.w3.org/2001/XMLSchema#unsignedInt",
700
- "http://www.w3.org/2001/XMLSchema#unsignedShort",
701
- "http://www.w3.org/2001/XMLSchema#unsignedByte",
702
- "http://www.w3.org/2001/XMLSchema#nonPositiveInteger",
703
- "http://www.w3.org/2001/XMLSchema#negativeInteger"
704
- ]
705
-
706
- NUMERIC_FORMAT_DATATYPES = [
707
- "http://www.w3.org/2001/XMLSchema#decimal",
708
- "http://www.w3.org/2001/XMLSchema#double",
709
- "http://www.w3.org/2001/XMLSchema#float"
710
- ] + INTEGER_FORMAT_DATATYPES
711
-
712
- DATE_FORMAT_DATATYPES = [
713
- "http://www.w3.org/2001/XMLSchema#date",
714
- "http://www.w3.org/2001/XMLSchema#dateTime",
715
- "http://www.w3.org/2001/XMLSchema#dateTimeStamp",
716
- "http://www.w3.org/2001/XMLSchema#time"
717
- ]
718
-
719
- BUILT_IN_DATATYPES = {
720
- "number" => "http://www.w3.org/2001/XMLSchema#double",
721
- "binary" => "http://www.w3.org/2001/XMLSchema#base64Binary",
722
- "datetime" => "http://www.w3.org/2001/XMLSchema#dateTime",
723
- "any" => "http://www.w3.org/2001/XMLSchema#anyAtomicType",
724
- "xml" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral",
725
- "html" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML",
726
- "json" => "http://www.w3.org/ns/csvw#JSON",
727
- "anyAtomicType" => "http://www.w3.org/2001/XMLSchema#anyAtomicType",
728
- "anyURI" => "http://www.w3.org/2001/XMLSchema#anyURI",
729
- "base64Binary" => "http://www.w3.org/2001/XMLSchema#base64Binary",
730
- "boolean" => "http://www.w3.org/2001/XMLSchema#boolean",
731
- "date" => "http://www.w3.org/2001/XMLSchema#date",
732
- "dateTime" => "http://www.w3.org/2001/XMLSchema#dateTime",
733
- "dateTimeStamp" => "http://www.w3.org/2001/XMLSchema#dateTimeStamp",
734
- "decimal" => "http://www.w3.org/2001/XMLSchema#decimal",
735
- "integer" => "http://www.w3.org/2001/XMLSchema#integer",
736
- "long" => "http://www.w3.org/2001/XMLSchema#long",
737
- "int" => "http://www.w3.org/2001/XMLSchema#int",
738
- "short" => "http://www.w3.org/2001/XMLSchema#short",
739
- "byte" => "http://www.w3.org/2001/XMLSchema#byte",
740
- "nonNegativeInteger" => "http://www.w3.org/2001/XMLSchema#nonNegativeInteger",
741
- "positiveInteger" => "http://www.w3.org/2001/XMLSchema#positiveInteger",
742
- "unsignedLong" => "http://www.w3.org/2001/XMLSchema#unsignedLong",
743
- "unsignedInt" => "http://www.w3.org/2001/XMLSchema#unsignedInt",
744
- "unsignedShort" => "http://www.w3.org/2001/XMLSchema#unsignedShort",
745
- "unsignedByte" => "http://www.w3.org/2001/XMLSchema#unsignedByte",
746
- "nonPositiveInteger" => "http://www.w3.org/2001/XMLSchema#nonPositiveInteger",
747
- "negativeInteger" => "http://www.w3.org/2001/XMLSchema#negativeInteger",
748
- "double" => "http://www.w3.org/2001/XMLSchema#double",
749
- "duration" => "http://www.w3.org/2001/XMLSchema#duration",
750
- "dayTimeDuration" => "http://www.w3.org/2001/XMLSchema#dayTimeDuration",
751
- "yearMonthDuration" => "http://www.w3.org/2001/XMLSchema#yearMonthDuration",
752
- "float" => "http://www.w3.org/2001/XMLSchema#float",
753
- "gDay" => "http://www.w3.org/2001/XMLSchema#gDay",
754
- "gMonth" => "http://www.w3.org/2001/XMLSchema#gMonth",
755
- "gMonthDay" => "http://www.w3.org/2001/XMLSchema#gMonthDay",
756
- "gYear" => "http://www.w3.org/2001/XMLSchema#gYear",
757
- "gYearMonth" => "http://www.w3.org/2001/XMLSchema#gYearMonth",
758
- "hexBinary" => "http://www.w3.org/2001/XMLSchema#hexBinary",
759
- "QName" => "http://www.w3.org/2001/XMLSchema#QName",
760
- "string" => "http://www.w3.org/2001/XMLSchema#string",
761
- "normalizedString" => "http://www.w3.org/2001/XMLSchema#normalizedString",
762
- "token" => "http://www.w3.org/2001/XMLSchema#token",
763
- "language" => "http://www.w3.org/2001/XMLSchema#language",
764
- "Name" => "http://www.w3.org/2001/XMLSchema#Name",
765
- "NMTOKEN" => "http://www.w3.org/2001/XMLSchema#NMTOKEN",
766
- "time" => "http://www.w3.org/2001/XMLSchema#time"
572
+ raise Csvlint::Csvw::MetadataError.new("foreignKey.reference.columnReference"), "foreignKey reference columnReference is missing" unless value["columnReference"]
573
+ raise Csvlint::Csvw::MetadataError.new("foreignKey.reference"), "foreignKey reference does not have either resource or schemaReference" unless value["resource"] || value["schemaReference"]
574
+ raise Csvlint::Csvw::MetadataError.new("foreignKey.reference"), "foreignKey reference has both resource and schemaReference" if value["resource"] && value["schemaReference"]
575
+ return value, warnings, :foreign_key
576
+ else
577
+ raise Csvlint::Csvw::MetadataError.new("foreignKey.reference"), "foreignKey reference is not an object"
578
+ end
579
+ },
580
+ # foreignKey reference properties
581
+ "resource" => lambda { |value, base_url, lang| return value, nil, :foreign_key_reference },
582
+ "schemaReference" => lambda { |value, base_url, lang|
583
+ return URI.join(base_url, value).to_s, nil, :foreign_key_reference
767
584
  }
768
-
769
- VALID_ENCODINGS = [
770
- "utf-8",
771
- "ibm866",
772
- "iso-8859-2",
773
- "iso-8859-3",
774
- "iso-8859-4",
775
- "iso-8859-5",
776
- "iso-8859-6",
777
- "iso-8859-7",
778
- "iso-8859-8",
779
- "iso-8859-8-i",
780
- "iso-8859-10",
781
- "iso-8859-13",
782
- "iso-8859-14",
783
- "iso-8859-15",
784
- "iso-8859-16",
785
- "koi8-r",
786
- "koi8-u",
787
- "macintosh",
788
- "windows-874",
789
- "windows-1250",
790
- "windows-1251",
791
- "windows-1252",
792
- "windows-1253",
793
- "windows-1254",
794
- "windows-1255",
795
- "windows-1256",
796
- "windows-1257",
797
- "windows-1258",
798
- "x-mac-cyrillic",
799
- "gb18030",
800
- "hz-gb-2312",
801
- "big5",
802
- "euc-jp",
803
- "iso-2022-jp",
804
- "shift_jis",
805
- "euc-kr",
806
- "replacement",
807
- "utf-16be",
808
- "utf-16le",
809
- "x-user-defined"
810
- ]
585
+ }
586
+
587
+ NAMESPACES = {
588
+ "dcat" => "http://www.w3.org/ns/dcat#",
589
+ "qb" => "http://purl.org/linked-data/cube#",
590
+ "grddl" => "http://www.w3.org/2003/g/data-view#",
591
+ "ma" => "http://www.w3.org/ns/ma-ont#",
592
+ "org" => "http://www.w3.org/ns/org#",
593
+ "owl" => "http://www.w3.org/2002/07/owl#",
594
+ "prov" => "http://www.w3.org/ns/prov#",
595
+ "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
596
+ "rdfa" => "http://www.w3.org/ns/rdfa#",
597
+ "rdfs" => "http://www.w3.org/2000/01/rdf-schema#",
598
+ "rif" => "http://www.w3.org/2007/rif#",
599
+ "rr" => "http://www.w3.org/ns/r2rml#",
600
+ "sd" => "http://www.w3.org/ns/sparql-service-description#",
601
+ "skos" => "http://www.w3.org/2004/02/skos/core#",
602
+ "skosxl" => "http://www.w3.org/2008/05/skos-xl#",
603
+ "wdr" => "http://www.w3.org/2007/05/powder#",
604
+ "void" => "http://rdfs.org/ns/void#",
605
+ "wdrs" => "http://www.w3.org/2007/05/powder-s#",
606
+ "xhv" => "http://www.w3.org/1999/xhtml/vocab#",
607
+ "xml" => "http://www.w3.org/XML/1998/namespace",
608
+ "xsd" => "http://www.w3.org/2001/XMLSchema#",
609
+ "csvw" => "http://www.w3.org/ns/csvw#",
610
+ "cnt" => "http://www.w3.org/2008/content",
611
+ "earl" => "http://www.w3.org/ns/earl#",
612
+ "ht" => "http://www.w3.org/2006/http#",
613
+ "oa" => "http://www.w3.org/ns/oa#",
614
+ "ptr" => "http://www.w3.org/2009/pointers#",
615
+ "cc" => "http://creativecommons.org/ns#",
616
+ "ctag" => "http://commontag.org/ns#",
617
+ "dc" => "http://purl.org/dc/terms/",
618
+ "dcterms" => "http://purl.org/dc/terms/",
619
+ "dc11" => "http://purl.org/dc/elements/1.1/",
620
+ "foaf" => "http://xmlns.com/foaf/0.1/",
621
+ "gr" => "http://purl.org/goodrelations/v1#",
622
+ "ical" => "http://www.w3.org/2002/12/cal/icaltzd#",
623
+ "og" => "http://ogp.me/ns#",
624
+ "rev" => "http://purl.org/stuff/rev#",
625
+ "sioc" => "http://rdfs.org/sioc/ns#",
626
+ "v" => "http://rdf.data-vocabulary.org/#",
627
+ "vcard" => "http://www.w3.org/2006/vcard/ns#",
628
+ "schema" => "http://schema.org/"
629
+ }
630
+
631
+ BCP47_REGULAR_REGEXP = "(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)"
632
+ BCP47_IRREGULAR_REGEXP = "(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)"
633
+ BCP47_GRANDFATHERED_REGEXP = "(?<grandfathered>" + BCP47_IRREGULAR_REGEXP + "|" + BCP47_REGULAR_REGEXP + ")"
634
+ BCP47_PRIVATE_USE_REGEXP = "(?<privateUse>x(-[A-Za-z0-9]{1,8})+)"
635
+ BCP47_SINGLETON_REGEXP = "[0-9A-WY-Za-wy-z]"
636
+ BCP47_EXTENSION_REGEXP = "(?<extension>" + BCP47_SINGLETON_REGEXP + "(-[A-Za-z0-9]{2,8})+)"
637
+ BCP47_VARIANT_REGEXP = "(?<variant>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3})"
638
+ BCP47_REGION_REGEXP = "(?<region>[A-Za-z]{2}|[0-9]{3})"
639
+ BCP47_SCRIPT_REGEXP = "(?<script>[A-Za-z]{4})"
640
+ BCP47_EXTLANG_REGEXP = "(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2})"
641
+ BCP47_LANGUAGE_REGEXP = "(?<language>([A-Za-z]{2,3}(-" + BCP47_EXTLANG_REGEXP + ")?)|[A-Za-z]{4}|[A-Za-z]{5,8})"
642
+ BCP47_LANGTAG_REGEXP = "(" + BCP47_LANGUAGE_REGEXP + "(-" + BCP47_SCRIPT_REGEXP + ")?" + "(-" + BCP47_REGION_REGEXP + ")?" + "(-" + BCP47_VARIANT_REGEXP + ")*" + "(-" + BCP47_EXTENSION_REGEXP + ")*" + "(-" + BCP47_PRIVATE_USE_REGEXP + ")?" + ")"
643
+ BCP47_LANGUAGETAG_REGEXP = "^(" + BCP47_GRANDFATHERED_REGEXP + "|" + BCP47_LANGTAG_REGEXP + "|" + BCP47_PRIVATE_USE_REGEXP + ")$"
644
+ BCP47_REGEXP = Regexp.new(BCP47_LANGUAGETAG_REGEXP)
645
+
646
+ NAME_REGEXP = /^([A-Za-z0-9]|(%[A-F0-9][A-F0-9]))([A-Za-z0-9_]|(%[A-F0-9][A-F0-9]))*$/
647
+
648
+ BUILT_IN_TYPES = ["TableGroup", "Table", "Schema", "Column", "Dialect", "Template", "Datatype"]
649
+
650
+ REGEXP_FORMAT_DATATYPES = [
651
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral",
652
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML",
653
+ "http://www.w3.org/ns/csvw#JSON",
654
+ "http://www.w3.org/2001/XMLSchema#anyAtomicType",
655
+ "http://www.w3.org/2001/XMLSchema#anyURI",
656
+ "http://www.w3.org/2001/XMLSchema#base64Binary",
657
+ "http://www.w3.org/2001/XMLSchema#duration",
658
+ "http://www.w3.org/2001/XMLSchema#dayTimeDuration",
659
+ "http://www.w3.org/2001/XMLSchema#yearMonthDuration",
660
+ "http://www.w3.org/2001/XMLSchema#hexBinary",
661
+ "http://www.w3.org/2001/XMLSchema#QName",
662
+ "http://www.w3.org/2001/XMLSchema#string",
663
+ "http://www.w3.org/2001/XMLSchema#normalizedString",
664
+ "http://www.w3.org/2001/XMLSchema#token",
665
+ "http://www.w3.org/2001/XMLSchema#language",
666
+ "http://www.w3.org/2001/XMLSchema#Name",
667
+ "http://www.w3.org/2001/XMLSchema#NMTOKEN"
668
+ ]
669
+
670
+ STRING_DATATYPES = [
671
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral",
672
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML",
673
+ "http://www.w3.org/ns/csvw#JSON",
674
+ "http://www.w3.org/2001/XMLSchema#string",
675
+ "http://www.w3.org/2001/XMLSchema#normalizedString",
676
+ "http://www.w3.org/2001/XMLSchema#token",
677
+ "http://www.w3.org/2001/XMLSchema#language",
678
+ "http://www.w3.org/2001/XMLSchema#Name",
679
+ "http://www.w3.org/2001/XMLSchema#NMTOKEN"
680
+ ]
681
+
682
+ BINARY_DATATYPES = [
683
+ "http://www.w3.org/2001/XMLSchema#base64Binary",
684
+ "http://www.w3.org/2001/XMLSchema#hexBinary"
685
+ ]
686
+
687
+ INTEGER_FORMAT_DATATYPES = [
688
+ "http://www.w3.org/2001/XMLSchema#integer",
689
+ "http://www.w3.org/2001/XMLSchema#long",
690
+ "http://www.w3.org/2001/XMLSchema#int",
691
+ "http://www.w3.org/2001/XMLSchema#short",
692
+ "http://www.w3.org/2001/XMLSchema#byte",
693
+ "http://www.w3.org/2001/XMLSchema#nonNegativeInteger",
694
+ "http://www.w3.org/2001/XMLSchema#positiveInteger",
695
+ "http://www.w3.org/2001/XMLSchema#unsignedLong",
696
+ "http://www.w3.org/2001/XMLSchema#unsignedInt",
697
+ "http://www.w3.org/2001/XMLSchema#unsignedShort",
698
+ "http://www.w3.org/2001/XMLSchema#unsignedByte",
699
+ "http://www.w3.org/2001/XMLSchema#nonPositiveInteger",
700
+ "http://www.w3.org/2001/XMLSchema#negativeInteger"
701
+ ]
702
+
703
+ NUMERIC_FORMAT_DATATYPES = [
704
+ "http://www.w3.org/2001/XMLSchema#decimal",
705
+ "http://www.w3.org/2001/XMLSchema#double",
706
+ "http://www.w3.org/2001/XMLSchema#float"
707
+ ] + INTEGER_FORMAT_DATATYPES
708
+
709
+ DATE_FORMAT_DATATYPES = [
710
+ "http://www.w3.org/2001/XMLSchema#date",
711
+ "http://www.w3.org/2001/XMLSchema#dateTime",
712
+ "http://www.w3.org/2001/XMLSchema#dateTimeStamp",
713
+ "http://www.w3.org/2001/XMLSchema#time"
714
+ ]
715
+
716
+ BUILT_IN_DATATYPES = {
717
+ "number" => "http://www.w3.org/2001/XMLSchema#double",
718
+ "binary" => "http://www.w3.org/2001/XMLSchema#base64Binary",
719
+ "datetime" => "http://www.w3.org/2001/XMLSchema#dateTime",
720
+ "any" => "http://www.w3.org/2001/XMLSchema#anyAtomicType",
721
+ "xml" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral",
722
+ "html" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML",
723
+ "json" => "http://www.w3.org/ns/csvw#JSON",
724
+ "anyAtomicType" => "http://www.w3.org/2001/XMLSchema#anyAtomicType",
725
+ "anyURI" => "http://www.w3.org/2001/XMLSchema#anyURI",
726
+ "base64Binary" => "http://www.w3.org/2001/XMLSchema#base64Binary",
727
+ "boolean" => "http://www.w3.org/2001/XMLSchema#boolean",
728
+ "date" => "http://www.w3.org/2001/XMLSchema#date",
729
+ "dateTime" => "http://www.w3.org/2001/XMLSchema#dateTime",
730
+ "dateTimeStamp" => "http://www.w3.org/2001/XMLSchema#dateTimeStamp",
731
+ "decimal" => "http://www.w3.org/2001/XMLSchema#decimal",
732
+ "integer" => "http://www.w3.org/2001/XMLSchema#integer",
733
+ "long" => "http://www.w3.org/2001/XMLSchema#long",
734
+ "int" => "http://www.w3.org/2001/XMLSchema#int",
735
+ "short" => "http://www.w3.org/2001/XMLSchema#short",
736
+ "byte" => "http://www.w3.org/2001/XMLSchema#byte",
737
+ "nonNegativeInteger" => "http://www.w3.org/2001/XMLSchema#nonNegativeInteger",
738
+ "positiveInteger" => "http://www.w3.org/2001/XMLSchema#positiveInteger",
739
+ "unsignedLong" => "http://www.w3.org/2001/XMLSchema#unsignedLong",
740
+ "unsignedInt" => "http://www.w3.org/2001/XMLSchema#unsignedInt",
741
+ "unsignedShort" => "http://www.w3.org/2001/XMLSchema#unsignedShort",
742
+ "unsignedByte" => "http://www.w3.org/2001/XMLSchema#unsignedByte",
743
+ "nonPositiveInteger" => "http://www.w3.org/2001/XMLSchema#nonPositiveInteger",
744
+ "negativeInteger" => "http://www.w3.org/2001/XMLSchema#negativeInteger",
745
+ "double" => "http://www.w3.org/2001/XMLSchema#double",
746
+ "duration" => "http://www.w3.org/2001/XMLSchema#duration",
747
+ "dayTimeDuration" => "http://www.w3.org/2001/XMLSchema#dayTimeDuration",
748
+ "yearMonthDuration" => "http://www.w3.org/2001/XMLSchema#yearMonthDuration",
749
+ "float" => "http://www.w3.org/2001/XMLSchema#float",
750
+ "gDay" => "http://www.w3.org/2001/XMLSchema#gDay",
751
+ "gMonth" => "http://www.w3.org/2001/XMLSchema#gMonth",
752
+ "gMonthDay" => "http://www.w3.org/2001/XMLSchema#gMonthDay",
753
+ "gYear" => "http://www.w3.org/2001/XMLSchema#gYear",
754
+ "gYearMonth" => "http://www.w3.org/2001/XMLSchema#gYearMonth",
755
+ "hexBinary" => "http://www.w3.org/2001/XMLSchema#hexBinary",
756
+ "QName" => "http://www.w3.org/2001/XMLSchema#QName",
757
+ "string" => "http://www.w3.org/2001/XMLSchema#string",
758
+ "normalizedString" => "http://www.w3.org/2001/XMLSchema#normalizedString",
759
+ "token" => "http://www.w3.org/2001/XMLSchema#token",
760
+ "language" => "http://www.w3.org/2001/XMLSchema#language",
761
+ "Name" => "http://www.w3.org/2001/XMLSchema#Name",
762
+ "NMTOKEN" => "http://www.w3.org/2001/XMLSchema#NMTOKEN",
763
+ "time" => "http://www.w3.org/2001/XMLSchema#time"
764
+ }
765
+
766
+ VALID_ENCODINGS = [
767
+ "utf-8",
768
+ "ibm866",
769
+ "iso-8859-2",
770
+ "iso-8859-3",
771
+ "iso-8859-4",
772
+ "iso-8859-5",
773
+ "iso-8859-6",
774
+ "iso-8859-7",
775
+ "iso-8859-8",
776
+ "iso-8859-8-i",
777
+ "iso-8859-10",
778
+ "iso-8859-13",
779
+ "iso-8859-14",
780
+ "iso-8859-15",
781
+ "iso-8859-16",
782
+ "koi8-r",
783
+ "koi8-u",
784
+ "macintosh",
785
+ "windows-874",
786
+ "windows-1250",
787
+ "windows-1251",
788
+ "windows-1252",
789
+ "windows-1253",
790
+ "windows-1254",
791
+ "windows-1255",
792
+ "windows-1256",
793
+ "windows-1257",
794
+ "windows-1258",
795
+ "x-mac-cyrillic",
796
+ "gb18030",
797
+ "hz-gb-2312",
798
+ "big5",
799
+ "euc-jp",
800
+ "iso-2022-jp",
801
+ "shift_jis",
802
+ "euc-kr",
803
+ "replacement",
804
+ "utf-16be",
805
+ "utf-16le",
806
+ "x-user-defined"
807
+ ]
811
808
  end
812
809
  end
813
810
  end