json-ld 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. data/History.markdown +3 -0
  2. data/VERSION +1 -1
  3. data/bin/jsonld +134 -0
  4. data/lib/json/ld/api.rb +4 -4
  5. data/lib/json/ld/frame.rb +2 -1
  6. data/lib/json/ld/from_rdf.rb +1 -1
  7. data/spec/api_spec.rb +66 -0
  8. data/spec/compact_spec.rb +420 -0
  9. data/spec/evaluation_context_spec.rb +1039 -0
  10. data/spec/expand_spec.rb +625 -0
  11. data/spec/format_spec.rb +71 -0
  12. data/spec/frame_spec.rb +542 -0
  13. data/spec/from_rdf_spec.rb +316 -0
  14. data/spec/matchers.rb +67 -0
  15. data/spec/reader_spec.rb +79 -0
  16. data/spec/spec_helper.rb +56 -0
  17. data/spec/suite_helper.rb +184 -0
  18. data/spec/suite_spec.rb +104 -0
  19. data/spec/support/extensions.rb +10 -0
  20. data/spec/test-files/test-1-automatic.json +10 -0
  21. data/spec/test-files/test-1-compacted.json +10 -0
  22. data/spec/test-files/test-1-context.json +7 -0
  23. data/spec/test-files/test-1-expanded.json +5 -0
  24. data/spec/test-files/test-1-input.json +10 -0
  25. data/spec/test-files/test-1-normalized.json +8 -0
  26. data/spec/test-files/test-1-rdf.ttl +7 -0
  27. data/spec/test-files/test-2-automatic.json +27 -0
  28. data/spec/test-files/test-2-compacted.json +20 -0
  29. data/spec/test-files/test-2-context.json +7 -0
  30. data/spec/test-files/test-2-expanded.json +16 -0
  31. data/spec/test-files/test-2-input.json +20 -0
  32. data/spec/test-files/test-2-normalized.json +32 -0
  33. data/spec/test-files/test-2-rdf.ttl +14 -0
  34. data/spec/test-files/test-3-compacted.json +11 -0
  35. data/spec/test-files/test-3-context.json +8 -0
  36. data/spec/test-files/test-3-expanded.json +10 -0
  37. data/spec/test-files/test-3-input.json +11 -0
  38. data/spec/test-files/test-3-normalized.json +13 -0
  39. data/spec/test-files/test-3-rdf.ttl +7 -0
  40. data/spec/test-files/test-4-automatic.json +10 -0
  41. data/spec/test-files/test-4-compacted.json +10 -0
  42. data/spec/test-files/test-4-context.json +7 -0
  43. data/spec/test-files/test-4-expanded.json +6 -0
  44. data/spec/test-files/test-4-input.json +10 -0
  45. data/spec/test-files/test-4-rdf.ttl +5 -0
  46. data/spec/test-files/test-5-automatic.json +13 -0
  47. data/spec/test-files/test-5-compacted.json +13 -0
  48. data/spec/test-files/test-5-context.json +7 -0
  49. data/spec/test-files/test-5-expanded.json +9 -0
  50. data/spec/test-files/test-5-input.json +13 -0
  51. data/spec/test-files/test-5-rdf.ttl +6 -0
  52. data/spec/test-files/test-6-automatic.json +10 -0
  53. data/spec/test-files/test-6-compacted.json +10 -0
  54. data/spec/test-files/test-6-context.json +7 -0
  55. data/spec/test-files/test-6-expanded.json +10 -0
  56. data/spec/test-files/test-6-input.json +10 -0
  57. data/spec/test-files/test-6-rdf.ttl +5 -0
  58. data/spec/test-files/test-7-automatic.json +20 -0
  59. data/spec/test-files/test-7-compacted.json +23 -0
  60. data/spec/test-files/test-7-context.json +4 -0
  61. data/spec/test-files/test-7-expanded.json +20 -0
  62. data/spec/test-files/test-7-input.json +23 -0
  63. data/spec/test-files/test-7-rdf.ttl +13 -0
  64. data/spec/test-files/test-8-automatic.json +1 -0
  65. data/spec/test-files/test-8-compacted.json +34 -0
  66. data/spec/test-files/test-8-context.json +11 -0
  67. data/spec/test-files/test-8-expanded.json +24 -0
  68. data/spec/test-files/test-8-frame.json +18 -0
  69. data/spec/test-files/test-8-framed.json +29 -0
  70. data/spec/test-files/test-8-input.json +30 -0
  71. data/spec/test-files/test-8-rdf.ttl +15 -0
  72. data/spec/test-files/test-9-compacted.json +20 -0
  73. data/spec/test-files/test-9-context.json +13 -0
  74. data/spec/test-files/test-9-expanded.json +14 -0
  75. data/spec/test-files/test-9-input.json +12 -0
  76. data/spec/to_rdf_spec.rb +640 -0
  77. data/spec/writer_spec.rb +161 -0
  78. metadata +150 -22
