rdf-tabular 0.1.1 → 0.1.2

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.
@@ -22,7 +22,7 @@ module RDF::Tabular
22
22
  ##
23
23
  # Initializes the RDF::Tabular Reader instance.
24
24
  #
25
- # @param [Util::File::RemoteDoc, IO, StringIO, Array<Array<String>>] input
25
+ # @param [Util::File::RemoteDoc, IO, StringIO, Array<Array<String>>, String] input
26
26
  # An opened file possibly JSON Metadata,
27
27
  # or an Array used as an internalized array of arrays
28
28
  # @param [Hash{Symbol => Object}] options
@@ -41,7 +41,7 @@ module RDF::Tabular
41
41
  @options[:base] ||= input.base_uri if input.respond_to?(:base_uri)
42
42
  @options[:base] ||= input.path if input.respond_to?(:path)
43
43
  @options[:base] ||= input.filename if input.respond_to?(:filename)
44
- if RDF::URI(@options[:base]).relative? && File.exist?(@options[:base])
44
+ if RDF::URI(@options[:base]).relative? && File.exist?(@options[:base].to_s)
45
45
  @options[:base] = "file:/#{File.expand_path(@options[:base])}"
46
46
  end
47
47
 
@@ -52,7 +52,12 @@ module RDF::Tabular
52
52
  # Minimal implies noProv
53
53
  @options[:noProv] ||= @options[:minimal]
54
54
 
55
- @input = input.is_a?(String) ? StringIO.new(input) : input
55
+ #byebug if input.is_a?(Array)
56
+ @input = case input
57
+ when String then StringIO.new(input)
58
+ when Array then StringIO.new(input.map {|r| r.join(",")}.join("\n"))
59
+ else input
60
+ end
56
61
 
57
62
  depth do
58
63
  # If input is JSON, then the input is the metadata
@@ -69,19 +74,23 @@ module RDF::Tabular
69
74
  elsif @options[:no_found_metadata]
70
75
  # Extract embedded metadata and merge
71
76
  table_metadata = @options[:metadata]
72
- embedded_metadata = table_metadata.dialect.embedded_metadata(input, @options)
73
- @metadata = table_metadata.dup.merge!(embedded_metadata)
74
- else
75
- # HTTP flags
76
- if @input.respond_to?(:headers) &&
77
- input.headers.fetch(:content_type, '').split(';').include?('header=absent')
78
- @options[:metadata] ||= Table.new(url: @options[:base])
79
- @options[:metadata].dialect.header = false
77
+ dialect = table_metadata.dialect.dup
78
+
79
+ # HTTP flags for setting header values
80
+ dialect.header = false if (input.headers.fetch(:content_type, '').split(';').include?('header=absent') rescue false)
81
+ dialect.encoding = input.charset if (input.charset rescue nil)
82
+ dialect.separator = "\t" if (input.content_type == "text/tsv" rescue nil)
83
+
84
+ embedded_metadata = dialect.embedded_metadata(input, @options)
85
+ if lang = (input.headers[:content_language] rescue "")
86
+ embedded_metadata.lang = lang unless lang.include?(',')
80
87
  end
81
88
 
89
+ @metadata = table_metadata.dup.merge!(embedded_metadata)
90
+ else
82
91
  # It's tabluar data. Find metadata and proceed as if it was specified in the first place
83
- @metadata = Metadata.for_input(@input, @options)
84
- @input = @metadata
92
+ @options[:original_input] = @input
93
+ @input = @metadata = Metadata.for_input(@input, @options)
85
94
  end
86
95
 
87
96
  debug("Reader#initialize") {"input: #{input}, metadata: #{metadata.inspect}"}
@@ -109,67 +118,86 @@ module RDF::Tabular
109
118
  if input.is_a?(Metadata)
110
119
  debug("each_statement: metadata") {input.inspect}
111
120
 
112
- # Validate metadata
113
- input.validate!
114
-
115
121
  depth do
116
122
  # Get Metadata to invoke and open referenced files
117
123
  case input.type
118
124
  when :TableGroup
119
- # Use resolved @id of TableGroup, if available
120
- table_group = input.id || RDF::Node.new
121
- add_statement(0, table_group, RDF.type, CSVW.TableGroup) unless minimal?
122
-
123
- # Common Properties
124
- input.each do |key, value|
125
- next unless key.to_s.include?(':') || key == :notes
126
- input.common_properties(table_group, key, value) do |statement|
127
- add_statement(0, statement)
128
- end
129
- end unless minimal?
130
-
131
- input.each_resource do |table|
132
- next if table.suppressOutput
133
- table_resource = table.id || RDF::Node.new
134
- add_statement(0, table_group, CSVW.table, table_resource) unless minimal?
135
- Reader.open(table.url, options.merge(
136
- format: :tabular,
137
- metadata: table,
138
- base: table.url,
139
- no_found_metadata: true,
140
- table_resource: table_resource
141
- )) do |r|
142
- r.each_statement(&block)
125
+ begin
126
+ # Validate metadata
127
+ input.validate!
128
+
129
+ # Use resolved @id of TableGroup, if available
130
+ table_group = input.id || RDF::Node.new
131
+ add_statement(0, table_group, RDF.type, CSVW.TableGroup) unless minimal?
132
+
133
+ # Common Properties
134
+ input.each do |key, value|
135
+ next unless key.to_s.include?(':') || key == :notes
136
+ input.common_properties(table_group, key, value) do |statement|
137
+ add_statement(0, statement)
138
+ end
139
+ end unless minimal?
140
+
141
+ # If we were originally given tabular data as input, simply use that, rather than opening the table URL. This allows buffered data to be used as input
142
+ if input.tables.empty? && options[:original_input]
143
+ table_resource = RDF::Node.new
144
+ add_statement(0, table_group, CSVW.table, table_resource) unless minimal?
145
+ Reader.new(options[:original_input], options.merge(
146
+ metadata: Table.new({url: options.fetch(:base, "http://example.org/default-metadata")}),
147
+ no_found_metadata: true,
148
+ table_resource: table_resource
149
+ )) do |r|
150
+ r.each_statement(&block)
151
+ end
152
+ else
153
+ input.each_table do |table|
154
+ next if table.suppressOutput
155
+ table_resource = table.id || RDF::Node.new
156
+ add_statement(0, table_group, CSVW.table, table_resource) unless minimal?
157
+ Reader.open(table.url, options.merge(
158
+ format: :tabular,
159
+ metadata: table,
160
+ base: table.url,
161
+ no_found_metadata: true,
162
+ table_resource: table_resource
163
+ )) do |r|
164
+ r.each_statement(&block)
165
+ end
166
+ end
143
167
  end
