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