@@ -0,0 +1,1039 @@
1
+ # coding: utf-8
2
+ $:.unshift "."
3
+ require 'spec_helper'
4
+ require 'rdf/spec/reader'
5
+
6
+ describe JSON::LD::EvaluationContext do
7
+ before(:each) {
8
+ @debug = []
9
+ @ctx_json = %q({
10
+ "@context": {
11
+ "name": "http://xmlns.com/foaf/0.1/name",
12
+ "homepage": {"@id": "http://xmlns.com/foaf/0.1/homepage", "@type": "@id"},
13
+ "avatar": {"@id": "http://xmlns.com/foaf/0.1/avatar", "@type": "@id"}
14
+ }
15
+ })
16
+ }
17
+ subject { JSON::LD::EvaluationContext.new(:debug => @debug, :validate => true)}
18
+
19
+ describe "#parse" do
20
+ context "remote" do
21
+ before(:each) do
22
+ @ctx = StringIO.new(@ctx_json)
23
+ def @ctx.content_type; "application/ld+json"; end
24
+ end
25
+
26
+ it "retrieves and parses a remote context document" do
27
+ RDF::Util::File.stub(:open_file).with("http://example.com/context").and_yield(@ctx)
28
+ ec = subject.parse("http://example.com/context")
29
+ ec.provided_context.should produce("http://example.com/context", @debug)
30
+ end
31
+
32
+ it "fails given a missing remote @context" do
33
+ RDF::Util::File.stub(:open_file).with("http://example.com/context").and_raise(IOError)
34
+ lambda {subject.parse("http://example.com/context")}.should raise_error(JSON::LD::InvalidContext, /Failed to parse remote context/)
35
+ end
36
+
37
+ it "creates mappings" do
38
+ RDF::Util::File.stub(:open_file).with("http://example.com/context").and_yield(@ctx)
39
+ ec = subject.parse("http://example.com/context")
40
+ ec.mappings.should produce({
41
+ "name" => "http://xmlns.com/foaf/0.1/name",
42
+ "homepage" => "http://xmlns.com/foaf/0.1/homepage",
43
+ "avatar" => "http://xmlns.com/foaf/0.1/avatar"
44
+ }, @debug)
45
+ end
46
+
47
+ it "allows a non-existing @context" do
48
+ ec = subject.parse(StringIO.new("{}"))
49
+ ec.mappings.should produce({}, @debug)
50
+ end
51
+ end
52
+
53
+ context "EvaluationContext" do
54
+ it "uses a duplicate of that provided" do
55
+ ec = subject.parse(StringIO.new(@ctx_json))
56
+ ec.mappings.should produce({
57
+ "name" => "http://xmlns.com/foaf/0.1/name",
58
+ "homepage" => "http://xmlns.com/foaf/0.1/homepage",
59
+ "avatar" => "http://xmlns.com/foaf/0.1/avatar"
60
+ }, @debug)
61
+ end
62
+ end
63
+
64
+ context "Array" do
65
+ before(:all) do
66
+ @ctx = [
67
+ {"foo" => "http://example.com/foo"},
68
+ {"bar" => "foo"}
69
+ ]
70
+ end
71
+
72
+ it "merges definitions from each context" do
73
+ ec = subject.parse(@ctx)
74
+ ec.mappings.should produce({
75
+ "foo" => "http://example.com/foo",
76
+ "bar" => "http://example.com/foo"
77
+ }, @debug)
78
+ end
79
+ end
80
+
81
+ context "Hash" do
82
+ it "extracts @language" do
83
+ subject.parse({
84
+ "@language" => "en"
85
+ }).default_language.should produce("en", @debug)
86
+ end
87
+
88
+ it "maps term with IRI value" do
89
+ subject.parse({
90
+ "foo" => "http://example.com/"
91
+ }).mappings.should produce({
92
+ "foo" => "http://example.com/"
93
+ }, @debug)
94
+ end
95
+
96
+ it "maps term with @id" do
97
+ subject.parse({
98
+ "foo" => {"@id" => "http://example.com/"}
99
+ }).mappings.should produce({
100
+ "foo" => "http://example.com/"
101
+ }, @debug)
102
+ end
103
+
104
+ it "associates @list coercion with predicate" do
105
+ subject.parse({
106
+ "foo" => {"@id" => "http://example.com/", "@container" => "@list"}
107
+ }).containers.should produce({
108
+ "foo" => '@list'
109
+ }, @debug)
110
+ end
111
+
112
+ it "associates @set coercion with predicate" do
113
+ subject.parse({
114
+ "foo" => {"@id" => "http://example.com/", "@container" => "@set"}
115
+ }).containers.should produce({
116
+ "foo" => '@set'
117
+ }, @debug)
118
+ end
119
+
120
+ it "associates @id coercion with predicate" do
121
+ subject.parse({
122
+ "foo" => {"@id" => "http://example.com/", "@type" => "@id"}
123
+ }).coercions.should produce({
124
+ "foo" => "@id"
125
+ }, @debug)
126
+ end
127
+
128
+ it "associates datatype coercion with predicate" do
129
+ subject.parse({
130
+ "foo" => {"@id" => "http://example.com/", "@type" => RDF::XSD.string.to_s}
131
+ }).coercions.should produce({
132
+ "foo" => RDF::XSD.string.to_s
133
+ }, @debug)
134
+ end
135
+
136
+ it "associates language coercion with predicate" do
137
+ subject.parse({
138
+ "foo" => {"@id" => "http://example.com/", "@language" => "en"}
139
+ }).languages.should produce({
140
+ "foo" => "en"
141
+ }, @debug)
142
+ end
143
+
144
+ it "expands chains of term definition/use with string values" do
145
+ subject.parse({
146
+ "foo" => "bar",
147
+ "bar" => "baz",
148
+ "baz" => "http://example.com/"
149
+ }).mappings.should produce({
150
+ "foo" => "http://example.com/",
151
+ "bar" => "http://example.com/",
152
+ "baz" => "http://example.com/"
153
+ }, @debug)
154
+ end
155
+
156
+ context "with null" do
157
+ it "removes @language if set to null" do
158
+ subject.parse([
159
+ {
160
+ "@language" => "en"
161
+ },
162
+ {
163
+ "@language" => nil
164
+ }
165
+ ]).default_language.should produce(nil, @debug)
166
+ end
167
+
168
+ it "loads initial context" do
169
+ init_ec = JSON::LD::EvaluationContext.new
170
+ nil_ec = subject.parse(nil)
171
+ nil_ec.default_language.should == init_ec.default_language
172
+ nil_ec.languages.should == init_ec.languages
173
+ nil_ec.mappings.should == init_ec.mappings
174
+ nil_ec.coercions.should == init_ec.coercions
175
+ nil_ec.containers.should == init_ec.containers
176
+ end
177
+
178
+ it "removes a term definition" do
179
+ subject.parse({"name" => nil}).mapping("name").should be_nil
180
+ end
181
+ end
182
+ end
183
+
184
+ describe "Syntax Errors" do
185
+ {
186
+ "malformed JSON" => StringIO.new(%q({"@context": {"foo" "http://malformed/"})),
187
+ "no @id, @type, or @container" => {"foo" => {}},
188
+ "value as array" => {"foo" => []},
189
+ "@id as object" => {"foo" => {"@id" => {}}},
190
+ "@id as array" => {"foo" => {"@id" => []}},
191
+ "@type as object" => {"foo" => {"@type" => {}}},
192
+ "@type as array" => {"foo" => {"@type" => []}},
193
+ "@type as @list" => {"foo" => {"@type" => "@list"}},
194
+ "@type as @list" => {"foo" => {"@type" => "@set"}},
195
+ "@container as object" => {"foo" => {"@container" => {}}},
196
+ "@container as array" => {"foo" => {"@container" => []}},
197
+ "@container as string" => {"foo" => {"@container" => "true"}},
198
+ "@language as @id" => {"@language" => {"@id" => "http://example.com/"}},
199
+ }.each do |title, context|
200
+ it title do
201
+ lambda {
202
+ ec = subject.parse(context)
203
+ ec.serialize.should produce({}, @debug)
204
+ }.should raise_error(JSON::LD::InvalidContext::Syntax)
205
+ end
206
+ end
207
+
208
+ (JSON::LD::KEYWORDS - %w(@language)).each do |kw|
209
+ it "does not redefined #{kw} as a string" do
210
+ lambda {
211
+ ec = subject.parse({kw => "http://example.com/"})
212
+ ec.serialize.should produce({}, @debug)
213
+ }.should raise_error(JSON::LD::InvalidContext::Syntax)
214
+ end
215
+
216
+ it "does not redefined #{kw} with an @id" do
217
+ lambda {
218
+ ec = subject.parse({kw => {"@id" => "http://example.com/"}})
219
+ ec.serialize.should produce({}, @debug)
220
+ }.should raise_error(JSON::LD::InvalidContext::Syntax)
221
+ end
222
+ end
223
+ end
224
+
225
+ describe "Load Errors" do
226
+ {
227
+ "fixme" => "FIXME",
228
+ }.each do |title, context|
229
+ it title do
230
+ lambda { subject.parse(context) }.should raise_error(JSON::LD::InvalidContext::LoadError)
231
+ end
232
+ end
233
+ end
234
+ end
235
+
236
+ describe "#serialize" do
237
+ it "uses provided context document" do
238
+ ctx = StringIO.new(@ctx_json)
239
+ def ctx.content_type; "application/ld+json"; end
240
+
241
+ RDF::Util::File.stub(:open_file).with("http://example.com/context").and_yield(ctx)
242
+ ec = subject.parse("http://example.com/context")
243
+ ec.serialize.should produce({
244
+ "@context" => "http://example.com/context"
245
+ }, @debug)
246
+ end
247
+
248
+ it "uses provided context array" do
249
+ ctx = [
250
+ {"foo" => "http://example.com/"},
251
+ {"baz" => "bob"}
252
+ ]
253
+
254
+ ec = subject.parse(ctx)
255
+ ec.serialize.should produce({
256
+ "@context" => ctx
257
+ }, @debug)
258
+ end
259
+
260
+ it "uses provided context hash" do
261
+ ctx = {"foo" => "http://example.com/"}
262
+
263
+ ec = subject.parse(ctx)
264
+ ec.serialize.should produce({
265
+ "@context" => ctx
266
+ }, @debug)
267
+ end
268
+
269
+ it "@language" do
270
+ subject.default_language = "en"
271
+ subject.serialize.should produce({
272
+ "@context" => {
273
+ "@language" => "en"
274
+ }
275
+ }, @debug)
276
+ end
277
+
278
+ it "term mappings" do
279
+ subject.set_mapping("foo", "http://example.com/")
280
+ subject.serialize.should produce({
281
+ "@context" => {
282
+ "foo" => "http://example.com/"
283
+ }
284
+ }, @debug)
285
+ end
286
+
287
+ it "@type with dependent prefixes in a single context" do
288
+ subject.set_mapping("xsd", RDF::XSD.to_uri.to_s)
289
+ subject.set_mapping("homepage", RDF::FOAF.homepage.to_s)
290
+ subject.set_coerce("homepage", "@id")
291
+ subject.serialize.should produce({
292
+ "@context" => {
293
+ "xsd" => RDF::XSD.to_uri,
294
+ "homepage" => {"@id" => RDF::FOAF.homepage.to_s, "@type" => "@id"}
295
+ }
296
+ }, @debug)
297
+ end
298
+
299
+ it "@list with @id definition in a single context" do
300
+ subject.set_mapping("knows", RDF::FOAF.knows.to_s)
301
+ subject.set_container("knows", '@list')
302
+ subject.serialize.should produce({
303
+ "@context" => {
304
+ "knows" => {"@id" => RDF::FOAF.knows.to_s, "@container" => "@list"}
305
+ }
306
+ }, @debug)
307
+ end
308
+
309
+ it "@set with @id definition in a single context" do
310
+ subject.set_mapping("knows", RDF::FOAF.knows.to_s)
311
+ subject.set_container("knows", '@set')
312
+ subject.serialize.should produce({
313
+ "@context" => {
314
+ "knows" => {"@id" => RDF::FOAF.knows.to_s, "@container" => "@set"}
315
+ }
316
+ }, @debug)
317
+ end
318
+
319
+ it "@language with @id definition in a single context" do
320
+ subject.set_mapping("name", RDF::FOAF.name.to_s)
321
+ subject.set_language("name", 'en')
322
+ subject.serialize.should produce({
323
+ "@context" => {
324
+ "name" => {"@id" => RDF::FOAF.name.to_s, "@language" => "en"}
325
+ }
326
+ }, @debug)
327
+ end
328
+
329
+ it "@language with @id definition in a single context and equivalent default" do
330
+ subject.set_mapping("name", RDF::FOAF.name.to_s)
331
+ subject.default_language = 'en'
332
+ subject.set_language("name", 'en')
333
+ subject.serialize.should produce({
334
+ "@context" => {
335
+ "@language" => 'en',
336
+ "name" => {"@id" => RDF::FOAF.name.to_s}
337
+ }
338
+ }, @debug)
339
+ end
340
+
341
+ it "@language with @id definition in a single context and different default" do
342
+ subject.set_mapping("name", RDF::FOAF.name.to_s)
343
+ subject.default_language = 'en'
344
+ subject.set_language("name", 'de')
345
+ subject.serialize.should produce({
346
+ "@context" => {
347
+ "@language" => 'en',
348
+ "name" => {"@id" => RDF::FOAF.name.to_s, "@language" => "de"}
349
+ }
350
+ }, @debug)
351
+ end
352
+
353
+ it "null @language with @id definition in a single context and default" do
354
+ subject.set_mapping("name", RDF::FOAF.name.to_s)
355
+ subject.default_language = 'en'
356
+ subject.set_language("name", nil)
357
+ subject.serialize.should produce({
358
+ "@context" => {
359
+ "@language" => 'en',
360
+ "name" => {"@id" => RDF::FOAF.name.to_s, "@language" => nil}
361
+ }
362
+ }, @debug)
363
+ end
364
+
365
+ it "prefix with @type and @list" do
366
+ subject.set_mapping("knows", RDF::FOAF.knows.to_s)
367
+ subject.set_coerce("knows", "@id")
368
+ subject.set_container("knows", '@list')
369
+ subject.serialize.should produce({
370
+ "@context" => {
371
+ "knows" => {"@id" => RDF::FOAF.knows.to_s, "@type" => "@id", "@container" => "@list"}
372
+ }
373
+ }, @debug)
374
+ end
375
+
376
+ it "prefix with @type and @set" do
377
+ subject.set_mapping("knows", RDF::FOAF.knows.to_s)
378
+ subject.set_coerce("knows", "@id")
379
+ subject.set_container("knows", '@set')
380
+ subject.serialize.should produce({
381
+ "@context" => {
382
+ "knows" => {"@id" => RDF::FOAF.knows.to_s, "@type" => "@id", "@container" => "@set"}
383
+ }
384
+ }, @debug)
385
+ end
386
+
387
+ it "CURIE with @type" do
388
+ subject.set_mapping("foaf", RDF::FOAF.to_uri.to_s)
389
+ subject.set_container("foaf:knows", '@list')
390
+ subject.serialize.should produce({
391
+ "@context" => {
392
+ "foaf" => RDF::FOAF.to_uri,
393
+ "foaf:knows" => {"@container" => "@list"}
394
+ }
395
+ }, @debug)
396
+ end
397
+
398
+ it "does not use aliased @id in key position" do
399
+ subject.set_mapping("id", '@id')
400
+ subject.set_mapping("knows", RDF::FOAF.knows.to_s)
401
+ subject.set_container("knows", '@list')
402
+ subject.serialize.should produce({
403
+ "@context" => {
404
+ "id" => "@id",
405
+ "knows" => {"@id" => RDF::FOAF.knows.to_s, "@container" => "@list"}
406
+ }
407
+ }, @debug)
408
+ end
409
+
410
+ it "does not use aliased @id in value position" do
411
+ subject.set_mapping("id", "@id")
412
+ subject.set_mapping("foaf", RDF::FOAF.to_uri.to_s)
413
+ subject.set_coerce("foaf:homepage", "@id")
414
+ subject.serialize.should produce({
415
+ "@context" => {
416
+ "foaf" => RDF::FOAF.to_uri.to_s,
417
+ "id" => "@id",
418
+ "foaf:homepage" => {"@type" => "@id"}
419
+ }
420
+ }, @debug)
421
+ end
422
+
423
+ it "does not use aliased @type" do
424
+ subject.set_mapping("type", "@type")
425
+ subject.set_mapping("foaf", RDF::FOAF.to_uri.to_s)
426
+ subject.set_coerce("foaf:homepage", "@id")
427
+ subject.serialize.should produce({
428
+ "@context" => {
429
+ "foaf" => RDF::FOAF.to_uri.to_s,
430
+ "type" => "@type",
431
+ "foaf:homepage" => {"@type" => "@id"}
432
+ }
433
+ }, @debug)
434
+ end
435
+
436
+ it "does not use aliased @container" do
437
+ subject.set_mapping("container", '@container')
438
+ subject.set_mapping("knows", RDF::FOAF.knows.to_s)
439
+ subject.set_container("knows", '@list')
440
+ subject.serialize.should produce({
441
+ "@context" => {
442
+ "container" => "@container",
443
+ "knows" => {"@id" => RDF::FOAF.knows.to_s, "@container" => "@list"}
444
+ }
445
+ }, @debug)
446
+ end
447
+
448
+ it "compacts IRIs to CURIEs" do
449
+ subject.set_mapping("ex", 'http://example.org/')
450
+ subject.set_mapping("term", 'http://example.org/term')
451
+ subject.set_coerce("term", "http://example.org/datatype")
452
+ subject.serialize.should produce({
453
+ "@context" => {
454
+ "ex" => 'http://example.org/',
455
+ "term" => {"@id" => "ex:term", "@type" => "ex:datatype"}
456
+ }
457
+ }, @debug)
458
+ end
459
+
460
+ context "extra keys or values" do
461
+ {
462
+ "extra key" => {
463
+ :input => {"foo" => {"@id" => "http://example.com/foo", "@baz" => "foobar"}},
464
+ :result => {"@context" => {"foo" => {"@id" => "http://example.com/foo", "@baz" => "foobar"}}}
465
+ }
466
+ }.each do |title, params|
467
+ it title do
468
+ ec = subject.parse(params[:input])
469
+ ec.serialize.should produce(params[:result], @debug)
470
+ end
471
+ end
472
+ end
473
+
474
+ end
475
+
476
+ describe "#expand_iri" do
477
+ before(:each) do
478
+ subject.set_mapping("ex", "http://example.org/")
479
+ subject.set_mapping("", "http://empty/")
480
+ subject.set_mapping("_", "http://underscore/")
481
+ end
482
+
483
+ it "bnode" do
484
+ subject.expand_iri("_:a").should be_a(RDF::Node)
485
+ end
486
+
487
+ context "relative IRI" do
488
+ {
489
+ :subject => true,
490
+ :predicate => false,
491
+ :object => true,
492
+ :datatype => false
493
+ }.each do |position, r|
494
+ context "as #{position}" do
495
+ {
496
+ "absolute IRI" => ["http://example.org/", "http://example.org/", true],
497
+ "term" => ["ex", "http://example.org/", true],
498
+ "prefix:suffix" => ["ex:suffix", "http://example.org/suffix", true],
499
+ "keyword" => ["@type", "@type", true],
500
+ "empty" => [":suffix", "http://empty/suffix", true],
501
+ "unmapped" => ["foo", "foo", false],
502
+ "empty term" => ["", "http://empty/", true],
503
+ "another abs IRI"=>["ex://foo", "ex://foo", true],
504
+ "absolute IRI looking like a curie" =>
505
+ ["foo:bar", "foo:bar", true],
506
+ "bnode" => ["_:foo", RDF::Node("foo"), true],
507
+ "_" => ["_", "http://underscore/", true],
508
+ }.each do |title, (input,result,abs)|
509
+ result = nil unless r || abs
510
+ result = nil if title == 'unmapped'
511
+ it title do
512
+ subject.expand_iri(input).should produce(result, @debug)
513
+ end
514
+ end
515
+ end
516
+ end
517
+
518
+ context "with base IRI" do
519
+ {
520
+ :subject => true,
521
+ :predicate => false,
522
+ :object => true,
523
+ :datatype => false
524
+ }.each do |position, r|
525
+ context "as #{position}" do
526
+ before(:each) do
527
+ subject.instance_variable_set(:@base, RDF::URI("http://example.org/"))
528
+ subject.mappings.delete("")
529
+ end
530
+
531
+ {
532
+ "base" => ["", RDF::URI("http://example.org/")],
533
+ "relative" => ["a/b", RDF::URI("http://example.org/a/b")],
534
+ "hash" => ["#a", RDF::URI("http://example.org/#a")],
535
+ "absolute" => ["http://foo/", RDF::URI("http://foo/")]
536
+ }.each do |title, (input,result)|
537
+ result = nil unless r || title == 'absolute'
538
+ it title do
539
+ subject.expand_iri(input, :position => position).should produce(result, @debug)
540
+ end
541
+ end
542
+ end
543
+ end
544
+ end
545
+ end
546
+ end
547
+
548
+ describe "#compact_iri" do
549
+ before(:each) do
550
+ subject.set_mapping("ex", "http://example.org/")
551
+ subject.set_mapping("", "http://empty/")
552
+ subject.set_mapping("http://example.com/null", nil)
553
+ end
554
+
555
+ {
556
+ "absolute IRI" => ["http://example.com/", "http://example.com/"],
557
+ "term" => ["ex", "http://example.org/"],
558
+ "prefix:suffix" => ["ex:suffix", "http://example.org/suffix"],
559
+ "keyword" => ["@type", "@type"],
560
+ "empty" => [":suffix", "http://empty/suffix"],
561
+ "unmapped" => ["foo", "foo"],
562
+ "bnode" => ["_:a", RDF::Node("a")],
563
+ "null IRI" => [nil, "http://example.com/null"],
564
+ }.each do |title, (result, input)|
565
+ it title do
566
+ subject.compact_iri(input).should produce(result, @debug)
567
+ end
568
+ end
569
+
570
+ context "with value" do
571
+ let(:ctx) do
572
+ c = subject.parse({
573
+ "xsd" => RDF::XSD.to_s,
574
+ "plain" => "http://example.com/plain",
575
+ "lang" => {"@id" => "http://example.com/lang", "@language" => "en"},
576
+ "bool" => {"@id" => "http://example.com/bool", "@type" => "xsd:boolean"},
577
+ "integer" => {"@id" => "http://example.com/integer", "@type" => "xsd:integer"},
578
+ "double" => {"@id" => "http://example.com/double", "@type" => "xsd:double"},
579
+ "date" => {"@id" => "http://example.com/date", "@type" => "xsd:date"},
580
+ "id" => {"@id" => "http://example.com/id", "@type" => "@id"},
581
+ "listplain" => {"@id" => "http://example.com/plain", "@container" => "@list"},
582
+ "listlang" => {"@id" => "http://example.com/lang", "@language" => "en", "@container" => "@list"},
583
+ "listbool" => {"@id" => "http://example.com/bool", "@type" => "xsd:boolean", "@container" => "@list"},
584
+ "listinteger" => {"@id" => "http://example.com/integer", "@type" => "xsd:integer", "@container" => "@list"},
585
+ "listdouble" => {"@id" => "http://example.com/double", "@type" => "xsd:double", "@container" => "@list"},
586
+ "listdate" => {"@id" => "http://example.com/date", "@type" => "xsd:date", "@container" => "@list"},
587
+ "listid" => {"@id" => "http://example.com/id", "@type" => "@id", "@container" => "@list"},
588
+ "setplain" => {"@id" => "http://example.com/plain", "@container" => "@set"},
589
+ "setlang" => {"@id" => "http://example.com/lang", "@language" => "en", "@container" => "@set"},
590
+ "setbool" => {"@id" => "http://example.com/bool", "@type" => "xsd:boolean", "@container" => "@set"},
591
+ "setinteger" => {"@id" => "http://example.com/integer", "@type" => "xsd:integer", "@container" => "@set"},
592
+ "setdouble" => {"@id" => "http://example.com/double", "@type" => "xsd:double", "@container" => "@set"},
593
+ "setdate" => {"@id" => "http://example.com/date", "@type" => "xsd:date", "@container" => "@set"},
594
+ "setid" => {"@id" => "http://example.com/id", "@type" => "@id", "@container" => "@set"},
595
+ })
596
+ @debug.clear
597
+ c
598
+ end
599
+
600
+ {
601
+ "setplain" => [
602
+ {"@value" => "foo"},
603
+ {"@value" => "de", "@language" => "de"},
604
+ {"@value" => "other dt", "@language" => "http://example.com/other-datatype"}
605
+ ],
606
+ "setlang" => [{"@value" => "en", "@language" => "en"}],
607
+ "setbool" => [{"@value" => true}, {"@value" => false}, {"@value" => "true", "@type" => RDF::XSD.boolean.to_s}],
608
+ "setinteger" => [{"@value" => 1}, {"@value" => "1", "@type" => RDF::XSD.integer.to_s}],
609
+ "setdouble" => [{"@value" => 1.1}, {"@value" => "1", "@type" => RDF::XSD.double.to_s}],
610
+ "setdate" => [{"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}],
611
+ }.each do |prop, values|
612
+ context "uses #{prop}", :pending => "does algorithm favor @set?" do
613
+ values.each do |value|
614
+ it "for #{value.inspect}" do
615
+ ctx.compact_iri("http://example.com/#{prop.sub('set', '')}", :value => value).should produce(prop, @debug)
616
+ end
617
+ end
618
+ end
619
+ end
620
+
621
+ context "for @list" do
622
+ {
623
+ "listplain" => [
624
+ [{"@value" => "foo"}],
625
+ [{"@value" => "foo"}, {"@value" => "bar"}, {"@value" => 1}],
626
+ [{"@value" => "foo"}, {"@value" => "bar"}, {"@value" => 1.1}],
627
+ [{"@value" => "foo"}, {"@value" => "bar"}, {"@value" => true}],
628
+ [{"@value" => "foo"}, {"@value" => "bar"}, {"@value" => 1}],
629
+ [{"@value" => "de", "@language" => "de"}, {"@value" => "jp", "@language" => "jp"}],
630
+ ],
631
+ "listlang" => [[{"@value" => "en", "@language" => "en"}]],
632
+ "listbool" => [[{"@value" => true}], [{"@value" => false}], [{"@value" => "true", "@type" => RDF::XSD.boolean.to_s}]],
633
+ "listinteger" => [[{"@value" => 1}], [{"@value" => "1", "@type" => RDF::XSD.integer.to_s}]],
634
+ "listdouble" => [[{"@value" => 1.1}], [{"@value" => "1", "@type" => RDF::XSD.double.to_s}]],
635
+ "listdate" => [[{"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}]],
636
+ }.each do |prop, values|
637
+ context "uses #{prop}" do
638
+ values.each do |value|
639
+ it "for #{{"@list" => value}.inspect}" do
640
+ ctx.compact_iri("http://example.com/#{prop.sub('list', '')}", :value => {"@list" => value}).should produce(prop, @debug)
641
+ end
642
+ end
643
+ end
644
+ end
645
+ end
646
+ end
647
+ end
648
+
649
+ describe "#term_rank" do
650
+ {
651
+ "no coercions" => {
652
+ :defn => {},
653
+ "boolean value" => {:value => {"@value" => true}, :rank => 2},
654
+ "integer value" => {:value => {"@value" => 1}, :rank => 2},
655
+ "double value" => {:value => {"@value" => 1.1}, :rank => 2},
656
+ "string value" => {:value => {"@value" => "foo"}, :rank => 3},
657
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 1},
658
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 1},
659
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 1},
660
+ "null" => {:value => nil, :rank => 3},
661
+ },
662
+ "boolean" => {
663
+ :defn => {"@type" => RDF::XSD.boolean.to_s},
664
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
665
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
666
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
667
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
668
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
669
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
670
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
671
+ "value boolean" => {:value => {"@value" => "true", "@type" => RDF::XSD.boolean.to_s}, :rank => 3},
672
+ "null" => {:value => nil, :rank => 3},
673
+ },
674
+ "integer" => {
675
+ :defn => {"@type" => RDF::XSD.integer.to_s},
676
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
677
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
678
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
679
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
680
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
681
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
682
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
683
+ "value integer" => {:value => {"@value" => "1", "@type" => RDF::XSD.integer.to_s}, :rank => 3},
684
+ "null" => {:value => nil, :rank => 3},
685
+ },
686
+ "double" => {
687
+ :defn => {"@type" => RDF::XSD.double.to_s},
688
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
689
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
690
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
691
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
692
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
693
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
694
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
695
+ "value double" => {:value => {"@value" => "1.1", "@type" => RDF::XSD.double.to_s}, :rank => 3},
696
+ "null" => {:value => nil, :rank => 3},
697
+ },
698
+ "date" => {
699
+ :defn => {"@type" => RDF::XSD.date.to_s},
700
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
701
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
702
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
703
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
704
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 3},
705
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
706
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
707
+ "null" => {:value => nil, :rank => 3},
708
+ },
709
+ "lang" => {
710
+ :defn => {"@language" => "en"},
711
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
712
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
713
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
714
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
715
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
716
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 3},
717
+ "other lang" => {:value => {"@value" => "apple", "@language" => "de"}, :rank => 0},
718
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
719
+ "null" => {:value => nil, :rank => 3},
720
+ },
721
+ "id" => {
722
+ :defn => {"@type" => "@id"},
723
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
724
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
725
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
726
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
727
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
728
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
729
+ "other lang" => {:value => {"@value" => "apple", "@language" => "de"}, :rank => 0},
730
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 3},
731
+ "null" => {:value => nil, :rank => 3},
732
+ },
733
+ }.each do |title, properties|
734
+ context title do
735
+ let(:ctx) do
736
+ subject.parse({
737
+ "term" => properties[:defn].merge("@id" => "http://example.org/term")
738
+ })
739
+ end
740
+ properties.each do |type, defn|
741
+ next unless type.is_a?(String)
742
+ it "returns #{defn[:rank]} for #{type}" do
743
+ ctx.send(:term_rank, "term", defn[:value]).should produce(defn[:rank], @debug)
744
+ end
745
+ end
746
+ end
747
+ end
748
+
749
+ context "with default language" do
750
+ before(:each) {subject.default_language = "en"}
751
+ {
752
+ "no coercions" => {
753
+ :defn => {},
754
+ "boolean value" => {:value => {"@value" => true}, :rank => 2},
755
+ "integer value" => {:value => {"@value" => 1}, :rank => 2},
756
+ "double value" => {:value => {"@value" => 1.1}, :rank => 2},
757
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
758
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 1},
759
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 3},
760
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 1},
761
+ "value string" => {:value => {"@value" => "foo"}, :rank => 0},
762
+ "null" => {:value => nil, :rank => 3},
763
+ },
764
+ "boolean" => {
765
+ :defn => {"@type" => RDF::XSD.boolean.to_s},
766
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
767
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
768
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
769
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
770
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
771
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
772
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
773
+ "value boolean" => {:value => {"@value" => "true", "@type" => RDF::XSD.boolean.to_s}, :rank => 3},
774
+ "null" => {:value => nil, :rank => 3},
775
+ },
776
+ "integer" => {
777
+ :defn => {"@type" => RDF::XSD.integer.to_s},
778
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
779
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
780
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
781
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
782
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
783
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
784
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
785
+ "value integer" => {:value => {"@value" => "1", "@type" => RDF::XSD.integer.to_s}, :rank => 3},
786
+ "null" => {:value => nil, :rank => 3},
787
+ },
788
+ "double" => {
789
+ :defn => {"@type" => RDF::XSD.double.to_s},
790
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
791
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
792
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
793
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
794
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
795
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
796
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
797
+ "value double" => {:value => {"@value" => "1.1", "@type" => RDF::XSD.double.to_s}, :rank => 3},
798
+ "null" => {:value => nil, :rank => 3},
799
+ },
800
+ "date" => {
801
+ :defn => {"@type" => RDF::XSD.date.to_s},
802
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
803
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
804
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
805
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
806
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 3},
807
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
808
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
809
+ "null" => {:value => nil, :rank => 3},
810
+ },
811
+ "lang" => {
812
+ :defn => {"@language" => "en"},
813
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
814
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
815
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
816
+ "string value" => {:value => {"@value" => "foo"}, :rank => 0},
817
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
818
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 3},
819
+ "other lang" => {:value => {"@value" => "apple", "@language" => "de"}, :rank => 0},
820
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
821
+ "null" => {:value => nil, :rank => 3},
822
+ },
823
+ "null lang" => {
824
+ :defn => {"@language" => nil},
825
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
826
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
827
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
828
+ "string value" => {:value => {"@value" => "foo"}, :rank => 3},
829
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
830
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
831
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 0},
832
+ "null" => {:value => nil, :rank => 3},
833
+ },
834
+ "id" => {
835
+ :defn => {"@type" => "@id"},
836
+ "boolean value" => {:value => {"@value" => true}, :rank => 1},
837
+ "integer value" => {:value => {"@value" => 1}, :rank => 1},
838
+ "double value" => {:value => {"@value" => 1.1}, :rank => 1},
839
+ "string" => {:value => {"@value" => "foo"}, :rank => 0},
840
+ "date" => {:value => {"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}, :rank => 0},
841
+ "lang" => {:value => {"@value" => "apple", "@language" => "en"}, :rank => 0},
842
+ "other lang" => {:value => {"@value" => "apple", "@language" => "de"}, :rank => 0},
843
+ "id" => {:value => {"@id" => "http://example/id"}, :rank => 3},
844
+ "null" => {:value => nil, :rank => 3},
845
+ },
846
+ }.each do |title, properties|
847
+ context title do
848
+ let(:ctx) do
849
+ subject.parse({
850
+ "term" => properties[:defn].merge("@id" => "http://example.org/term")
851
+ })
852
+ end
853
+ properties.each do |type, defn|
854
+ next unless type.is_a?(String)
855
+ it "returns #{defn[:rank]} for #{type}" do
856
+ ctx.send(:term_rank, "term", defn[:value]).should produce(defn[:rank], @debug)
857
+ end
858
+ end
859
+ end
860
+ end
861
+ end
862
+ end
863
+
864
+ describe "#expand_value" do
865
+ before(:each) do
866
+ subject.set_mapping("dc", RDF::DC.to_uri.to_s)
867
+ subject.set_mapping("ex", "http://example.org/")
868
+ subject.set_mapping("foaf", RDF::FOAF.to_uri.to_s)
869
+ subject.set_mapping("xsd", RDF::XSD.to_uri.to_s)
870
+ subject.set_coerce("foaf:age", RDF::XSD.integer.to_s)
871
+ subject.set_coerce("foaf:knows", "@id")
872
+ subject.set_coerce("dc:created", RDF::XSD.date.to_s)
873
+ subject.set_coerce("ex:double", RDF::XSD.double.to_s)
874
+ subject.set_coerce("ex:boolean", RDF::XSD.boolean.to_s)
875
+ end
876
+
877
+ {
878
+ "absolute IRI" => ["foaf:knows", "http://example.com/", {"@id" => "http://example.com/"}],
879
+ "term" => ["foaf:knows", "ex", {"@id" => "http://example.org/"}],
880
+ "prefix:suffix" => ["foaf:knows", "ex:suffix", {"@id" => "http://example.org/suffix"}],
881
+ "no IRI" => ["foo", "http://example.com/", {"@value" => "http://example.com/"}],
882
+ "no term" => ["foo", "ex", {"@value" => "ex"}],
883
+ "no prefix" => ["foo", "ex:suffix", {"@value" => "ex:suffix"}],
884
+ "integer" => ["foaf:age", "54", {"@value" => "54", "@type" => RDF::XSD.integer.to_s}],
885
+ "date " => ["dc:created", "2011-12-27Z", {"@value" => "2011-12-27Z", "@type" => RDF::XSD.date.to_s}],
886
+ "native boolean" => ["foo", true, {"@value" => true}],
887
+ "native integer" => ["foo", 1, {"@value" => 1}],
888
+ "native double" => ["foo", 1.1e1, {"@value" => 1.1E1}],
889
+ "native date" => ["foo", Date.parse("2011-12-27Z"), {"@value" => "2011-12-27Z", "@type" => RDF::XSD.date.to_s}],
890
+ "native time" => ["foo", Time.parse("10:11:12Z"), {"@value" => "10:11:12Z", "@type" => RDF::XSD.time.to_s}],
891
+ "native dateTime" =>["foo", DateTime.parse("2011-12-27T10:11:12Z"), {"@value" => "2011-12-27T10:11:12Z", "@type" => RDF::XSD.dateTime.to_s}],
892
+ "rdf boolean" => ["foo", RDF::Literal(true), {"@value" => true}],
893
+ "rdf integer" => ["foo", RDF::Literal(1), {"@value" => 1}],
894
+ "rdf decimal" => ["foo", RDF::Literal::Decimal.new(1.1), {"@value" => "1.1", "@type" => RDF::XSD.decimal.to_s}],
895
+ "rdf double" => ["foo", RDF::Literal::Double.new(1.1), {"@value" => 1.1}],
896
+ "rdf URI" => ["foo", RDF::URI("foo"), {"@id" => "foo"}],
897
+ "rdf date " => ["foo", RDF::Literal(Date.parse("2011-12-27Z")), {"@value" => "2011-12-27Z", "@type" => RDF::XSD.date.to_s}],
898
+ }.each do |title, (key, compacted, expanded)|
899
+ it title do
900
+ subject.expand_value(key, compacted).should produce(expanded, @debug)
901
+ end
902
+ end
903
+
904
+ context "@language" do
905
+ before(:each) {subject.default_language = "en"}
906
+ {
907
+ "no IRI" => ["foo", "http://example.com/", {"@value" => "http://example.com/", "@language" => "en"}],
908
+ "no term" => ["foo", "ex", {"@value" => "ex", "@language" => "en"}],
909
+ "no prefix" => ["foo", "ex:suffix", {"@value" => "ex:suffix", "@language" => "en"}],
910
+ "native boolean" => ["foo", true, {"@value" => true}],
911
+ "native integer" => ["foo", 1, {"@value" => 1}],
912
+ "native double" => ["foo", 1.1, {"@value" => 1.1}],
913
+ }.each do |title, (key, compacted, expanded)|
914
+ it title do
915
+ subject.expand_value(key, compacted).should produce(expanded, @debug)
916
+ end
917
+ end
918
+ end
919
+
920
+ context "coercion" do
921
+ before(:each) {subject.default_language = "en"}
922
+ {
923
+ "boolean-boolean" => ["ex:boolean", true, {"@value" => true}],
924
+ "boolean-double" => ["ex:double", true, {"@value" => "true", "@type" => RDF::XSD.double.to_s}],
925
+ "boolean-int" => ["foaf:age", true, {"@value" => true}],
926
+ "double-boolean" => ["ex:boolean", 1.1, {"@value" => "1.1", "@type" => RDF::XSD.boolean.to_s}],
927
+ "double-double" => ["ex:double", 1.1, {"@value" => "1.1E0", "@type" => RDF::XSD.double.to_s}],
928
+ "double-int" => ["foaf:age", 1.1, {"@value" => "1", "@type" => RDF::XSD.integer.to_s}],
929
+ "int-boolean" => ["ex:boolean", 1, {"@value" => "1", "@type" => RDF::XSD.boolean.to_s}],
930
+ "int-double" => ["ex:double", 1, {"@value" => "1.0E0", "@type" => RDF::XSD.double.to_s}],
931
+ "int-int" => ["foaf:age", 1, {"@value" => 1}],
932
+ "string-boolean" => ["ex:boolean", "foo", {"@value" => "foo", "@type" => RDF::XSD.boolean.to_s}],
933
+ "string-double" => ["ex:double", "foo", {"@value" => "foo", "@type" => RDF::XSD.double.to_s}],
934
+ "string-int" => ["foaf:age", "foo", {"@value" => "foo", "@type" => RDF::XSD.integer.to_s}],
935
+ }.each do |title, (key, compacted, expanded)|
936
+ it title do
937
+ subject.expand_value(key, compacted).should produce(expanded, @debug)
938
+ end
939
+ end
940
+ end
941
+ end
942
+
943
+ describe "compact_value" do
944
+ before(:each) do
945
+ subject.set_mapping("dc", RDF::DC.to_uri.to_s)
946
+ subject.set_mapping("ex", "http://example.org/")
947
+ subject.set_mapping("foaf", RDF::FOAF.to_uri.to_s)
948
+ subject.set_mapping("xsd", RDF::XSD.to_uri.to_s)
949
+ subject.set_mapping("list", "http://example.org/list")
950
+ subject.set_mapping("nolang", "http://example.org/nolang")
951
+ subject.set_coerce("foaf:age", RDF::XSD.integer.to_s)
952
+ subject.set_coerce("foaf:knows", "@id")
953
+ subject.set_coerce("dc:created", RDF::XSD.date.to_s)
954
+ subject.set_container("list", "@list")
955
+ subject.set_language("nolang", nil)
956
+ end
957
+
958
+ {
959
+ "absolute IRI" => ["foaf:knows", "http://example.com/", {"@id" => "http://example.com/"}],
960
+ "term" => ["foaf:knows", "ex", {"@id" => "http://example.org/"}],
961
+ "prefix:suffix" => ["foaf:knows", "ex:suffix", {"@id" => "http://example.org/suffix"}],
962
+ "integer" => ["foaf:age", "54", {"@value" => "54", "@type" => RDF::XSD.integer.to_s}],
963
+ "date " => ["dc:created", "2011-12-27Z", {"@value" => "2011-12-27Z", "@type" => RDF::XSD.date.to_s}],
964
+ "no IRI" => ["foo", {"@id" =>"http://example.com/"},{"@id" => "http://example.com/"}],
965
+ "no IRI (term)" => ["foo", {"@id" => "ex"}, {"@id" => "http://example.org/"}],
966
+ "no IRI (CURIE)" => ["foo", {"@id" => "foaf:Person"}, {"@id" => RDF::FOAF.Person.to_s}],
967
+ "no boolean" => ["foo", {"@value" => "true", "@type" => "xsd:boolean"},{"@value" => "true", "@type" => RDF::XSD.boolean.to_s}],
968
+ "no integer" => ["foo", {"@value" => "54", "@type" => "xsd:integer"},{"@value" => "54", "@type" => RDF::XSD.integer.to_s}],
969
+ "no date " => ["foo", {"@value" => "2011-12-27Z", "@type" => "xsd:date"}, {"@value" => "2011-12-27Z", "@type" => RDF::XSD.date.to_s}],
970
+ "no string " => ["foo", "string", {"@value" => "string"}],
971
+ "no lang " => ["nolang", "string", {"@value" => "string"}],
972
+ "native boolean" => ["foo", true, {"@value" => true}],
973
+ "native integer" => ["foo", 1, {"@value" => 1}],
974
+ "native integer(list)"=>["list", 1, {"@value" => 1}],
975
+ "native double" => ["foo", 1.1e1, {"@value" => 1.1E1}],
976
+ }.each do |title, (key, compacted, expanded)|
977
+ it title do
978
+ subject.compact_value(key, expanded).should produce(compacted, @debug)
979
+ end
980
+ end
981
+
982
+ context "@language" do
983
+ {
984
+ "@id" => ["foo", {"@id" => "foo"}, {"@id" => "foo"}],
985
+ "integer" => ["foo", {"@value" => "54", "@type" => "xsd:integer"}, {"@value" => "54", "@type" => "xsd:integer"}],
986
+ "date" => ["foo", {"@value" => "2011-12-27Z","@type" => "xsd:date"},{"@value" => "2011-12-27Z", "@type" => RDF::XSD.date.to_s}],
987
+ "no lang" => ["foo", {"@value" => "foo" }, {"@value" => "foo"}],
988
+ "same lang" => ["foo", "foo", {"@value" => "foo", "@language" => "en"}],
989
+ "other lang" => ["foo", {"@value" => "foo", "@language" => "bar"}, {"@value" => "foo", "@language" => "bar"}],
990
+ "no lang with @type coercion" => ["dc:created", {"@value" => "foo"}, {"@value" => "foo"}],
991
+ "no lang with @id coercion" => ["foaf:knows", {"@value" => "foo"}, {"@value" => "foo"}],
992
+ "no lang with @language=null" => ["nolang", "string", {"@value" => "string"}],
993
+ "same lang with @type coercion" => ["dc:created", {"@value" => "foo"}, {"@value" => "foo"}],
994
+ "same lang with @id coercion" => ["foaf:knows", {"@value" => "foo"}, {"@value" => "foo"}],
995
+ "other lang with @type coercion" => ["dc:created", {"@value" => "foo", "@language" => "bar"}, {"@value" => "foo", "@language" => "bar"}],
996
+ "other lang with @id coercion" => ["foaf:knows", {"@value" => "foo", "@language" => "bar"}, {"@value" => "foo", "@language" => "bar"}],
997
+ "native boolean" => ["foo", true, {"@value" => true}],
998
+ "native integer" => ["foo", 1, {"@value" => 1}],
999
+ "native integer(list)" => ["list", 1, {"@value" => 1}],
1000
+ "native double" => ["foo", 1.1e1, {"@value" => 1.1E1}],
1001
+ }.each do |title, (key, compacted, expanded)|
1002
+ it title do
1003
+ subject.default_language = "en"
1004
+ subject.compact_value(key, expanded).should produce(compacted, @debug)
1005
+ end
1006
+ end
1007
+ end
1008
+
1009
+ [[], true, false, 1, 1.1, "string"].each do |v|
1010
+ it "raises error given #{v.class}" do
1011
+ lambda {subject.compact_value("foo", v)}.should raise_error(JSON::LD::ProcessingError::Lossy)
1012
+ end
1013
+ end
1014
+
1015
+ context "keywords" do
1016
+ before(:each) do
1017
+ subject.set_mapping("id", "@id")
1018
+ subject.set_mapping("type", "@type")
1019
+ subject.set_mapping("list", "@list")
1020
+ subject.set_mapping("set", "@set")
1021
+ subject.set_mapping("language", "@language")
1022
+ subject.set_mapping("literal", "@value")
1023
+ end
1024
+
1025
+ {
1026
+ "@id" => [{"id" => "http://example.com/"}, {"@id" => "http://example.com/"}],
1027
+ "@type" => [{"literal" => "foo", "type" => "http://example.com/"},
1028
+ {"@value" => "foo", "@type" => "http://example.com/"}],
1029
+ "@value" => [{"literal" => "foo", "language" => "bar"}, {"@value" => "foo", "@language" => "bar"}],
1030
+ "@list" => [{"list" => ["foo"]}, {"@list" => ["foo"] }],
1031
+ "@set" => [{"set" => ["foo"]}, {"@set" => ["foo"] }],
1032
+ }.each do |title, (compacted, expanded)|
1033
+ it title do
1034
+ subject.compact_value("foo", expanded).should produce(compacted, @debug)
1035
+ end
1036
+ end
1037
+ end
1038
+ end
1039
+ end