144
- end
145
168
 
146
- # Provenance
147
- if prov?
148
- activity = RDF::Node.new
149
- add_statement(0, table_group, RDF::PROV.wasGeneratedBy, activity)
150
- add_statement(0, activity, RDF.type, RDF::PROV.Activity)
151
- add_statement(0, activity, RDF::PROV.wasAssociatedWith, RDF::URI("http://rubygems.org/gems/rdf-tabular"))
152
- add_statement(0, activity, RDF::PROV.startedAtTime, RDF::Literal::DateTime.new(start_time))
153
- add_statement(0, activity, RDF::PROV.endedAtTime, RDF::Literal::DateTime.new(Time.now))
154
-
155
- unless (urls = input.resources.map(&:url)).empty?
156
- usage = RDF::Node.new
157
- add_statement(0, activity, RDF::PROV.qualifiedUsage, usage)
158
- add_statement(0, usage, RDF.type, RDF::PROV.Usage)
159
- urls.each do |url|
160
- add_statement(0, usage, RDF::PROV.entity, RDF::URI(url))
169
+ # Provenance
170
+ if prov?
171
+ activity = RDF::Node.new
172
+ add_statement(0, table_group, RDF::PROV.wasGeneratedBy, activity)
173
+ add_statement(0, activity, RDF.type, RDF::PROV.Activity)
174
+ add_statement(0, activity, RDF::PROV.wasAssociatedWith, RDF::URI("http://rubygems.org/gems/rdf-tabular"))
175
+ add_statement(0, activity, RDF::PROV.startedAtTime, RDF::Literal::DateTime.new(start_time))
176
+ add_statement(0, activity, RDF::PROV.endedAtTime, RDF::Literal::DateTime.new(Time.now))
177
+
178
+ unless (urls = input.tables.map(&:url)).empty?
179
+ usage = RDF::Node.new
180
+ add_statement(0, activity, RDF::PROV.qualifiedUsage, usage)
181
+ add_statement(0, usage, RDF.type, RDF::PROV.Usage)
182
+ urls.each do |url|
183
+ add_statement(0, usage, RDF::PROV.entity, RDF::URI(url))
184
+ end
185
+ add_statement(0, usage, RDF::PROV.hadRole, CSVW.csvEncodedTabularData)
161
186
  end
162
- add_statement(0, usage, RDF::PROV.hadRole, CSVW.csvEncodedTabularData)
163
- end
164
187
 
165
- unless Array(input.filenames).empty?
166
- usage = RDF::Node.new
167
- add_statement(0, activity, RDF::PROV.qualifiedUsage, usage)
168
- add_statement(0, usage, RDF.type, RDF::PROV.Usage)
169
- Array(input.filenames).each do |fn|
170
- add_statement(0, usage, RDF::PROV.entity, RDF::URI(fn))
188
+ unless Array(input.filenames).empty?
189
+ usage = RDF::Node.new
190
+ add_statement(0, activity, RDF::PROV.qualifiedUsage, usage)
191
+ add_statement(0, usage, RDF.type, RDF::PROV.Usage)
192
+ Array(input.filenames).each do |fn|
193
+ add_statement(0, usage, RDF::PROV.entity, RDF::URI(fn))
194
+ end
195
+ add_statement(0, usage, RDF::PROV.hadRole, CSVW.tabularMetadata)
171
196
  end
172
- add_statement(0, usage, RDF::PROV.hadRole, CSVW.tabularMetadata)
197
+ end
198
+ ensure
199
+ if validate? && !input.warnings.empty?
200
+ $stderr.puts "Warnings: #{input.warnings.join("\n")}"
173
201
  end
174
202
  end
175
203
  when :Table
@@ -216,6 +244,7 @@ module RDF::Tabular
216
244
  unless minimal?
217
245
  add_statement(row.sourceNumber, table_resource, CSVW.row, row_resource)
218
246
  add_statement(row.sourceNumber, row_resource, CSVW.rownum, row.number)
247
+ add_statement(row.sourceNumber, row_resource, RDF.type, CSVW.Row)
219
248
  add_statement(row.sourceNumber, row_resource, CSVW.url, row.id)
