ld4l-open_annotation_rdf 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +11 -0
  6. data/LICENSE.txt +14 -0
  7. data/README.md +231 -0
  8. data/Rakefile +2 -0
  9. data/ld4l-open_annotation_rdf.gemspec +46 -0
  10. data/lib/ld4l/open_annotation_rdf.rb +66 -0
  11. data/lib/ld4l/open_annotation_rdf/annotation.rb +82 -0
  12. data/lib/ld4l/open_annotation_rdf/comment_annotation.rb +47 -0
  13. data/lib/ld4l/open_annotation_rdf/comment_body.rb +24 -0
  14. data/lib/ld4l/open_annotation_rdf/configuration.rb +127 -0
  15. data/lib/ld4l/open_annotation_rdf/semantic_tag_annotation.rb +66 -0
  16. data/lib/ld4l/open_annotation_rdf/semantic_tag_body.rb +70 -0
  17. data/lib/ld4l/open_annotation_rdf/tag_annotation.rb +98 -0
  18. data/lib/ld4l/open_annotation_rdf/tag_body.rb +83 -0
  19. data/lib/ld4l/open_annotation_rdf/version.rb +5 -0
  20. data/lib/ld4l/open_annotation_rdf/vocab/cnt.rb +6 -0
  21. data/lib/ld4l/open_annotation_rdf/vocab/dctypes.rb +5 -0
  22. data/lib/ld4l/open_annotation_rdf/vocab/oa.rb +23 -0
  23. data/spec/ld4l/open_annotation_rdf/annotation_spec.rb +603 -0
  24. data/spec/ld4l/open_annotation_rdf/comment_annotation_spec.rb +559 -0
  25. data/spec/ld4l/open_annotation_rdf/comment_body_spec.rb +371 -0
  26. data/spec/ld4l/open_annotation_rdf/configuration_spec.rb +194 -0
  27. data/spec/ld4l/open_annotation_rdf/semantic_tag_annotation_spec.rb +619 -0
  28. data/spec/ld4l/open_annotation_rdf/semantic_tag_body_spec.rb +412 -0
  29. data/spec/ld4l/open_annotation_rdf/tag_annotation_spec.rb +672 -0
  30. data/spec/ld4l/open_annotation_rdf/tag_body_spec.rb +430 -0
  31. data/spec/ld4l/open_annotation_rdf_spec.rb +57 -0
  32. data/spec/spec_helper.rb +21 -0
  33. metadata +201 -0
