csvlint 0.4.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/push.yml +35 -0
  4. data/.gitignore +1 -0
  5. data/.ruby-version +1 -1
  6. data/.standard_todo.yml +43 -0
  7. data/CHANGELOG.md +38 -0
  8. data/Dockerfile +16 -0
  9. data/Gemfile +2 -2
  10. data/README.md +13 -10
  11. data/Rakefile +7 -7
  12. data/bin/create_schema +2 -2
  13. data/csvlint.gemspec +19 -22
  14. data/docker_notes_for_windows.txt +20 -0
  15. data/features/step_definitions/cli_steps.rb +11 -11
  16. data/features/step_definitions/information_steps.rb +4 -4
  17. data/features/step_definitions/parse_csv_steps.rb +11 -11
  18. data/features/step_definitions/schema_validation_steps.rb +10 -10
  19. data/features/step_definitions/sources_steps.rb +1 -1
  20. data/features/step_definitions/validation_errors_steps.rb +19 -19
  21. data/features/step_definitions/validation_info_steps.rb +9 -9
  22. data/features/step_definitions/validation_warnings_steps.rb +11 -11
  23. data/features/support/aruba.rb +10 -9
  24. data/features/support/earl_formatter.rb +39 -39
  25. data/features/support/env.rb +10 -11
  26. data/features/support/load_tests.rb +109 -105
  27. data/features/support/webmock.rb +3 -1
  28. data/lib/csvlint/cli.rb +136 -142
  29. data/lib/csvlint/csvw/column.rb +279 -280
  30. data/lib/csvlint/csvw/date_format.rb +90 -92
  31. data/lib/csvlint/csvw/metadata_error.rb +1 -3
  32. data/lib/csvlint/csvw/number_format.rb +40 -32
  33. data/lib/csvlint/csvw/property_checker.rb +714 -717
  34. data/lib/csvlint/csvw/table.rb +49 -52
  35. data/lib/csvlint/csvw/table_group.rb +24 -23
  36. data/lib/csvlint/error_collector.rb +2 -0
  37. data/lib/csvlint/error_message.rb +0 -1
  38. data/lib/csvlint/field.rb +153 -141
  39. data/lib/csvlint/schema.rb +35 -43
  40. data/lib/csvlint/validate.rb +173 -151
  41. data/lib/csvlint/version.rb +1 -1
  42. data/lib/csvlint.rb +22 -23
  43. data/spec/csvw/column_spec.rb +15 -16
  44. data/spec/csvw/date_format_spec.rb +5 -7
  45. data/spec/csvw/number_format_spec.rb +2 -4
  46. data/spec/csvw/table_group_spec.rb +103 -105
  47. data/spec/csvw/table_spec.rb +71 -73
  48. data/spec/field_spec.rb +116 -121
  49. data/spec/schema_spec.rb +131 -141
  50. data/spec/spec_helper.rb +6 -6
  51. data/spec/validator_spec.rb +167 -203
  52. metadata +41 -85
  53. data/.travis.yml +0 -37
@@ -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( 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