ld4l-open_annotation_rdf 0.0.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 (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