@@ -0,0 +1,619 @@
1
+ require 'spec_helper'
2
+
3
+ # TODO: Uses CommentBody as the annotation body, which is wrong. Should be URI into controlled vocabulary.
4
+
5
+ describe 'LD4L::OpenAnnotationRDF::SemanticTagAnnotation' do
6
+
7
+ subject { LD4L::OpenAnnotationRDF::SemanticTagAnnotation.new }
8
+
9
+ describe 'rdf_subject' do
10
+ it "should be a blank node if we haven't set it" do
11
+ expect(subject.rdf_subject.node?).to be true
12
+ end
13
+
14
+ it "should be settable when it has not been set yet" do
15
+ subject.set_subject! RDF::URI('http://example.org/moomin')
16
+ expect(subject.rdf_subject).to eq RDF::URI('http://example.org/moomin')
17
+ end
18
+
19
+ it "should append to base URI when setting to non-URI subject" do
20
+ subject.set_subject! '123'
21
+ expect(subject.rdf_subject).to eq RDF::URI("#{LD4L::OpenAnnotationRDF::SemanticTagAnnotation.base_uri}123")
22
+ end
23
+
24
+ describe 'when changing subject' do
25
+ before do
26
+ subject << RDF::Statement.new(subject.rdf_subject, RDF::DC.title, RDF::Literal('Comet in Moominland'))
27
+ subject << RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.isPartOf, subject.rdf_subject)
28
+ subject << RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.relation, 'http://example.org/moomin_land')
29
+ subject.set_subject! RDF::URI('http://example.org/moomin')
30
+ end
31
+
32
+ it 'should update graph subjects' do
33
+ expect(subject.has_statement?(RDF::Statement.new(subject.rdf_subject, RDF::DC.title, RDF::Literal('Comet in Moominland')))).to be true
34
+ end
35
+
36
+ it 'should update graph objects' do
37
+ expect(subject.has_statement?(RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.isPartOf, subject.rdf_subject))).to be true
38
+ end
39
+
40
+ it 'should leave other uris alone' do
41
+ expect(subject.has_statement?(RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.relation, 'http://example.org/moomin_land'))).to be true
42
+ end
43
+ end
44
+
45
+ describe 'created with URI subject' do
46
+ before do
47
+ subject.set_subject! RDF::URI('http://example.org/moomin')
48
+ end
49
+
50
+ it 'should not be settable' do
51
+ expect{ subject.set_subject! RDF::URI('http://example.org/moomin2') }.to raise_error
52
+ end
53
+ end
54
+ end
55
+
56
+
57
+ # -------------------------------------------------
58
+ # START -- Test attributes specific to this model
59
+ # -------------------------------------------------
60
+
61
+ describe 'type' do
62
+ it "should be an RDFVocabularies::OA.Annotation" do
63
+ expect(subject.type.first.value).to eq RDFVocabularies::OA.Annotation.value
64
+ end
65
+ end
66
+
67
+ describe 'hasTarget' do
68
+ it "should be empty array if we haven't set it" do
69
+ expect(subject.hasTarget).to match_array([])
70
+ end
71
+
72
+ it "should be settable" do
73
+ subject.hasTarget = RDF::URI("http://example.org/b123")
74
+ expect(subject.hasTarget.first.rdf_subject.to_s).to eq "http://example.org/b123"
75
+ end
76
+
77
+ it "should be changeable" do
78
+ subject.hasTarget = RDF::URI("http://example.org/b123")
79
+ subject.hasTarget = RDF::URI("http://example.org/b123_NEW")
80
+ expect(subject.hasTarget.first.rdf_subject.to_s).to eq "http://example.org/b123_NEW"
81
+ end
82
+ end
83
+
84
+ describe 'hasBody' do
85
+ # NOTE: Preferred method to set body is to use setTerm method which will
86
+ # create the appropriate annotation body object and triples.
87
+ it "should be empty array if we haven't set it" do
88
+ expect(subject.hasBody).to match_array([])
89
+ end
90
+
91
+ it "should be settable" do
92
+ subject.hasBody = RDF::URI("http://example.org/cv/term/t123")
93
+ expect(subject.hasBody.first.rdf_subject.to_s).to eq "http://example.org/cv/term/t123"
94
+ end
95
+
96
+ it "should be changeable" do
97
+ subject.hasBody = RDF::URI("http://example.org/cv/term/t123")
98
+ subject.hasBody = RDF::URI("http://example.org/cv/term/t123_NEW")
99
+ expect(subject.hasBody.first.rdf_subject.to_s).to eq "http://example.org/cv/term/t123_NEW"
100
+ end
101
+ end
102
+
103
+ describe '#setTerm' do
104
+ before do
105
+ @repo = RDF::Repository.new
106
+ allow(subject.class).to receive(:repository).and_return(nil)
107
+ allow(subject).to receive(:repository).and_return(@repo)
108
+ end
109
+
110
+ context "when new value is nil" do
111
+ it "should throw invalid arguement exception" do
112
+ expect{ subject.setTerm(nil) }.to raise_error
113
+ end
114
+ end
115
+
116
+ context "when new value is a string of 0 length" do
117
+ it "should throw invalid arguement exception" do
118
+ expect{ subject.setTerm("") }.to raise_error
119
+ end
120
+ end
121
+
122
+ context "when new value is not a string or uri" do
123
+ it "should throw invalid arguement exception" do
124
+ expect{ subject.setTerm(3) }.to raise_error
125
+ end
126
+ end
127
+
128
+ context "when new value is same as old value" do
129
+ it "should return the existing TagBody unchanged" do
130
+ tb1 = subject.setTerm('http://example.org/new_term')
131
+ tb2 = subject.setTerm('http://example.org/new_term')
132
+ expect(tb2).to eq tb1
133
+ end
134
+ end
135
+
136
+ context "when term doesn't already exist as a SemanticTagBody" do
137
+ before do
138
+ stb = LD4L::OpenAnnotationRDF::SemanticTagBody.new('http://example.org/new_term')
139
+ expect(stb).not_to be_persisted
140
+ end
141
+ it "should create an instance of LD4L::OpenAnnotationRDF::SemanticTagBody and set hasBody property to term URI" do
142
+ subject.setTerm('http://example.org/new_term')
143
+ expect(subject.hasBody.first.rdf_subject).to be_kind_of RDF::URI
144
+ expect(subject.hasBody.first.rdf_subject.to_s).to eq 'http://example.org/new_term'
145
+ stb = LD4L::OpenAnnotationRDF::SemanticTagBody.new('http://example.org/new_term')
146
+ expect(stb).not_to be_persisted
147
+ expect(subject.getBody).to be_kind_of LD4L::OpenAnnotationRDF::SemanticTagBody
148
+ expect(subject.getBody.rdf_subject.to_s).to eq 'http://example.org/new_term'
149
+ expect(subject.getBody).not_to be_persisted
150
+ end
151
+ end
152
+
153
+ context "when term already exists as a SemanticTagBody" do
154
+ before do
155
+ stb = LD4L::OpenAnnotationRDF::SemanticTagBody.new('http://example.org/existing_term')
156
+ stb.persist!
157
+ expect(stb).to be_persisted
158
+ end
159
+ it "should resume the existing LD4L::OpenAnnotationRDF::SemanticTagBody and set hasBody property to it" do
160
+ subject.setTerm('http://example.org/existing_term')
161
+ stb = LD4L::OpenAnnotationRDF::SemanticTagBody.new('http://example.org/existing_term')
162
+ expect(stb).to be_persisted
163
+ expect(subject.hasBody.first.rdf_subject).to be_kind_of RDF::URI
164
+ expect(subject.hasBody.first.rdf_subject.to_s).to eq 'http://example.org/existing_term'
165
+ expect(subject.getBody).to be_kind_of LD4L::OpenAnnotationRDF::SemanticTagBody
166
+ expect(subject.getBody.rdf_subject.to_s).to eq 'http://example.org/existing_term'
167
+ # NOTE: body is considered not persisted because it's parent, the annotation, is not persisted
168
+ expect(subject.getBody).not_to be_persisted
169
+ end
170
+ end
171
+ end
172
+
173
+ describe 'annotatedBy' do
174
+ it "should be empty array if we haven't set it" do
175
+ expect(subject.annotatedBy).to match_array([])
176
+ end
177
+
178
+ it "should be settable" do
179
+ a_person = LD4L::FoafRDF::Person.new('1')
180
+ subject.annotatedBy = a_person
181
+ expect(subject.annotatedBy.first).to eq a_person
182
+ end
183
+
184
+ it "should be changeable" do
185
+ orig_person = LD4L::FoafRDF::Person.new('1')
186
+ new_person = LD4L::FoafRDF::Person.new('2')
187
+ subject.annotatedBy = orig_person
188
+ subject.annotatedBy = new_person
189
+ expect(subject.annotatedBy.first).to eq new_person
190
+ end
191
+ end
192
+
193
+ describe 'annotatedAt' do
194
+ it "should be empty array if we haven't set it" do
195
+ expect(subject.annotatedAt).to match_array([])
196
+ end
197
+
198
+ it "should be settable" do
199
+ a_time = Time::now.strftime("%Y-%m-%dT%H:%M:%S.%L%z")
200
+ subject.annotatedAt = a_time
201
+ expect(subject.annotatedAt.first).to eq a_time
202
+ end
203
+
204
+ it "should be changeable" do
205
+ orig_time = Time.local(2014, 6, 1, 8, 30).strftime("%Y-%m-%dT%H:%M:%S.%L%z")
206
+ new_time = Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L%z")
207
+ subject.annotatedAt = orig_time
208
+ subject.annotatedAt = new_time
209
+ expect(subject.annotatedAt.first).to eq new_time
210
+ end
211
+ end
212
+
213
+ describe 'motivatedBy' do
214
+ it "should be OA.tagging if we haven't set it" do
215
+ expect(subject.motivatedBy.first.rdf_subject.to_s).to eq RDFVocabularies::OA.tagging
216
+ end
217
+
218
+ it "should be settable" do
219
+ subject.motivatedBy = RDFVocabularies::OA.describing
220
+ expect(subject.motivatedBy.first.rdf_subject.to_s).to eq RDFVocabularies::OA.describing
221
+ end
222
+
223
+ it "should be changeable" do
224
+ subject.motivatedBy = RDFVocabularies::OA.describing
225
+ subject.motivatedBy = RDFVocabularies::OA.classifying
226
+ expect(subject.motivatedBy.first.rdf_subject.to_s).to eq RDFVocabularies::OA.classifying
227
+ end
228
+ end
229
+
230
+ describe '#localname_prefix' do
231
+ it "should return default prefix" do
232
+ prefix = LD4L::OpenAnnotationRDF::SemanticTagAnnotation.localname_prefix
233
+ expect(prefix).to eq "sta"
234
+ end
235
+ end
236
+
237
+ # -----------------------------------------------
238
+ # END -- Test attributes specific to this model
239
+ # -----------------------------------------------
240
+
241
+
242
+ describe "#persisted?" do
243
+ context 'with a repository' do
244
+ before do
245
+ # Create inmemory repository
246
+ repository = RDF::Repository.new
247
+ allow(subject).to receive(:repository).and_return(repository)
248
+ end
249
+
250
+ context "when the object is new" do
251
+ it "should return false" do
252
+ expect(subject).not_to be_persisted
253
+ end
254
+ end
255
+
256
+ context "when it is saved" do
257
+ before do
258
+ subject.motivatedBy = RDFVocabularies::OA.commenting
259
+ subject.persist!
260
+ end
261
+
262
+ it "should return true" do
263
+ expect(subject).to be_persisted
264
+ end
265
+
266
+ context "and then modified" do
267
+ before do
268
+ subject.motivatedBy = RDFVocabularies::OA.tagging
269
+ end
270
+
271
+ it "should return true" do
272
+ expect(subject).to be_persisted
273
+ end
274
+ end
275
+ context "and then reloaded" do
276
+ before do
277
+ subject.reload
278
+ end
279
+
280
+ it "should reset the motivatedBy" do
281
+ expect(subject.motivatedBy.first.rdf_subject.to_s).to eq RDFVocabularies::OA.commenting.to_s
282
+ end
283
+
284
+ it "should be persisted" do
285
+ expect(subject).to be_persisted
286
+ end
287
+ end
288
+ end
289
+ end
290
+ end
291
+
292
+ describe "#persist!" do
293
+ context "when the repository is set" do
294
+ context "and the item is not a blank node" do
295
+
296
+ subject {LD4L::OpenAnnotationRDF::SemanticTagAnnotation.new("123")}
297
+
298
+ before do
299
+ # Create inmemory repository
300
+ @repo = RDF::Repository.new
301
+ allow(subject.class).to receive(:repository).and_return(nil)
302
+ allow(subject).to receive(:repository).and_return(@repo)
303
+ subject.motivatedBy = RDFVocabularies::OA.commenting
304
+ subject.persist!
305
+ end
306
+
307
+ it "should persist to the repository" do
308
+ expect(@repo.statements.first).to eq subject.statements.first
309
+ end
310
+
311
+ it "should delete from the repository" do
312
+ subject.reload
313
+ expect(subject.motivatedBy.first.rdf_subject.to_s).to eq RDFVocabularies::OA.commenting.to_s
314
+ subject.motivatedBy = []
315
+ expect(subject.motivatedBy).to eq []
316
+ subject.persist!
317
+ subject.reload
318
+ expect(subject.annotatedAt).to eq []
319
+ expect(@repo.statements.to_a.length).to eq 1 # Only the type statement
320
+ end
321
+
322
+ context "when body is set" do
323
+ before do
324
+ subject.setTerm('http://example.org/new_term2')
325
+ subject.persist!
326
+ end
327
+ it "should persist body to the repository" do
328
+ stb = LD4L::OpenAnnotationRDF::SemanticTagBody.new(subject.getBody.rdf_subject)
329
+ expect(stb).to be_persisted
330
+ stb = LD4L::OpenAnnotationRDF::SemanticTagBody.new('http://example.org/new_term2')
331
+ expect(stb).to be_persisted
332
+ expect(subject.getBody.rdf_subject.to_s).to eq 'http://example.org/new_term2'
333
+ end
334
+ end
335
+ end
336
+ end
337
+ end
338
+
339
+ describe '#destroy!' do
340
+ before do
341
+ subject << RDF::Statement(RDF::DC.LicenseDocument, RDF::DC.title, 'LICENSE')
342
+ end
343
+
344
+ subject { LD4L::OpenAnnotationRDF::SemanticTagAnnotation.new('123') }
345
+
346
+ it 'should return true' do
347
+ expect(subject.destroy!).to be true
348
+ expect(subject.destroy).to be true
349
+ end
350
+
351
+ it 'should delete the graph' do
352
+ subject.destroy
353
+ expect(subject).to be_empty
354
+ end
355
+
356
+ context 'with a parent' do
357
+ before do
358
+ subject.annotatedBy = child
359
+ end
360
+
361
+ let(:child) do
362
+ LD4L::FoafRDF::Person.new('456')
363
+ end
364
+
365
+ it 'should empty the graph and remove it from the parent' do
366
+ child.destroy
367
+ expect(subject.annotatedBy).to be_empty
368
+ end
369
+
370
+ it 'should remove its whole graph from the parent' do
371
+ child.destroy
372
+ child.each_statement do |s|
373
+ expect(subject.statements).not_to include s
374
+ end
375
+ end
376
+ end
377
+
378
+ context 'with annotation body' do
379
+ before do
380
+ subject.setTerm('http://example.org/new_term3')
381
+ end
382
+
383
+ context 'and body is set on the annotation' do
384
+ let(:child) do
385
+ subject.getBody
386
+ end
387
+
388
+ it 'should empty the graph and remove it from the parent' do
389
+ child.destroy
390
+ expect(subject.hasBody).to be_empty
391
+ end
392
+
393
+ it 'should remove its whole graph from the parent' do
394
+ child.destroy
395
+ child.each_statement do |s|
396
+ expect(subject.statements).not_to include s
397
+ end
398
+ end
399
+ end
400
+ end
401
+ end
402
+
403
+ describe 'attributes' do
404
+ before do
405
+ subject.annotatedBy = annotatedBy
406
+ subject.motivatedBy = 'commenting'
407
+ end
408
+
409
+ subject {LD4L::OpenAnnotationRDF::SemanticTagAnnotation.new("123")}
410
+
411
+ let(:annotatedBy) { LD4L::FoafRDF::Person.new('456') }
412
+
413
+ it 'should return an attributes hash' do
414
+ expect(subject.attributes).to be_a Hash
415
+ end
416
+
417
+ it 'should contain data' do
418
+ expect(subject.attributes['motivatedBy']).to eq ['commenting']
419
+ end
420
+
421
+ it 'should contain child objects' do
422
+ expect(subject.attributes['annotatedBy']).to eq [annotatedBy]
423
+ end
424
+
425
+ context 'with unmodeled data' do
426
+ before do
427
+ subject << RDF::Statement(subject.rdf_subject, RDF::DC.contributor, 'Tove Jansson')
428
+ subject << RDF::Statement(subject.rdf_subject, RDF::DC.relation, RDF::URI('http://example.org/moomi'))
429
+ node = RDF::Node.new
430
+ subject << RDF::Statement(RDF::URI('http://example.org/moomi'), RDF::DC.relation, node)
431
+ subject << RDF::Statement(node, RDF::DC.title, 'bnode')
432
+ end
433
+
434
+ it 'should include data with URIs as attribute names' do
435
+ expect(subject.attributes[RDF::DC.contributor.to_s]).to eq ['Tove Jansson']
436
+ end
437
+
438
+ it 'should return generic Resources' do
439
+ expect(subject.attributes[RDF::DC.relation.to_s].first).to be_a ActiveTriples::Resource
440
+ end
441
+
442
+ it 'should build deep data for Resources' do
443
+ expect(subject.attributes[RDF::DC.relation.to_s].first.get_values(RDF::DC.relation).
444
+ first.get_values(RDF::DC.title)).to eq ['bnode']
445
+ end
446
+
447
+ it 'should include deep data in serializable_hash' do
448
+ expect(subject.serializable_hash[RDF::DC.relation.to_s].first.get_values(RDF::DC.relation).
449
+ first.get_values(RDF::DC.title)).to eq ['bnode']
450
+ end
451
+ end
452
+
453
+ describe 'attribute_serialization' do
454
+ describe '#to_json' do
455
+ it 'should return a string with correct objects' do
456
+ json_hash = JSON.parse(subject.to_json)
457
+ expect(json_hash['annotatedBy'].first['id']).to eq annotatedBy.rdf_subject.to_s
458
+ end
459
+ end
460
+ end
461
+ end
462
+
463
+ describe 'property methods' do
464
+ it 'should set and get properties' do
465
+ subject.motivatedBy = 'commenting'
466
+ expect(subject.motivatedBy).to eq ['commenting']
467
+ end
468
+ end
469
+
470
+ describe 'child nodes' do
471
+ it 'should return an object of the correct class when the value is built from the base URI' do
472
+ subject.annotatedBy = LD4L::FoafRDF::Person.new('456')
473
+ expect(subject.annotatedBy.first).to be_kind_of LD4L::FoafRDF::Person
474
+ end
475
+
476
+ it 'should return an object with the correct URI when created with a URI' do
477
+ subject.annotatedBy = LD4L::FoafRDF::Person.new("http://vivo.cornell.edu/individual/JohnSmith")
478
+ expect(subject.annotatedBy.first.rdf_subject).to eq RDF::URI("http://vivo.cornell.edu/individual/JohnSmith")
479
+ end
480
+
481
+ it 'should return an object of the correct class when the value is a bnode' do
482
+ subject.annotatedBy = LD4L::FoafRDF::Person.new
483
+ expect(subject.annotatedBy.first).to be_kind_of LD4L::FoafRDF::Person
484
+ end
485
+ end
486
+
487
+ describe '#type' do
488
+ it 'should return the type configured on the parent class' do
489
+ expect(subject.type).to eq [LD4L::OpenAnnotationRDF::SemanticTagAnnotation.type]
490
+ end
491
+
492
+ it 'should set the type' do
493
+ subject.type = RDF::URI('http://example.org/AnotherClass')
494
+ expect(subject.type).to eq [RDF::URI('http://example.org/AnotherClass')]
495
+ end
496
+
497
+ it 'should be the type in the graph' do
498
+ subject.query(:subject => subject.rdf_subject, :predicate => RDF.type).statements do |s|
499
+ expect(s.object).to eq RDF::URI('http://example.org/AnotherClass')
500
+ end
501
+ end
502
+ end
503
+
504
+ describe '#rdf_label' do
505
+ subject {LD4L::OpenAnnotationRDF::SemanticTagAnnotation.new("123")}
506
+
507
+ it 'should return an array of label values' do
508
+ expect(subject.rdf_label).to be_kind_of Array
509
+ end
510
+
511
+ it 'should return the default label as URI when no title property exists' do
512
+ expect(subject.rdf_label).to eq [RDF::URI("#{LD4L::OpenAnnotationRDF::SemanticTagAnnotation.base_uri}123")]
513
+ end
514
+
515
+ it 'should prioritize configured label values' do
516
+ custom_label = RDF::URI('http://example.org/custom_label')
517
+ subject.class.configure :rdf_label => custom_label
518
+ subject << RDF::Statement(subject.rdf_subject, custom_label, RDF::Literal('New Label'))
519
+ expect(subject.rdf_label).to eq ['New Label']
520
+ end
521
+ end
522
+
523
+ describe '#solrize' do
524
+ it 'should return a label for bnodes' do
525
+ expect(subject.solrize).to eq subject.rdf_label
526
+ end
527
+
528
+ it 'should return a string of the resource uri' do
529
+ subject.set_subject! 'http://example.org/moomin'
530
+ expect(subject.solrize).to eq 'http://example.org/moomin'
531
+ end
532
+ end
533
+
534
+ describe 'editing the graph' do
535
+ it 'should write properties when statements are added' do
536
+ subject << RDF::Statement.new(subject.rdf_subject, RDFVocabularies::OA.motivatedBy, 'commenting')
537
+ expect(subject.motivatedBy).to include 'commenting'
538
+ end
539
+
540
+ it 'should delete properties when statements are removed' do
541
+ subject << RDF::Statement.new(subject.rdf_subject, RDFVocabularies::OA.annotatedBy, 'John Smith')
542
+ subject.delete RDF::Statement.new(subject.rdf_subject, RDFVocabularies::OA.annotatedBy, 'John Smith')
543
+ expect(subject.annotatedBy).to eq []
544
+ end
545
+ end
546
+
547
+ describe 'big complex graphs' do
548
+ before do
549
+ class DummyPerson < ActiveTriples::Resource
550
+ configure :type => RDF::URI('http://example.org/Person')
551
+ property :foafname, :predicate => RDF::FOAF.name
552
+ property :publications, :predicate => RDF::FOAF.publications, :class_name => 'DummyDocument'
553
+ property :knows, :predicate => RDF::FOAF.knows, :class_name => DummyPerson
554
+ end
555
+
556
+ class DummyDocument < ActiveTriples::Resource
557
+ configure :type => RDF::URI('http://example.org/Document')
558
+ property :title, :predicate => RDF::DC.title
559
+ property :creator, :predicate => RDF::DC.creator, :class_name => 'DummyPerson'
560
+ end
561
+
562
+ LD4L::OpenAnnotationRDF::SemanticTagAnnotation.property :item, :predicate => RDF::DC.relation, :class_name => DummyDocument
563
+ end
564
+
565
+ subject { LD4L::OpenAnnotationRDF::SemanticTagAnnotation.new }
566
+
567
+ let (:document1) do
568
+ d = DummyDocument.new
569
+ d.title = 'Document One'
570
+ d
571
+ end
572
+
573
+ let (:document2) do
574
+ d = DummyDocument.new
575
+ d.title = 'Document Two'
576
+ d
577
+ end
578
+
579
+ let (:person1) do
580
+ p = DummyPerson.new
581
+ p.foafname = 'Alice'
582
+ p
583
+ end
584
+
585
+ let (:person2) do
586
+ p = DummyPerson.new
587
+ p.foafname = 'Bob'
588
+ p
589
+ end
590
+
591
+ let (:data) { <<END
592
+ _:1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/SomeClass> .
593
+ _:1 <http://purl.org/dc/terms/relation> _:2 .
594
+ _:2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Document> .
595
+ _:2 <http://purl.org/dc/terms/title> "Document One" .
596
+ _:2 <http://purl.org/dc/terms/creator> _:3 .
597
+ _:2 <http://purl.org/dc/terms/creator> _:4 .
598
+ _:4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Person> .
599
+ _:4 <http://xmlns.com/foaf/0.1/name> "Bob" .
600
+ _:3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Person> .
601
+ _:3 <http://xmlns.com/foaf/0.1/name> "Alice" .
602
+ _:3 <http://xmlns.com/foaf/0.1/knows> _:4 ."
603
+ END
604
+ }
605
+
606
+ after do
607
+ Object.send(:remove_const, "DummyDocument")
608
+ Object.send(:remove_const, "DummyPerson")
609
+ end
610
+
611
+ it 'should allow access to deep nodes' do
612
+ document1.creator = [person1, person2]
613
+ document2.creator = person1
614
+ person1.knows = person2
615
+ subject.item = [document1]
616
+ expect(subject.item.first.creator.first.knows.first.foafname).to eq ['Bob']
617
+ end
618
+ end
619
+ end