220
249
  end
221
250
  row.values.each_with_index do |cell, index|
@@ -281,7 +310,7 @@ module RDF::Tabular
281
310
  # @option options [::JSON::State] :state used when dumping
282
311
  # @option options [Boolean] :atd output Abstract Table representation instead
283
312
  # @return [String]
284
- def to_json(options = {})
313
+ def to_json(options = @options)
285
314
  io = case options
286
315
  when IO, StringIO then options
287
316
  when Hash then options[:io]
@@ -326,40 +355,61 @@ module RDF::Tabular
326
355
  # Get Metadata to invoke and open referenced files
327
356
  case input.type
328
357
  when :TableGroup
329
- # Validate metadata
330
- input.validate!
331
-
332
- tables = []
333
- table_group = {}
334
- table_group['@id'] = input.id.to_s if input.id
335
-
336
- # Common Properties
337
- input.each do |key, value|
338
- next unless key.to_s.include?(':') || key == :notes
339
- table_group[key] = input.common_properties(nil, key, value)
340
- table_group[key] = [table_group[key]] if key == :notes && !table_group[key].is_a?(Array)
341
- end
358
+ begin
359
+ # Validate metadata
360
+ input.validate!
342
361
 
343
- table_group['table'] = tables
362
+ tables = []
363
+ table_group = {}
364
+ table_group['@id'] = input.id.to_s if input.id
344
365
 
345
- input.each_resource do |table|
346
- next if table.suppressOutput
347
- Reader.open(table.url, options.merge(
348
- format: :tabular,
349
- metadata: table,
350
- base: table.url,
351
- minimal: minimal?,
352
- no_found_metadata: true
353
- )) do |r|
354
- case table = r.to_hash(options)
355
- when Array then tables += table
356
- when Hash then tables << table
366
+ # Common Properties
367
+ input.each do |key, value|
368
+ next unless key.to_s.include?(':') || key == :notes
369
+ table_group[key] = input.common_properties(nil, key, value)
370
+ table_group[key] = [table_group[key]] if key == :notes && !table_group[key].is_a?(Array)
371
+ end
372
+
373
+ table_group['table'] = tables
374
+
375
+ if input.tables.empty? && options[:original_input]
376
+ md = Table.new({url: options.fetch(:base, "http://example.org/default-metadata")})
377
+ Reader.new(options[:original_input], options.merge(
378
+ metadata: md,
379
+ base: options.fetch(:base, "http://example.org/default-metadata"),
380
+ minimal: minimal?,
381
+ no_found_metadata: true
382
+ )) do |r|
383
+ case table = r.to_hash(options)
384
+ when Array then tables += table
385
+ when Hash then tables << table
386
+ end
387
+ end
388
+ else
389
+ input.each_table do |table|
390
+ next if table.suppressOutput
391
+ Reader.open(table.url, options.merge(
392
+ format: :tabular,
393
+ metadata: table,
394
+ base: table.url,
395
+ minimal: minimal?,
396
+ no_found_metadata: true
397
+ )) do |r|
398
+ case table = r.to_hash(options)
399
+ when Array then tables += table
400
+ when Hash then tables << table
401
+ end
402
+ end
357
403
  end
358
404
  end
359
- end
360
405
 
361
- # Result is table_group or array
362
- minimal? ? tables : table_group
406
+ # Result is table_group or array
407
+ minimal? ? tables : table_group
408
+ ensure
409
+ if validate? && !input.warnings.empty?
410
+ $stderr.puts "Warnings: #{input.warnings.join("\n")}"
411
+ end
412
+ end
363
413
  when :Table
364
414
  table = nil
