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,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