365
415
  Reader.open(input.url, options.merge(
@@ -442,12 +492,12 @@ module RDF::Tabular
442
492
  cell.value.object
443
493
  when cell.value.is_a?(RDF::Literal::Boolean)
444
494
  cell.value.object
445
- else
495
+ when cell.value
446
496
  cell.value
447
497
  end
448
498
 
449
499
  # Add or merge value
450
- merge_compacted_value(co, prop, value)
500
+ merge_compacted_value(co, prop, value) unless value.nil?
451
501
  end
452
502
 
453
503
  # Check for nesting
@@ -488,7 +538,7 @@ module RDF::Tabular
488
538
  when :TableGroup
489
539
  table_group = input.to_atd
490
540
 
491
- input.each_resource do |table|
541
+ input.each_table do |table|
492
542
  Reader.open(table.url, options.merge(
493
543
  format: :tabular,
494
544
  metadata: table,
@@ -499,7 +549,7 @@ module RDF::Tabular
499
549
  table = r.to_atd(options)
500
550
 
501
551
  # Fill in columns and rows in table_group entry from returned table
502
- t = table_group[:resources].detect {|tab| tab["url"] == table["url"]}
552
+ t = table_group[:tables].detect {|tab| tab["url"] == table["url"]}
503
553
  t["columns"] = table["columns"]
504
554
  t["rows"] = table["rows"]
505
555
  end
@@ -86,20 +86,22 @@ describe RDF::Tabular::Metadata do
86
86
  params[:valid].each do |v|
87
87
  subject.send("#{prop}=".to_sym, v)
88
88
  expect(subject.errors).to be_empty
89
+ expect(subject.warnings).to be_empty
89
90
  end
90
91
  end
91
92
  it "invalidates" do
92
93
  params[:invalid].each do |v|
93
94
  subject.send("#{prop}=".to_sym, v)
94
- subject.valid?
95
- expect(subject.errors).not_to be_empty
95
+ expect(subject.errors).to be_empty
96
+ expect(subject.warnings).not_to be_empty
96
97
  end
97
98
  end
98
99
  else
99
100
  it "does not allow" do
100
101
  params[:valid].each do |v|
101
102
  subject.send("#{prop}=".to_sym, v)
102
- expect(subject.errors).not_to be_empty
103
+ expect(subject.errors).to be_empty
104
+ expect(subject.warnings).not_to be_empty
103
105
  end
104
106
  end
105
107
  end
@@ -144,7 +146,8 @@ describe RDF::Tabular::Metadata do
144
146
  it "Does not allow unknown prefxies or unprefixed names" do
145
147
  invalid.each do |v|
146
148
  subject[v.to_sym] = "foo"
147
- expect(subject.errors).not_to be_empty
149
+ expect(subject.errors).to be_empty
150
+ expect(subject.warnings).not_to be_empty
148
151
  end
149
152
  end
150
153
 
@@ -167,7 +170,8 @@ describe RDF::Tabular::Metadata do
167
170
  it "Does not allow defined prefixed names and absolute URIs" do
168
171
  (valid + invalid).each do |v|
169
172
  subject[v.to_sym] = "foo"
170
- expect(subject.errors).not_to be_empty
173
+ expect(subject.errors).to be_empty
174
+ expect(subject.warnings).not_to be_empty
171
175
  end
172
176
  end
173
177
  end
@@ -197,21 +201,21 @@ describe RDF::Tabular::Metadata do
197
201
  its(:type) {is_expected.to eql :Column}
198
202
 
199
203
  {
200
- title: {
204
+ titles: {
201
205
  valid: ["foo", %w(foo bar), {"en" => "foo", "de" => "bar"}],
202
206
  invalid: [1, true, nil]
203
207
  },
204
208
  required: {
205
209
  valid: [true, false],
206
- invalid: [nil, "foo", 1, 0, "true", "false", "TrUe", "fAlSe", "1", "0"],
210
+ warning: [nil, "foo", 1, 0, "true", "false", "TrUe", "fAlSe", "1", "0"],
207
211
  },
208
212
  suppressOutput: {
209
213
  valid: [true, false],
210
- invalid: [nil, "foo", 1, 0, "true", "false", "TrUe", "fAlSe", "1", "0"],
214
+ warning: [nil, "foo", 1, 0, "true", "false", "TrUe", "fAlSe", "1", "0"],
211
215
  },
212
216
  virtual: {
213
217
  valid: [true, false],
214
- invalid: [nil, 1, 0, "true", "false", "TrUe", "fAlSe", "1", "0", "foo"],
218
+ warning: [nil, 1, 0, "true", "false", "TrUe", "fAlSe", "1", "0", "foo"],
215
219
  },
216
220
  }.each do |prop, params|
217
221
  context prop.to_s do
@@ -226,17 +230,24 @@ describe RDF::Tabular::Metadata do
226
230
  subject.send("#{prop}=".to_sym, v)
227
231
  expect(subject).not_to be_valid
228
232
  end
229
- end
233
+ end if params[:invalid]
234
+ it "warnings" do
235
+ params[:warning].each do |v|
236
+ subject.send("#{prop}=".to_sym, v)
237
+ expect(subject).to be_valid
238
+ expect(subject.warnings).not_to be_empty
239
+ end
240
+ end if params[:warning]
230
241
  end
231
242
  end
232
243
 
233
- context "title" do
244
+ context "titles" do
234
245
  {
235
246
  string: ["foo", {"und" => ["foo"]}],
236
247
  }.each do |name, (input, output)|
237
248
  it name do
238
- subject.title = input
239
- expect(subject.title).to produce(output)
249
+ subject.titles = input
250
+ expect(subject.titles).to produce(output)
240
251
  end
241
252
  end
242
253
  end
@@ -307,7 +318,7 @@ describe RDF::Tabular::Metadata do
307
318
  describe "foreignKeys" do
308
319
  subject {
309
320
  RDF::Tabular::TableGroup.new({
310
- resources: [{
321
+ tables: [{
311
322
  url: "a",
312
323
  tableSchema: {
313
324
  "@id" => "a_s",
@@ -350,7 +361,7 @@ describe RDF::Tabular::Metadata do
350
361
  }
351
362
  }.each do |name, fk|
352
363
  it name do
353
- subject.resources.first.tableSchema.foreignKeys << fk
364
+ subject.tables.first.tableSchema.foreignKeys << fk
354
365
  expect(subject.normalize!.errors).to be_empty
355
366
  end
356
367
  end
@@ -403,7 +414,7 @@ describe RDF::Tabular::Metadata do
403
414
  },
404
415
  }.each do |name, fk|
405
416
  it name do
406
- subject.resources.first.tableSchema.foreignKeys << fk
417
+ subject.tables.first.tableSchema.foreignKeys << fk
407
418
  expect(subject.normalize!.errors).not_to be_empty
408
419
  end
409
420
  end
@@ -442,13 +453,13 @@ describe RDF::Tabular::Metadata do
442
453
  end
443
454
  end
444
455
 
445
- context "title" do
456
+ context "titles" do
446
457
  {
447
458
  string: ["foo", {"und" => ["foo"]}],
448
459
  }.each do |name, (input, output)|
449
460
  it name do
450
- subject.title = input
451
- expect(subject.title).to produce(output)
461
+ subject.titles = input
462
+ expect(subject.titles).to produce(output)
452
463
  end
453
464
  end
454
465
  end
@@ -485,10 +496,10 @@ describe RDF::Tabular::Metadata do
485
496
  "tableSchema": {
486
497
  "@type": "Schema",
487
498
  "columns": [
488
- {"title": {"und": ["countryCode"]}},
489
- {"title": {"und": ["latitude"]}},
490
- {"title": {"und": ["longitude"]}},
491
- {"title": {"und": ["name"]}}
499
+ {"titles": {"und": ["countryCode"]}},
500
+ {"titles": {"und": ["latitude"]}},
501
+ {"titles": {"und": ["longitude"]}},
502
+ {"titles": {"und": ["name"]}}
492
503
  ]
493
504
  }
494
505
  })
@@ -503,10 +514,10 @@ describe RDF::Tabular::Metadata do
503
514
  "tableSchema": {
504
515
  "@type": "Schema",
505
516
  "columns": [
506
- {"title": {"und": ["AD"]}},
507
- {"title": {"und": ["42.546245"]}},
508
- {"title": {"und": ["1.601554"]}},
509
- {"title": {"und": ["Andorra"]}}
517
+ {"titles": {"und": ["AD"]}},
518
+ {"titles": {"und": ["42.546245"]}},
519
+ {"titles": {"und": ["1.601554"]}},
520
+ {"titles": {"und": ["Andorra"]}}
510
521
  ]
511
522
  },
512
523
  "rdfs:comment": ["countryCode,latitude,longitude,name"]
@@ -522,29 +533,11 @@ describe RDF::Tabular::Metadata do
522
533
  "tableSchema": {
523
534
  "@type": "Schema",
524
535
  "columns": [
525
- {"title": {"und": ["GID"]}},
526
- {"title": {"und": ["On Street"]}},
527
- {"title": {"und": ["Species"]}},
528
- {"title": {"und": ["Trim Cycle"]}},
529
- {"title": {"und": ["Inventory Date"]}}
530
- ]
531
- }
532
- })
533
- },
534
- "headerColumnCount" => {
535
- input: "https://example.org/tree-ops.csv",
536
- dialect: {headerColumnCount: 1},
537
- result: %({
538
- "@context": "http://www.w3.org/ns/csvw",
539
- "@type": "Table",
540
- "url": "https://example.org/tree-ops.csv",
541
- "tableSchema": {
542
- "@type": "Schema",
543
- "columns": [
544
- {"title": {"und": ["On Street"]}},
545
- {"title": {"und": ["Species"]}},
546
- {"title": {"und": ["Trim Cycle"]}},
547
- {"title": {"und": ["Inventory Date"]}}
536
+ {"titles": {"und": ["GID"]}},
537
+ {"titles": {"und": ["On Street"]}},
538
+ {"titles": {"und": ["Species"]}},
539
+ {"titles": {"und": ["Trim Cycle"]}},
540
+ {"titles": {"und": ["Inventory Date"]}}
548
541
  ]
549
542
  }
550
543
  })
@@ -595,7 +588,7 @@ describe RDF::Tabular::Metadata do
595
588
  },
596
589
  suppressOutput: {
597
590
  valid: [true, false],
598
- invalid: [nil, "foo", 1, 0, "true", "false", "TrUe", "fAlSe", "1", "0"],
591
+ warning: [nil, "foo", 1, 0, "true", "false", "TrUe", "fAlSe", "1", "0"],
599
592
  },
600
593
  }.each do |prop, params|
601
594
  context prop.to_s do
@@ -610,14 +603,21 @@ describe RDF::Tabular::Metadata do
610
603
  subject.send("#{prop}=".to_sym, v)
611
604
  expect(subject).not_to be_valid
612
605
  end
613
- end
606
+ end if params[:invalid]
607
+ it "warnings" do
608
+ params[:warning].each do |v|
609
+ subject.send("#{prop}=".to_sym, v)
610
+ expect(subject).to be_valid
611
+ expect(subject.warnings).not_to be_empty
612
+ end
613
+ end if params[:warning]
614
614
  end
615
615
  end
616
616
  end
617
617
 
618
618
  describe RDF::Tabular::TableGroup do
619
619
  let(:table) {{"url" => "http://example.org/table.csv"}}
620
- subject {described_class.new({"resources" => [table]}, base: RDF::URI("http://example.org/base"), debug: @debug)}
620
+ subject {described_class.new({"tables" => [table]}, base: RDF::URI("http://example.org/base"), debug: @debug)}
621
621
  specify {is_expected.to be_valid}
622
622
 
623
623
  it_behaves_like("inherited properties")
@@ -749,7 +749,7 @@ describe RDF::Tabular::Metadata do
749
749
  "@type Schema" => [{"@type" => "Schema"}, RDF::Tabular::Schema],
750
750
  "@type Column" => [{"@type" => "Column"}, RDF::Tabular::Column],
751
751
  "@type Dialect" => [{"@type" => "Dialect"}, RDF::Tabular::Dialect],
752
- "resources TableGroup" => [{"resources" => []}, RDF::Tabular::TableGroup],
752
+ "tables TableGroup" => [{"tables" => []}, RDF::Tabular::TableGroup],
753
753
  "dialect Table" => [{"dialect" => {}}, RDF::Tabular::Table],
754
754
  "tableSchema Table" => [{"tableSchema" => {}}, RDF::Tabular::Table],
755
755
  "transformations Table" => [{"transformations" => []}, RDF::Tabular::Table],
@@ -765,9 +765,8 @@ describe RDF::Tabular::Metadata do
765
765
  "doubleQuote Dialect" => [{"doubleQuote" => true}, RDF::Tabular::Dialect],
766
766
  "encoding Dialect" => [{"encoding" => "utf-8"}, RDF::Tabular::Dialect],
767
767
  "header Dialect" => [{"header" => true}, RDF::Tabular::Dialect],
768
- "headerColumnCount Dialect" => [{"headerColumnCount" => 0}, RDF::Tabular::Dialect],
769
768
  "headerRowCount Dialect" => [{"headerRowCount" => 1}, RDF::Tabular::Dialect],
770
- "lineTerminator Dialect" => [{"lineTerminator" => "\r\n"}, RDF::Tabular::Dialect],
769
+ "lineTerminators Dialect" => [{"lineTerminators" => "\r\n"}, RDF::Tabular::Dialect],
771
770
  "quoteChar Dialect" => [{"quoteChar" => "\""}, RDF::Tabular::Dialect],
772
771
  "skipBlankRows Dialect" => [{"skipBlankRows" => true}, RDF::Tabular::Dialect],
773
772
  "skipColumns Dialect" => [{"skipColumns" => 0}, RDF::Tabular::Dialect],
@@ -792,19 +791,19 @@ describe RDF::Tabular::Metadata do
792
791
  "@type": "Schema",
793
792
  "columns": [{
794
793
  "name": "countryCode",
795
- "title": "countryCode",
794
+ "titles": "countryCode",
796
795
  "propertyUrl": "https://example.org/countries.csv#countryCode"
797
796
  }, {
798
797
  "name": "latitude",
799
- "title": "latitude",
798
+ "titles": "latitude",
800
799
  "propertyUrl": "https://example.org/countries.csv#latitude"
801
800
  }, {
802
801
  "name": "longitude",
803
- "title": "longitude",
802
+ "titles": "longitude",
804
803
  "propertyUrl": "https://example.org/countries.csv#longitude"
805
804
  }, {
806
805
  "name": "name",
807
- "title": "name",
806
+ "titles": "name",
808
807
  "propertyUrl": "https://example.org/countries.csv#name"
809
808
  }]
810
809
  }
@@ -867,10 +866,10 @@ describe RDF::Tabular::Metadata do
867
866
  "url": "https://example.org/countries.csv",
868
867
  "tableSchema": {
869
868
  "columns": [
870
- {"title": "addressCountry"},
871
- {"title": "latitude"},
872
- {"title": "longitude"},
873
- {"title": "name"}
869
+ {"titles": "addressCountry"},
870
+ {"titles": "latitude"},
871
+ {"titles": "longitude"},
872
+ {"titles": "name"}
874
873
  ]
875
874
  }
876
875
  })), base: RDF::URI("http://example.org/base"), debug: @debug)
@@ -878,16 +877,16 @@ describe RDF::Tabular::Metadata do
878
877
  let(:input) {RDF::Util::File.open_file("https://example.org/countries.csv")}
879
878
 
880
879
  {
881
- "default title" => {
880
+ "default titles" => {
882
881
  aboutUrl: [RDF::Node, RDF::Node, RDF::Node, RDF::Node],
883
882
  propertyUrl: [nil, nil, nil, nil],
884
883
  valueUrl: [nil, nil, nil, nil],
885
884
  md: {"url" => "https://example.org/countries.csv", "tableSchema" => {
886
885
  "columns" => [
887
- {"title" => "addressCountry"},
888
- {"title" => "latitude"},
889
- {"title" => "longitude"},
890
- {"title" => "name"}
886
+ {"titles" => "addressCountry"},
887
+ {"titles" => "latitude"},
888
+ {"titles" => "longitude"},
889
+ {"titles" => "name"}
891
890
  ]
892
891
  }
893
892
  }
@@ -903,10 +902,10 @@ describe RDF::Tabular::Metadata do
903
902
  "propertyUrl" => '{?_name}',
904
903
  "valueUrl" => '{_name}',
905
904
  "columns" => [
906
- {"title" => "addressCountry"},
907
- {"title" => "latitude"},
908
- {"title" => "longitude"},
909
- {"title" => "name"}
905
+ {"titles" => "addressCountry"},
906
+ {"titles" => "latitude"},
907
+ {"titles" => "longitude"},
908
+ {"titles" => "name"}
910
909
  ]
911
910
  }
912
911
  }
@@ -922,17 +921,17 @@ describe RDF::Tabular::Metadata do
922
921
  "propertyUrl" => 'schema:{_name}',
923
922
  "valueUrl" => 'schema:{_name}',
924
923
  "columns" => [
925
- {"title" => "addressCountry"},
926
- {"title" => "latitude"},
927
- {"title" => "longitude"},
928
- {"title" => "name"}
924
+ {"titles" => "addressCountry"},
925
+ {"titles" => "latitude"},
926
+ {"titles" => "longitude"},
927
+ {"titles" => "name"}
929
928
  ]
930
929
  }
931
930
  }
932
931
  },
933
932
  }.each do |name, props|
934
933
  context name do
935
- let(:md) {RDF::Tabular::Table.new(props[:md]).merge(subject).resources.first}
934
+ let(:md) {RDF::Tabular::Table.new(props[:md]).merge(subject).tables.first}
936
935
  let(:cells) {md.to_enum(:each_row, input).to_a.first.values}
937
936
  let(:aboutUrls) {props[:aboutUrl].map {|u| u.is_a?(String) ? md.url.join(u) : u}}
938
937
  let(:propertyUrls) {props[:propertyUrl].map {|u| u.is_a?(String) ? md.url.join(u) : u}}
@@ -961,8 +960,6 @@ describe RDF::Tabular::Metadata do
961
960
  "headerRowCount" => {dialect: {headerRowCount: 0}},
962
961
  "skipRows + headerRowCount" => {dialect: {skipRows: 1, headerRowCount: 0}},
963
962
  "skipColumns" => {dialect: {skipColumns: 1}},
964
- "headerColumnCount" => {dialect: {headerColumnCount: 0}},
965
- "skipColumns + headerColumnCount" => {dialect: {skipColumns: 1, headerColumnCount: 0}},
966
963
  }.each do |name, props|
967
964
  context name do
968
965
  subject {
@@ -973,19 +970,19 @@ describe RDF::Tabular::Metadata do
973
970
  "@type": "Schema",
974
971
  "columns": [{
975
972
  "name": "countryCode",
976
- "title": "countryCode",
973
+ "titles": "countryCode",
977
974
  "propertyUrl": "https://example.org/countries.csv#countryCode"
978
975
  }, {
979
976
  "name": "latitude",
980
- "title": "latitude",
977
+ "titles": "latitude",
981
978
  "propertyUrl": "https://example.org/countries.csv#latitude"
982
979
  }, {
983
980
  "name": "longitude",
984
- "title": "longitude",
981
+ "titles": "longitude",
985
982
  "propertyUrl": "https://example.org/countries.csv#longitude"
986
983
  }, {
987
984
  "name": "name",
988
- "title": "name",
985
+ "titles": "name",
989
986
  "propertyUrl": "https://example.org/countries.csv#name"
990
987
  }]
991
988
  }
@@ -995,7 +992,7 @@ describe RDF::Tabular::Metadata do
995
992
  }
996
993
  let(:rows) {subject.to_enum(:each_row, input).to_a}
997
994
  let(:rowOffset) {props[:dialect].fetch(:skipRows, 0) + props[:dialect].fetch(:headerRowCount, 1)}
998
- let(:columnOffset) {props[:dialect].fetch(:skipColumns, 0) + props[:dialect].fetch(:headerColumnCount, 0)}
995
+ let(:columnOffset) {props[:dialect].fetch(:skipColumns, 0)}
999
996
  it "has expected number attributes" do
1000
997
  nums = [1, 2, 3, 4]
1001
998
  nums = nums.first(nums.length - rowOffset)
@@ -1372,7 +1369,7 @@ describe RDF::Tabular::Metadata do
1372
1369
  })],
1373
1370
  R: %({
1374
1371
  "@type": "TableGroup",
1375
- "resources": [{
1372
+ "tables": [{
1376
1373
  "@type": "Table",
1377
1374
  "url": "http://example.org/table"
1378
1375
  }],
@@ -1390,7 +1387,7 @@ describe RDF::Tabular::Metadata do
1390
1387
  })],
1391
1388
  R: %({
1392
1389
  "@type": "TableGroup",
1393
- "resources": [{
1390
+ "tables": [{
1394
1391
  "@type": "Table",
1395
1392
  "url": "http://example.org/table1"
1396
1393
  }, {
@@ -1407,14 +1404,14 @@ describe RDF::Tabular::Metadata do
1407
1404
  }),
1408
1405
  B: [%({
1409
1406
  "@type": "TableGroup",
1410
- "resources": [{
1407
+ "tables": [{
1411
1408
  "@type": "Table",
1412
1409
  "url": "http://example.org/table2"
1413
1410
  }]
1414
1411
  })],
1415
1412
  R: %({
1416
1413
  "@type": "TableGroup",
1417
- "resources": [{
1414
+ "tables": [{
1418
1415
  "@type": "Table",
1419
1416
  "url": "http://example.org/table1"
1420
1417
  }, {
@@ -1427,7 +1424,7 @@ describe RDF::Tabular::Metadata do
1427
1424
  "table-group and table" => {
1428
1425
  A: %({
1429
1426
  "@type": "TableGroup",
1430
- "resources": [{
1427
+ "tables": [{
1431
1428
  "@type": "Table",
1432
1429
  "url": "http://example.org/table1"
1433
1430
  }]
@@ -1438,7 +1435,7 @@ describe RDF::Tabular::Metadata do
1438
1435
  })],
1439
1436
  R: %({
1440
1437
  "@type": "TableGroup",
1441
- "resources": [{
1438
+ "tables": [{
1442
1439
  "@type": "Table",
1443
1440
  "url": "http://example.org/table1"
1444
1441
  }, {
@@ -1451,7 +1448,7 @@ describe RDF::Tabular::Metadata do
1451
1448
  "table-group and two tables" => {
1452
1449
  A: %({
1453
1450
  "@type": "TableGroup",
1454
- "resources": [{
1451
+ "tables": [{
1455
1452
  "@type": "Table",
1456
1453
  "url": "http://example.org/table1"
1457
1454
  }]
@@ -1467,7 +1464,7 @@ describe RDF::Tabular::Metadata do
1467
1464
  })],
1468
1465
  R: %({
1469
1466
  "@type": "TableGroup",
1470
- "resources": [{
1467
+ "tables": [{
1471
1468
  "@type": "Table",
1472
1469
  "url": "http://example.org/table1"
1473
1470
  }, {
@@ -1505,29 +1502,29 @@ describe RDF::Tabular::Metadata do
1505
1502
  describe "#merge!" do
1506
1503
  {
1507
1504
  "TableGroup with and without @id" => {
1508
- A: %({"@id": "http://example.org/foo", "resources": [], "@type": "TableGroup"}),
1509
- B: %({"resources": [], "@type": "TableGroup"}),
1510
- R: %({"@id": "http://example.org/foo", "resources": [], "@type": "TableGroup"})
1505
+ A: %({"@id": "http://example.org/foo", "tables": [], "@type": "TableGroup"}),
1506
+ B: %({"tables": [], "@type": "TableGroup"}),
1507
+ R: %({"@id": "http://example.org/foo", "tables": [], "@type": "TableGroup"})
1511
1508
  },
1512
1509
  "TableGroup with and without @type" => {
1513
- A: %({"resources": []}),
1514
- B: %({"resources": [], "@type": "TableGroup"}),
1515
- R: %({"resources": [], "@type": "TableGroup"})
1510
+ A: %({"tables": []}),
1511
+ B: %({"tables": [], "@type": "TableGroup"}),
1512
+ R: %({"tables": [], "@type": "TableGroup"})
1516
1513
  },
1517
- "TableGroup with matching resources" => {
1518
- A: %({"resources": [{"url": "http://example.org/foo", "dc:title": "foo"}]}),
1519
- B: %({"resources": [{"url": "http://example.org/foo", "dc:description": "bar"}]}),
1520
- R: %({"resources": [{
1514
+ "TableGroup with matching tables" => {
1515
+ A: %({"tables": [{"url": "http://example.org/foo", "dc:title": "foo"}]}),
1516
+ B: %({"tables": [{"url": "http://example.org/foo", "dc:description": "bar"}]}),
1517
+ R: %({"tables": [{
1521
1518
  "url": "http://example.org/foo",
1522
1519
  "dc:title": {"@value": "foo"},
1523
1520
  "dc:description": {"@value": "bar"}
1524
1521
  }]})
1525
1522
  },
1526
- "TableGroup with differing resources" => {
1527
- A: %({"resources": [{"url": "http://example.org/foo", "dc:title": "foo"}]}),
1528
- B: %({"resources": [{"url": "http://example.org/bar", "dc:description": "bar"}]}),
1523
+ "TableGroup with differing tables" => {
1524
+ A: %({"tables": [{"url": "http://example.org/foo", "dc:title": "foo"}]}),
1525
+ B: %({"tables": [{"url": "http://example.org/bar", "dc:description": "bar"}]}),
1529
1526
  R: %({
1530
- "resources": [
1527
+ "tables": [
1531
1528
  {"url": "http://example.org/foo", "dc:title": {"@value": "foo"}},
1532
1529
  {"url": "http://example.org/bar", "dc:description": {"@value": "bar"}}
1533
1530
  ]})
@@ -1642,14 +1639,14 @@ describe RDF::Tabular::Metadata do
1642
1639
  "@type": "Table",
1643
1640
  "url": "http://example.com/foo",
1644
1641
  "tableSchema": {
1645
- "columns": [{"title": "foo"}]
1642
+ "columns": [{"titles": "foo"}]
1646
1643
  }
1647
1644
  }),
1648
1645
  B: %({
1649
1646
  "@type": "Table",
1650
1647
  "url": "http://example.com/foo",
1651
1648
  "tableSchema": {
1652
- "columns": [{"title": "foo"}]
1649
+ "columns": [{"titles": "foo"}]
1653
1650
  }
1654
1651
  }),
1655
1652
  R: %({
@@ -1657,7 +1654,7 @@ describe RDF::Tabular::Metadata do
1657
1654
  "@type": "Table",
1658
1655
  "url": "http://example.com/foo",
1659
1656
  "tableSchema": {
1660
- "columns": [{"title": {"en": ["foo"]}}]
1657
+ "columns": [{"titles": {"en": ["foo"]}}]
1661
1658
  }
1662
1659
  }),
1663
1660
  },
@@ -1667,9 +1664,9 @@ describe RDF::Tabular::Metadata do
1667
1664
  R: %({"@type": "Schema", "columns": [{"name": "foo", "required": true}]}),
1668
1665
  },
1669
1666
  "Schema with matching column titles" => {
1670
- A: %({"@type": "Schema", "columns": [{"title": "Foo"}]}),
1671
- B: %({"@type": "Schema", "columns": [{"name": "foo", "title": "Foo"}]}),
1672
- R: %({"@type": "Schema", "columns": [{"name": "foo", "title": {"und": ["Foo"]}}]}),
1667
+ A: %({"@type": "Schema", "columns": [{"titles": "Foo"}]}),
1668
+ B: %({"@type": "Schema", "columns": [{"name": "foo", "titles": "Foo"}]}),
1669
+ R: %({"@type": "Schema", "columns": [{"name": "foo", "titles": {"und": ["Foo"]}}]}),
1673
1670
  },
1674
1671
  "Schema with primaryKey always takes A" => {
1675
1672
  A: %({"@type": "Schema", "primaryKey": "foo"}),