ld4l-ore_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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +25 -0
- data/.travis.yml +12 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +14 -0
- data/README.md +171 -0
- data/Rakefile +2 -0
- data/ld4l-ore_rdf.gemspec +45 -0
- data/lib/ld4l/ore_rdf/configuration.rb +41 -0
- data/lib/ld4l/ore_rdf/models/aggregation.rb +50 -0
- data/lib/ld4l/ore_rdf/models/aggregation_resource.rb +98 -0
- data/lib/ld4l/ore_rdf/models/proxy_resource.rb +54 -0
- data/lib/ld4l/ore_rdf/services/aggregation/add_aggregated_resource.rb +49 -0
- data/lib/ld4l/ore_rdf/services/aggregation/add_aggregated_resources.rb +28 -0
- data/lib/ld4l/ore_rdf/services/aggregation/create.rb +39 -0
- data/lib/ld4l/ore_rdf/services/aggregation/destroy.rb +47 -0
- data/lib/ld4l/ore_rdf/services/aggregation/destroy_with_id.rb +22 -0
- data/lib/ld4l/ore_rdf/services/aggregation/find.rb +72 -0
- data/lib/ld4l/ore_rdf/services/aggregation/persist.rb +34 -0
- data/lib/ld4l/ore_rdf/services/aggregation/resume.rb +30 -0
- data/lib/ld4l/ore_rdf/services/proxy/create.rb +64 -0
- data/lib/ld4l/ore_rdf/services/proxy/find.rb +93 -0
- data/lib/ld4l/ore_rdf/version.rb +5 -0
- data/lib/ld4l/ore_rdf/vocab/co.rb +27 -0
- data/lib/ld4l/ore_rdf/vocab/dcterms.rb +6 -0
- data/lib/ld4l/ore_rdf/vocab/iana.rb +9 -0
- data/lib/ld4l/ore_rdf/vocab/ore.rb +16 -0
- data/lib/ld4l/ore_rdf.rb +76 -0
- data/spec/ld4l/ore_rdf/configuration_spec.rb +174 -0
- data/spec/ld4l/ore_rdf/models/aggregation_resource_spec.rb +830 -0
- data/spec/ld4l/ore_rdf/models/aggregation_spec.rb +9 -0
- data/spec/ld4l/ore_rdf/models/proxy_resource_spec.rb +690 -0
- data/spec/ld4l/ore_rdf/services/aggregation/add_aggregated_resource_spec.rb +36 -0
- data/spec/ld4l/ore_rdf/services/aggregation/add_aggregated_resources_spec.rb +78 -0
- data/spec/ld4l/ore_rdf/services/aggregation/create_spec.rb +62 -0
- data/spec/ld4l/ore_rdf/services/aggregation/destroy_spec.rb +169 -0
- data/spec/ld4l/ore_rdf/services/aggregation/find_spec.rb +198 -0
- data/spec/ld4l/ore_rdf/services/aggregation/persist_spec.rb +13 -0
- data/spec/ld4l/ore_rdf/services/aggregation/resume_spec.rb +46 -0
- data/spec/ld4l/ore_rdf/services/proxy/create_spec.rb +143 -0
- data/spec/ld4l/ore_rdf/services/proxy/find_spec.rb +138 -0
- data/spec/ld4l/ore_rdf_spec.rb +53 -0
- data/spec/spec_helper.rb +23 -0
- metadata +259 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
module LD4L
|
2
|
+
module OreRDF
|
3
|
+
class FindProxies
|
4
|
+
|
5
|
+
##
|
6
|
+
# Find proxies matching the specified criteria.
|
7
|
+
#
|
8
|
+
# @param [Hash] options the options to use to find proxies
|
9
|
+
# @option options [String, RDF::URI, LD4L::OreRDF::AggregationResource] :aggregation - limit proxies found to this aggregation (required)
|
10
|
+
# @option options [Hash<Object,Object>] :criteria for finding proxies (ex. RDF::DC.proxy_in=>RDF::URI('http://example.org/ag123')) (default - nil for all proxies in the aggregation)
|
11
|
+
# @option options [Hash<Symbol><Object>] :properties to return with the proxy uri (ex. :proxy_for=>RDFVocabularies::ORE.proxyFor) (default - nil aggregation uri only)
|
12
|
+
# @option options [Symbol] :repository to search (default - :default)
|
13
|
+
# @option options [TrueClass,FalseClass] :resume if true, find and resume; otherwise, find only (default - false)
|
14
|
+
#
|
15
|
+
# @returns [Array<RDF::URI>,Hash<RDF::URI,LD4L::OreRDF::Proxy,Hash<RDF::URI,Hash<Object,Object>]
|
16
|
+
# if resume==false, returns URIs of matching proxy resources + specified properties' values;
|
17
|
+
# otherwise, returns resumed instances of matching proxies
|
18
|
+
#
|
19
|
+
# @example Search for all proxies in aggregation
|
20
|
+
# all_proxies = LD4L::OreRDF.FindProxies('http://example.org/aggregations/ag123')
|
21
|
+
#
|
22
|
+
# @example Search for all proxies in aggregation
|
23
|
+
# all_proxies = LD4L::OreRDF.FindProxies(RDF::URI('http://example.org/aggregations/ag123'))
|
24
|
+
#
|
25
|
+
# @example Search for all proxies in aggregation
|
26
|
+
# aggregation_resource = LD4L::OreRDF::AggregationResource.new('http://example.org/aggregations/ag123'))
|
27
|
+
# all_proxies = LD4L::OreRDF.FindProxies(aggregation_resource)
|
28
|
+
#
|
29
|
+
def self.call( options={} )
|
30
|
+
aggregation = options[:aggregation] || nil
|
31
|
+
raise ArgumentError, 'aggregation must be one of string uri, RDF::URI, LD4L::OreRDF::AggregationResource' unless
|
32
|
+
!aggregation.nil? && ( aggregation.kind_of?(String) ||
|
33
|
+
aggregation.kind_of?(RDF::URI) ||
|
34
|
+
aggregation.kind_of?(LD4L::OreRDF::AggregationResource) )
|
35
|
+
aggregation = RDF::URI(aggregation) if aggregation.kind_of?(String)
|
36
|
+
aggregation = aggregation.rdf_subject if aggregation.kind_of?(LD4L::OreRDF::AggregationResource)
|
37
|
+
# aggregation = aggregation.to_s if aggregation.kind_of?(RDF::URI)
|
38
|
+
# aggregation = aggregation.rdf_subject.to_s if aggregation.kind_of?(LD4L::OreRDF::AggregationResource)
|
39
|
+
|
40
|
+
repository = options[:repository] || :default
|
41
|
+
raise ArgumentError, 'repository must be a symbol' unless repository.kind_of?(Symbol)
|
42
|
+
raise ArgumentError, 'repository must be a registered repository' unless
|
43
|
+
ActiveTriples::Repositories.repositories.has_key?(repository)
|
44
|
+
|
45
|
+
resume = options[:resume] || false
|
46
|
+
raise ArgumentError, 'resume must be true or false' unless
|
47
|
+
resume.kind_of?(TrueClass) || resume.kind_of?(FalseClass)
|
48
|
+
|
49
|
+
criteria = options[:criteria] || nil
|
50
|
+
raise ArgumentError, 'criteria must be a hash of attribute-value pairs for searching for proxies' unless
|
51
|
+
criteria.nil? || criteria.kind_of?(Hash)
|
52
|
+
criteria = criteria ? criteria.dup : {}
|
53
|
+
criteria[RDF.type] = RDFVocabularies::ORE.Proxy
|
54
|
+
criteria[RDFVocabularies::ORE.proxyIn] = aggregation
|
55
|
+
|
56
|
+
# properties are ignored when resume==true because all properties are returned as part of the resumed proxies
|
57
|
+
properties = options[:properties] || nil
|
58
|
+
raise ArgumentError, 'properties must be an array of predicates' unless
|
59
|
+
properties.nil? || properties.kind_of?(Hash) || resume
|
60
|
+
properties.each_key { |k| criteria[properties[k]] = k unless criteria.has_key?(properties[k]) } unless
|
61
|
+
properties.nil? || resume
|
62
|
+
process_properties = properties.nil? || resume ? false : true
|
63
|
+
|
64
|
+
|
65
|
+
graph = ActiveTriples::Repositories.repositories[repository]
|
66
|
+
query = RDF::Query.new({ :proxy => criteria })
|
67
|
+
|
68
|
+
process_properties || resume ? proxies = {} : proxies = []
|
69
|
+
results = query.execute(graph)
|
70
|
+
results.each do |r|
|
71
|
+
h = r.to_hash
|
72
|
+
uri = h[:proxy]
|
73
|
+
if resume
|
74
|
+
# if resume, return Hash of proxy uri => resumed proxy for each found
|
75
|
+
proxies[uri] = LD4L::OreRDF::ProxyResource.new(uri)
|
76
|
+
elsif process_properties
|
77
|
+
# if properties, return Hash of proxy uri => Hash of property => value for each found
|
78
|
+
properties = h
|
79
|
+
properties.delete(:proxy)
|
80
|
+
proxies[uri] = properties
|
81
|
+
else
|
82
|
+
# if no properties && not resumed, return array of proxy uris
|
83
|
+
proxies << uri
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
proxies
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
module RDFVocabularies
|
3
|
+
class CO < RDF::Vocabulary("http://purl.org/co#")
|
4
|
+
|
5
|
+
# Class definitions
|
6
|
+
term :Set # used for unordered lists
|
7
|
+
term :List # used for ordered lists
|
8
|
+
term :Element # used for items in an unordered list
|
9
|
+
term :ListItem # used for items in an ordered list
|
10
|
+
|
11
|
+
# Property definitions for CO.Set and CO.List
|
12
|
+
property :size # xsd:nonNegativeInteger -- count of all Elements/ListItems in this list
|
13
|
+
property :item # URI of each ListItem in this List
|
14
|
+
|
15
|
+
# Property definitions for CO.List
|
16
|
+
property :firstItem # URI to first ListItem in an ordered list
|
17
|
+
property :lastItem # URI to last ListItem in an ordered list
|
18
|
+
|
19
|
+
# Property definitions for CO.Element and CO.ListItem
|
20
|
+
property :itemContent # URI to any content
|
21
|
+
|
22
|
+
# Property definitions for CO.ListItem
|
23
|
+
property :index # xsd:positiveInteger -- index of each ListItem starting at 1 counting up
|
24
|
+
property :nextItem # URI to a ListItem
|
25
|
+
property :previousItem # URI to a ListItem
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# require 'rdf'
|
2
|
+
module RDFVocabularies
|
3
|
+
class IANA < RDF::Vocabulary("http://www.iana.org/assignments/relation/")
|
4
|
+
property :first # URI of first item - An IRI that refers to the furthest preceding resource in a series of resources.
|
5
|
+
property :last # URI of last item - An IRI that refers to the furthest following resource in a series of resources.
|
6
|
+
property :next # URI of next item - Indicates that the link's context is a part of a series, and that the next in the series is the link target.
|
7
|
+
property :prev # URI of previous item - Indicates that the link's context is a part of a series, and that the previous in the series is the link target.
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
module RDFVocabularies
|
3
|
+
class ORE < RDF::Vocabulary("http://www.openarchives.org/ore/terms/")
|
4
|
+
|
5
|
+
# Class definitions
|
6
|
+
term :Aggregation
|
7
|
+
term :Proxy
|
8
|
+
|
9
|
+
# Property definitions ORE.Aggregation
|
10
|
+
property :aggregates # URI of each list item in this Aggregation
|
11
|
+
|
12
|
+
# Property definitions for ORE.Proxy
|
13
|
+
property :proxyFor # URI of list item
|
14
|
+
property :proxyIn # URI of aggregating list
|
15
|
+
end
|
16
|
+
end
|
data/lib/ld4l/ore_rdf.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
require 'active_triples'
|
3
|
+
require 'active_triples/local_name'
|
4
|
+
require 'linkeddata'
|
5
|
+
require 'doubly_linked_list'
|
6
|
+
require 'ld4l/foaf_rdf'
|
7
|
+
require 'ld4l/ore_rdf/version'
|
8
|
+
require 'ld4l/ore_rdf/vocab/ore'
|
9
|
+
require 'ld4l/ore_rdf/vocab/iana'
|
10
|
+
require 'ld4l/ore_rdf/vocab/dcterms'
|
11
|
+
|
12
|
+
module LD4L
|
13
|
+
module OreRDF
|
14
|
+
|
15
|
+
# Methods for configuring the GEM
|
16
|
+
class << self
|
17
|
+
attr_accessor :configuration
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.configuration
|
21
|
+
@configuration ||= Configuration.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.reset
|
25
|
+
@configuration = Configuration.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.configure
|
29
|
+
yield(configuration)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# RDF vocabularies
|
34
|
+
autoload :DCTERMS, 'ld4l/ore_rdf/vocab/dcterms'
|
35
|
+
autoload :IANA, 'ld4l/ore_rdf/vocab/iana'
|
36
|
+
autoload :ORE, 'ld4l/ore_rdf/vocab/ore'
|
37
|
+
|
38
|
+
|
39
|
+
# autoload classes
|
40
|
+
autoload :Configuration, 'ld4l/ore_rdf/configuration'
|
41
|
+
|
42
|
+
# autoload model classes
|
43
|
+
autoload :Aggregation, 'ld4l/ore_rdf/models/aggregation'
|
44
|
+
autoload :AggregationResource, 'ld4l/ore_rdf/models/aggregation_resource'
|
45
|
+
autoload :ProxyResource, 'ld4l/ore_rdf/models/proxy_resource'
|
46
|
+
|
47
|
+
# autoload service classes
|
48
|
+
autoload :CreateAggregation, 'ld4l/ore_rdf/services/aggregation/create'
|
49
|
+
autoload :PersistAggregation, 'ld4l/ore_rdf/services/aggregation/persist'
|
50
|
+
autoload :ResumeAggregation, 'ld4l/ore_rdf/services/aggregation/resume'
|
51
|
+
autoload :DestroyAggregation, 'ld4l/ore_rdf/services/aggregation/destroy'
|
52
|
+
autoload :FindAggregations, 'ld4l/ore_rdf/services/aggregation/find'
|
53
|
+
autoload :AddAggregatedResource, 'ld4l/ore_rdf/services/aggregation/add_aggregated_resource'
|
54
|
+
autoload :AddAggregatedResources, 'ld4l/ore_rdf/services/aggregation/add_aggregated_resources'
|
55
|
+
|
56
|
+
autoload :CreateProxy, 'ld4l/ore_rdf/services/proxy/create'
|
57
|
+
autoload :FindProxies, 'ld4l/ore_rdf/services/proxy/find'
|
58
|
+
|
59
|
+
def self.class_from_string(class_name, container_class=Kernel)
|
60
|
+
container_class = container_class.name if container_class.is_a? Module
|
61
|
+
container_parts = container_class.split('::')
|
62
|
+
(container_parts + class_name.split('::')).flatten.inject(Kernel) do |mod, class_name|
|
63
|
+
if mod == Kernel
|
64
|
+
Object.const_get(class_name)
|
65
|
+
elsif mod.const_defined? class_name.to_sym
|
66
|
+
mod.const_get(class_name)
|
67
|
+
else
|
68
|
+
container_parts.pop
|
69
|
+
class_from_string(class_name, container_parts.join('::'))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'LD4L::OreRDF' do
|
4
|
+
|
5
|
+
describe '#configuration' do
|
6
|
+
describe "base_uri" do
|
7
|
+
context "when base_uri is not configured" do
|
8
|
+
before do
|
9
|
+
class DummyAggregation < LD4L::OreRDF::AggregationResource
|
10
|
+
configure :type => RDFVocabularies::ORE.Aggregation, :base_uri => LD4L::OreRDF.configuration.base_uri, :repository => :default
|
11
|
+
end
|
12
|
+
end
|
13
|
+
after do
|
14
|
+
Object.send(:remove_const, "DummyAggregation") if Object
|
15
|
+
end
|
16
|
+
it "should generate an Aggregation URI using the default base_uri" do
|
17
|
+
expect(DummyAggregation.new('1').rdf_subject.to_s).to eq "http://localhost/1"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when uri ends with slash" do
|
22
|
+
before do
|
23
|
+
LD4L::OreRDF.configure do |config|
|
24
|
+
config.base_uri = "http://localhost/test_slash/"
|
25
|
+
end
|
26
|
+
class DummyAggregation < LD4L::OreRDF::AggregationResource
|
27
|
+
configure :type => RDFVocabularies::ORE.Aggregation, :base_uri => LD4L::OreRDF.configuration.base_uri, :repository => :default
|
28
|
+
end
|
29
|
+
end
|
30
|
+
after do
|
31
|
+
Object.send(:remove_const, "DummyAggregation") if Object
|
32
|
+
LD4L::OreRDF.reset
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should generate an Aggregation URI using the configured base_uri" do
|
36
|
+
expect(DummyAggregation.new('1').rdf_subject.to_s).to eq "http://localhost/test_slash/1"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when uri does not end with slash" do
|
41
|
+
before do
|
42
|
+
LD4L::OreRDF.configure do |config|
|
43
|
+
config.base_uri = "http://localhost/test_no_slash"
|
44
|
+
end
|
45
|
+
class DummyAggregation < LD4L::OreRDF::AggregationResource
|
46
|
+
configure :type => RDFVocabularies::ORE.Aggregation, :base_uri => LD4L::OreRDF.configuration.base_uri, :repository => :default
|
47
|
+
end
|
48
|
+
end
|
49
|
+
after do
|
50
|
+
Object.send(:remove_const, "DummyAggregation") if Object
|
51
|
+
LD4L::OreRDF.reset
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should generate an Aggregation URI using the configured base_uri" do
|
55
|
+
expect(DummyAggregation.new('1').rdf_subject.to_s).to eq "http://localhost/test_no_slash/1"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should return value of configured base_uri" do
|
60
|
+
LD4L::OreRDF.configure do |config|
|
61
|
+
config.base_uri = "http://localhost/test_config/"
|
62
|
+
end
|
63
|
+
expect(LD4L::OreRDF.configuration.base_uri).to eq "http://localhost/test_config/"
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should return default base_uri when base_uri is reset" do
|
67
|
+
LD4L::OreRDF.configure do |config|
|
68
|
+
config.base_uri = "http://localhost/test_config/"
|
69
|
+
end
|
70
|
+
expect(LD4L::OreRDF.configuration.base_uri).to eq "http://localhost/test_config/"
|
71
|
+
LD4L::OreRDF.configuration.reset_base_uri
|
72
|
+
expect(LD4L::OreRDF.configuration.base_uri).to eq "http://localhost/"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should return default base_uri when all configs are reset" do
|
76
|
+
LD4L::OreRDF.configure do |config|
|
77
|
+
config.base_uri = "http://localhost/test_config/"
|
78
|
+
end
|
79
|
+
expect(LD4L::OreRDF.configuration.base_uri).to eq "http://localhost/test_config/"
|
80
|
+
LD4L::OreRDF.reset
|
81
|
+
expect(LD4L::OreRDF.configuration.base_uri).to eq "http://localhost/"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "localname_minter" do
|
86
|
+
context "when minter is nil" do
|
87
|
+
before do
|
88
|
+
class DummyAggregation < LD4L::OreRDF::AggregationResource
|
89
|
+
configure :type => RDFVocabularies::ORE.Aggregation, :base_uri => LD4L::OreRDF.configuration.base_uri, :repository => :default
|
90
|
+
end
|
91
|
+
end
|
92
|
+
after do
|
93
|
+
Object.send(:remove_const, "DummyAggregation") if Object
|
94
|
+
end
|
95
|
+
it "should use default minter in minter gem" do
|
96
|
+
localname = ActiveTriples::LocalName::Minter.generate_local_name(
|
97
|
+
LD4L::OreRDF::AggregationResource, 10, {:prefix=>'default_'},
|
98
|
+
LD4L::OreRDF.configuration.localname_minter )
|
99
|
+
expect(localname).to be_kind_of String
|
100
|
+
expect(localname.size).to eq 44
|
101
|
+
expect(localname).to match /default_[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}/
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "when minter is configured" do
|
106
|
+
before do
|
107
|
+
LD4L::OreRDF.configure do |config|
|
108
|
+
config.localname_minter = lambda { |prefix=""| prefix+'_configured_'+SecureRandom.uuid }
|
109
|
+
end
|
110
|
+
class DummyAggregation < LD4L::OreRDF::AggregationResource
|
111
|
+
configure :type => RDFVocabularies::ORE.Aggregation, :base_uri => LD4L::OreRDF.configuration.base_uri, :repository => :default
|
112
|
+
end
|
113
|
+
end
|
114
|
+
after do
|
115
|
+
Object.send(:remove_const, "DummyAggregation") if Object
|
116
|
+
LD4L::OreRDF.reset
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should generate an Aggregation URI using the configured localname_minter" do
|
120
|
+
localname = ActiveTriples::LocalName::Minter.generate_local_name(
|
121
|
+
LD4L::OreRDF::AggregationResource, 10,
|
122
|
+
LD4L::OreRDF::AggregationResource.localname_prefix,
|
123
|
+
&LD4L::OreRDF.configuration.localname_minter )
|
124
|
+
expect(localname).to be_kind_of String
|
125
|
+
expect(localname.size).to eq 50
|
126
|
+
expect(localname).to match /ag_configured_[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}/
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
describe "LD4L::OreRDF::Configuration" do
|
134
|
+
describe "#base_uri" do
|
135
|
+
it "should default to localhost" do
|
136
|
+
expect(LD4L::OreRDF::Configuration.new.base_uri).to eq "http://localhost/"
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should be settable" do
|
140
|
+
config = LD4L::OreRDF::Configuration.new
|
141
|
+
config.base_uri = "http://localhost/test"
|
142
|
+
expect(config.base_uri).to eq "http://localhost/test"
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should be re-settable" do
|
146
|
+
config = LD4L::OreRDF::Configuration.new
|
147
|
+
config.base_uri = "http://localhost/test/again"
|
148
|
+
expect(config.base_uri).to eq "http://localhost/test/again"
|
149
|
+
config.reset_base_uri
|
150
|
+
expect(config.base_uri).to eq "http://localhost/"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "#localname_minter" do
|
155
|
+
it "should default to nil" do
|
156
|
+
expect(LD4L::OreRDF::Configuration.new.localname_minter).to eq nil
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should be settable" do
|
160
|
+
config = LD4L::OreRDF::Configuration.new
|
161
|
+
config.localname_minter = lambda { |prefix=""| prefix+'_configured_'+SecureRandom.uuid }
|
162
|
+
expect(config.localname_minter).to be_kind_of Proc
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should be re-settable" do
|
166
|
+
config = LD4L::OreRDF::Configuration.new
|
167
|
+
config.localname_minter = lambda { |prefix=""| prefix+'_configured_'+SecureRandom.uuid }
|
168
|
+
expect(config.localname_minter).to be_kind_of Proc
|
169
|
+
config.reset_localname_minter
|
170
|
+
expect(config.localname_minter).to eq nil
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,830 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'LD4L::OreRDF::AggregationResource' do
|
4
|
+
|
5
|
+
subject { LD4L::OreRDF::AggregationResource.new } # new virtual collection without a subject
|
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::OreRDF::AggregationResource.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
|
+
it 'should update graph subjects' do
|
31
|
+
expect(subject.has_statement?(RDF::Statement.new(subject.rdf_subject, RDF::DC.title, RDF::Literal('Comet in Moominland')))).to be true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should update graph objects' do
|
35
|
+
expect(subject.has_statement?(RDF::Statement.new(RDF::URI('http://example.org/moomin_comics'), RDF::DC.isPartOf, subject.rdf_subject))).to be true
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should leave other uris alone' do
|
39
|
+
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
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'created with URI subject' do
|
44
|
+
before do
|
45
|
+
subject.set_subject! RDF::URI('http://example.org/moomin')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should not be settable' do
|
49
|
+
expect{ subject.set_subject! RDF::URI('http://example.org/moomin2') }.to raise_error
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# -------------------------------------------------
|
56
|
+
# START -- Test attributes specific to this model
|
57
|
+
# -------------------------------------------------
|
58
|
+
|
59
|
+
describe 'type' do
|
60
|
+
it "should be an ORE.Aggregation" do
|
61
|
+
expect(subject.type.first.value).to eq RDFVocabularies::ORE.Aggregation.value
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'title' do
|
66
|
+
it "should be empty array if we haven't set it" do
|
67
|
+
expect(subject.title).to match_array([])
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should be settable" do
|
71
|
+
subject.title = "Test Title"
|
72
|
+
expect(subject.title).to eq ["Test Title"]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should be changeable" do
|
76
|
+
subject.title = "Test Title"
|
77
|
+
subject.title = "New Title"
|
78
|
+
expect(subject.title).to eq ["New Title"]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'description' do
|
83
|
+
it "should be empty array if we haven't set it" do
|
84
|
+
expect(subject.description).to match_array([])
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should be settable" do
|
88
|
+
subject.description = "Test Description"
|
89
|
+
expect(subject.description).to eq ["Test Description"]
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should be changeable" do
|
93
|
+
subject.description = "Test Description"
|
94
|
+
subject.description = "New Description"
|
95
|
+
expect(subject.description).to eq ["New Description"]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'owner' do
|
100
|
+
it "should be empty array if we haven't set it" do
|
101
|
+
expect(subject.owner).to match_array([])
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should be settable" do
|
105
|
+
a_person = LD4L::FoafRDF::Person.new('1')
|
106
|
+
subject.owner = a_person
|
107
|
+
expect(subject.owner.first.rdf_subject).to eq a_person.rdf_subject
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should be changeable" do
|
111
|
+
orig_person = LD4L::FoafRDF::Person.new('1')
|
112
|
+
new_person = LD4L::FoafRDF::Person.new('2')
|
113
|
+
subject.owner = orig_person
|
114
|
+
subject.owner = new_person
|
115
|
+
expect(subject.owner.first.rdf_subject).to eq new_person.rdf_subject
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'aggregates' do
|
120
|
+
it "should be empty array if we haven't set it" do
|
121
|
+
expect(subject.aggregates).to match_array([])
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should be set to a URI producing an ActiveTriple::Resource" do
|
125
|
+
subject.aggregates = RDF::URI("http://example.org/individual/b1")
|
126
|
+
expect(subject.aggregates.first).to be_a ActiveTriples::Resource
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should be settable" do
|
130
|
+
subject.aggregates = RDF::URI("http://example.org/individual/b1")
|
131
|
+
expect(subject.aggregates.first.rdf_subject).to eq RDF::URI("http://example.org/individual/b1")
|
132
|
+
['id']
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should be settable to multiple values" do
|
136
|
+
bib1 = RDF::URI("http://example.org/individual/b1")
|
137
|
+
bib2 = RDF::URI("http://example.org/individual/b2")
|
138
|
+
bib3 = RDF::URI("http://example.org/individual/b3")
|
139
|
+
subject.aggregates = bib1
|
140
|
+
subject.aggregates << bib2
|
141
|
+
subject.aggregates << bib3
|
142
|
+
expect(subject.aggregates[0].rdf_subject).to eq bib1
|
143
|
+
expect(subject.aggregates[1].rdf_subject).to eq bib2
|
144
|
+
expect(subject.aggregates[2].rdf_subject).to eq bib3
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should be changeable" do
|
148
|
+
orig_bib = RDF::URI("http://example.org/individual/b1")
|
149
|
+
new_bib = RDF::URI("http://example.org/individual/b1_NEW")
|
150
|
+
subject.aggregates = orig_bib
|
151
|
+
subject.aggregates = new_bib
|
152
|
+
expect(subject.aggregates.first.rdf_subject).to eq new_bib
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should be changeable for multiple values" do
|
156
|
+
orig_bib1 = RDF::URI("http://example.org/individual/b1")
|
157
|
+
orig_bib2 = RDF::URI("http://example.org/individual/b2")
|
158
|
+
orig_bib3 = RDF::URI("http://example.org/individual/b3")
|
159
|
+
|
160
|
+
new_bib1 = RDF::URI("http://example.org/individual/b1_NEW")
|
161
|
+
new_bib2 = RDF::URI("http://example.org/individual/b2_NEW")
|
162
|
+
new_bib3 = RDF::URI("http://example.org/individual/b3_NEW")
|
163
|
+
|
164
|
+
subject.aggregates = orig_bib1
|
165
|
+
subject.aggregates << orig_bib2
|
166
|
+
subject.aggregates << orig_bib3
|
167
|
+
|
168
|
+
aggregates = subject.aggregates.dup
|
169
|
+
aggregates[0] = new_bib1
|
170
|
+
# aggregates[1] = new_bib2
|
171
|
+
aggregates[2] = new_bib3
|
172
|
+
subject.aggregates = aggregates
|
173
|
+
|
174
|
+
expect(subject.aggregates[0].rdf_subject).to eq new_bib1
|
175
|
+
# expect(subject.aggregates[1].rdf_subject).to eq new_bib2
|
176
|
+
expect(subject.aggregates[1].rdf_subject).to eq orig_bib2
|
177
|
+
expect(subject.aggregates[2].rdf_subject).to eq new_bib3
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should be directly changeable for multiple values" do
|
181
|
+
orig_bib1 = RDF::URI("http://example.org/individual/b1")
|
182
|
+
orig_bib2 = RDF::URI("http://example.org/individual/b2")
|
183
|
+
orig_bib3 = RDF::URI("http://example.org/individual/b3")
|
184
|
+
|
185
|
+
new_bib1 = RDF::URI("http://example.org/individual/b1_NEW")
|
186
|
+
new_bib2 = RDF::URI("http://example.org/individual/b2_NEW")
|
187
|
+
new_bib3 = RDF::URI("http://example.org/individual/b3_NEW")
|
188
|
+
|
189
|
+
subject.aggregates = orig_bib1
|
190
|
+
subject.aggregates << orig_bib2
|
191
|
+
subject.aggregates << orig_bib3
|
192
|
+
|
193
|
+
subject.aggregates[0] = new_bib1
|
194
|
+
# subject.aggregates[1] = new_bib2
|
195
|
+
subject.aggregates[2] = new_bib3
|
196
|
+
|
197
|
+
expect(subject.aggregates[0].rdf_subject).to eq new_bib1
|
198
|
+
# expect(subject.aggregates[1].rdf_subject).to eq new_bib2
|
199
|
+
expect(subject.aggregates[1].rdf_subject).to eq orig_bib2
|
200
|
+
expect(subject.aggregates[2].rdf_subject).to eq new_bib3
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# -----------------------------------------------
|
205
|
+
# END -- Test attributes specific to this model
|
206
|
+
# -----------------------------------------------
|
207
|
+
|
208
|
+
|
209
|
+
# -----------------------------------------------------
|
210
|
+
# START -- Test helper methods specific to this model
|
211
|
+
# -----------------------------------------------------
|
212
|
+
|
213
|
+
|
214
|
+
########### NEED TO MOVE TO SERVICE OBJECT ####################
|
215
|
+
|
216
|
+
|
217
|
+
describe "#get_items_content" do
|
218
|
+
context "when collection has 0 items" do
|
219
|
+
before do
|
220
|
+
subject.aggregates = []
|
221
|
+
end
|
222
|
+
it "should return empty array when no items exist" do
|
223
|
+
subject.aggregates = []
|
224
|
+
content_array = subject.get_items_content
|
225
|
+
expect(content_array).to eq []
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "when collection has items" do
|
230
|
+
xit "should return array" do
|
231
|
+
|
232
|
+
|
233
|
+
### TODO need to update add_items_with_content to use new service
|
234
|
+
|
235
|
+
|
236
|
+
# subject.add_items_with_content([RDF::URI("http://example.org/individual/b1"),
|
237
|
+
# RDF::URI("http://example.org/individual/b2"),
|
238
|
+
# RDF::URI("http://example.org/individual/b3")])
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
content_array = subject.get_items_content
|
244
|
+
expect(content_array).to be_a(Array)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context "when start and limit are not specified" do
|
249
|
+
xit "should return array of all content aggregated by subject" do
|
250
|
+
|
251
|
+
|
252
|
+
### TODO need to update add_items_with_content to use new service
|
253
|
+
|
254
|
+
|
255
|
+
# subject.add_items_with_content([RDF::URI("http://example.org/individual/b1"),
|
256
|
+
# RDF::URI("http://example.org/individual/b2"),
|
257
|
+
# RDF::URI("http://example.org/individual/b3")])
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
content_array = subject.get_items_content
|
263
|
+
expect(content_array).to include ActiveTriples::Resource.new(RDF::URI("http://example.org/individual/b1"))
|
264
|
+
expect(content_array).to include ActiveTriples::Resource.new(RDF::URI("http://example.org/individual/b2"))
|
265
|
+
expect(content_array).to include ActiveTriples::Resource.new(RDF::URI("http://example.org/individual/b3"))
|
266
|
+
end
|
267
|
+
|
268
|
+
xit "should not return any content not aggregated by subject" do
|
269
|
+
vc = LD4L::OreRDF::AggregationResource.new('999')
|
270
|
+
|
271
|
+
|
272
|
+
### TODO need to update add_items_with_content to use new service
|
273
|
+
|
274
|
+
|
275
|
+
# vc.add_item_with_content(RDF::URI("http://example.org/individual/b999"))
|
276
|
+
#
|
277
|
+
# subject.add_items_with_content([RDF::URI("http://example.org/individual/b1"),
|
278
|
+
# RDF::URI("http://example.org/individual/b2"),
|
279
|
+
# RDF::URI("http://example.org/individual/b3")])
|
280
|
+
|
281
|
+
|
282
|
+
|
283
|
+
content_array = subject.get_items_content
|
284
|
+
expect(content_array).to include ActiveTriples::Resource.new(RDF::URI("http://example.org/individual/b1"))
|
285
|
+
expect(content_array).to include ActiveTriples::Resource.new(RDF::URI("http://example.org/individual/b2"))
|
286
|
+
expect(content_array).to include ActiveTriples::Resource.new(RDF::URI("http://example.org/individual/b3"))
|
287
|
+
expect(content_array.size).to eq 3
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
context "when limit is specified" do
|
292
|
+
xit "should return array of content with max size=limit" do
|
293
|
+
pending "this needs to be implemented"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context "when start is specified" do
|
298
|
+
xit "should return array of content_beginning with item at position=start" do
|
299
|
+
# TODO: What does _start_ mean in ActiveTriples? Does it support this kind of query?
|
300
|
+
pending "this needs to be implemented"
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
context "when start and limit are specified" do
|
305
|
+
xit "should return an array of content with max size=limit beginning with item at position=start" do
|
306
|
+
pending "this needs to be implemented"
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "#get_items" do
|
312
|
+
context "when collection has 0 items" do
|
313
|
+
before do
|
314
|
+
subject.aggregates = []
|
315
|
+
end
|
316
|
+
|
317
|
+
it "should return empty array when no items exist" do
|
318
|
+
vci_array = subject.get_items
|
319
|
+
expect(vci_array).to eq []
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
context "when collection has items" do
|
324
|
+
before do
|
325
|
+
|
326
|
+
|
327
|
+
### TODO need to update add_items_with_content to use new service
|
328
|
+
|
329
|
+
|
330
|
+
# subject.add_items_with_content([RDF::URI("http://example.org/individual/b1"),
|
331
|
+
# RDF::URI("http://example.org/individual/b2"),
|
332
|
+
# RDF::URI("http://example.org/individual/b3")])
|
333
|
+
end
|
334
|
+
|
335
|
+
xit "should return array" do
|
336
|
+
vci_array = subject.get_items
|
337
|
+
expect(vci_array).to be_a(Array)
|
338
|
+
end
|
339
|
+
|
340
|
+
xit "should return array of LD4L::OreRDF::ProxyResource instances" do
|
341
|
+
vci_array = subject.get_items
|
342
|
+
vci_array.each do |vci|
|
343
|
+
expect(vci).to be_a(LD4L::OreRDF::ProxyResource)
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
context "when start and limit are not specified" do
|
349
|
+
context "and objects not persisted" do
|
350
|
+
xit "should return empty array" do
|
351
|
+
|
352
|
+
|
353
|
+
### TODO need to update add_items_with_content to use new service
|
354
|
+
|
355
|
+
|
356
|
+
# subject.add_items_with_content([RDF::URI("http://example.org/individual/b1"),
|
357
|
+
# RDF::URI("http://example.org/individual/b2"),
|
358
|
+
# RDF::URI("http://example.org/individual/b3")])
|
359
|
+
vci_array = subject.get_items
|
360
|
+
expect(vci_array.size).to eq(0)
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
context "and objects are persisted" do
|
365
|
+
xit "should return array of all LD4L::OreRDF::ProxyResource instances for content aggregated by subject" do
|
366
|
+
|
367
|
+
|
368
|
+
### TODO need to update add_items_with_content to use new service
|
369
|
+
|
370
|
+
|
371
|
+
# vci_array = subject.add_items_with_content([RDF::URI("http://example.org/individual/b1"),
|
372
|
+
# RDF::URI("http://example.org/individual/b2"),
|
373
|
+
# RDF::URI("http://example.org/individual/b3")])
|
374
|
+
subject.persist!
|
375
|
+
vci_array.each { |vci| vci.persist! }
|
376
|
+
|
377
|
+
vci_array = subject.get_items
|
378
|
+
vci_array.each do |vci|
|
379
|
+
expect(vci).to be_a(LD4L::OreRDF::ProxyResource)
|
380
|
+
expect(vci.proxy_in.first).to eq subject
|
381
|
+
end
|
382
|
+
results = []
|
383
|
+
vci_array.each { |vci| results << vci.proxy_for.first }
|
384
|
+
expect(results).to include ActiveTriples::Resource.new(RDF::URI("http://example.org/individual/b1"))
|
385
|
+
expect(results).to include ActiveTriples::Resource.new(RDF::URI("http://example.org/individual/b2"))
|
386
|
+
expect(results).to include ActiveTriples::Resource.new(RDF::URI("http://example.org/individual/b3"))
|
387
|
+
expect(vci_array.size).to eq(3)
|
388
|
+
end
|
389
|
+
|
390
|
+
xit "should not return any LD4L::OreRDF::ProxyResource instances for content not aggregated by subject" do
|
391
|
+
pending "this needs to be implemented"
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
context "when limit is specified" do
|
397
|
+
xit "should return array of LD4L::OreRDF::ProxyResource instances with max size=limit" do
|
398
|
+
pending "this needs to be implemented"
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
context "when start is specified" do
|
403
|
+
xit "should return array of LD4L::OreRDF::ProxyResource instances_beginning with item at position=start" do
|
404
|
+
# TODO: What does _start_ mean in ActiveTriples? Does it support this kind of query?
|
405
|
+
pending "this needs to be implemented"
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
context "when start and limit are specified" do
|
410
|
+
xit "should return an array of LD4L::OreRDF::ProxyResource instances with max size=limit beginning with item at position=start" do
|
411
|
+
pending "this needs to be implemented"
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
describe "#find_item_with_content" do
|
417
|
+
skip "this needs to be implemented"
|
418
|
+
end
|
419
|
+
|
420
|
+
describe "#get_item_content_at" do
|
421
|
+
skip "this needs to be implemented"
|
422
|
+
end
|
423
|
+
|
424
|
+
describe "#get_item_at" do
|
425
|
+
skip "this needs to be implemented"
|
426
|
+
end
|
427
|
+
|
428
|
+
describe "#has_item_at?" do
|
429
|
+
skip "this needs to be implemented"
|
430
|
+
end
|
431
|
+
|
432
|
+
describe "#has_item_content?" do
|
433
|
+
skip "this needs to be implemented"
|
434
|
+
end
|
435
|
+
|
436
|
+
describe "#remove_item_with_content" do
|
437
|
+
skip "this needs to be implemented"
|
438
|
+
end
|
439
|
+
|
440
|
+
describe "#is_ordered?" do
|
441
|
+
skip "this needs to be implemented"
|
442
|
+
end
|
443
|
+
|
444
|
+
# ---------------------------------------------------
|
445
|
+
# END -- Test helper methods specific to this model
|
446
|
+
# ---------------------------------------------------
|
447
|
+
|
448
|
+
|
449
|
+
describe "#persisted?" do
|
450
|
+
context 'with a repository' do
|
451
|
+
before do
|
452
|
+
# Create inmemory repository
|
453
|
+
repository = RDF::Repository.new
|
454
|
+
allow(subject).to receive(:repository).and_return(repository)
|
455
|
+
end
|
456
|
+
|
457
|
+
context "when the object is new" do
|
458
|
+
it "should return false" do
|
459
|
+
expect(subject).not_to be_persisted
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
context "when it is saved" do
|
464
|
+
before do
|
465
|
+
subject.title = "bla"
|
466
|
+
subject.persist!
|
467
|
+
end
|
468
|
+
|
469
|
+
it "should return true" do
|
470
|
+
expect(subject).to be_persisted
|
471
|
+
end
|
472
|
+
|
473
|
+
context "and then modified" do
|
474
|
+
before do
|
475
|
+
subject.title = "newbla"
|
476
|
+
end
|
477
|
+
|
478
|
+
it "should return true" do
|
479
|
+
expect(subject).to be_persisted
|
480
|
+
end
|
481
|
+
end
|
482
|
+
context "and then reloaded" do
|
483
|
+
before do
|
484
|
+
subject.reload
|
485
|
+
end
|
486
|
+
|
487
|
+
it "should reset the title" do
|
488
|
+
expect(subject.title).to eq ["bla"]
|
489
|
+
end
|
490
|
+
|
491
|
+
it "should be persisted" do
|
492
|
+
expect(subject).to be_persisted
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
describe "#persist!" do
|
500
|
+
context "when the repository is set" do
|
501
|
+
context "and the item is not a blank node" do
|
502
|
+
|
503
|
+
subject {LD4L::OreRDF::AggregationResource.new("123")}
|
504
|
+
|
505
|
+
before do
|
506
|
+
# Create inmemory repository
|
507
|
+
@repo = RDF::Repository.new
|
508
|
+
allow(subject.class).to receive(:repository).and_return(nil)
|
509
|
+
allow(subject).to receive(:repository).and_return(@repo)
|
510
|
+
subject.title = "bla"
|
511
|
+
subject.persist!
|
512
|
+
end
|
513
|
+
|
514
|
+
it "should persist to the repository" do
|
515
|
+
expect(@repo.statements.first).to eq subject.statements.first
|
516
|
+
end
|
517
|
+
|
518
|
+
it "should delete from the repository" do
|
519
|
+
subject.reload
|
520
|
+
expect(subject.title).to eq ["bla"]
|
521
|
+
subject.title = []
|
522
|
+
expect(subject.title).to eq []
|
523
|
+
subject.persist!
|
524
|
+
subject.reload
|
525
|
+
expect(subject.title).to eq []
|
526
|
+
expect(@repo.statements.to_a.length).to eq 1 # Only the type statement
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
describe '#destroy!' do
|
533
|
+
before do
|
534
|
+
subject << RDF::Statement(RDF::DC.LicenseDocument, RDF::DC.title, 'LICENSE')
|
535
|
+
end
|
536
|
+
|
537
|
+
subject { LD4L::FoafRDF::Person.new('456')}
|
538
|
+
|
539
|
+
it 'should return true' do
|
540
|
+
expect(subject.destroy!).to be true
|
541
|
+
expect(subject.destroy).to be true
|
542
|
+
end
|
543
|
+
|
544
|
+
it 'should delete the graph' do
|
545
|
+
subject.destroy
|
546
|
+
expect(subject).to be_empty
|
547
|
+
end
|
548
|
+
|
549
|
+
context 'with a parent' do
|
550
|
+
before do
|
551
|
+
parent.owner = subject
|
552
|
+
end
|
553
|
+
|
554
|
+
let(:parent) do
|
555
|
+
LD4L::OreRDF::AggregationResource.new('123')
|
556
|
+
end
|
557
|
+
|
558
|
+
it 'should empty the graph and remove it from the parent' do
|
559
|
+
subject.destroy
|
560
|
+
expect(parent.owner).to be_empty
|
561
|
+
end
|
562
|
+
|
563
|
+
it 'should remove its whole graph from the parent' do
|
564
|
+
subject.destroy
|
565
|
+
subject.each_statement do |s|
|
566
|
+
expect(parent.statements).not_to include s
|
567
|
+
end
|
568
|
+
end
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
describe 'attributes' do
|
573
|
+
before do
|
574
|
+
subject.owner = owner
|
575
|
+
subject.title = 'My Title'
|
576
|
+
end
|
577
|
+
|
578
|
+
subject {LD4L::OreRDF::AggregationResource.new("123")}
|
579
|
+
|
580
|
+
let(:owner) { LD4L::FoafRDF::Person.new('456') }
|
581
|
+
|
582
|
+
it 'should return an attributes hash' do
|
583
|
+
expect(subject.attributes).to be_a Hash
|
584
|
+
end
|
585
|
+
|
586
|
+
it 'should contain data' do
|
587
|
+
expect(subject.attributes['title']).to eq ['My Title']
|
588
|
+
end
|
589
|
+
|
590
|
+
it 'should contain child objects' do
|
591
|
+
expect(subject.attributes['owner']).to eq [owner]
|
592
|
+
end
|
593
|
+
|
594
|
+
context 'with unmodeled data' do
|
595
|
+
before do
|
596
|
+
subject << RDF::Statement(subject.rdf_subject, RDF::DC.contributor, 'Tove Jansson')
|
597
|
+
subject << RDF::Statement(subject.rdf_subject, RDF::DC.relation, RDF::URI('http://example.org/moomi'))
|
598
|
+
node = RDF::Node.new
|
599
|
+
subject << RDF::Statement(RDF::URI('http://example.org/moomi'), RDF::DC.relation, node)
|
600
|
+
subject << RDF::Statement(node, RDF::DC.title, 'bnode')
|
601
|
+
end
|
602
|
+
|
603
|
+
it 'should include data with URIs as attribute names' do
|
604
|
+
expect(subject.attributes[RDF::DC.contributor.to_s]).to eq ['Tove Jansson']
|
605
|
+
end
|
606
|
+
|
607
|
+
it 'should return generic Resources' do
|
608
|
+
expect(subject.attributes[RDF::DC.relation.to_s].first).to be_a ActiveTriples::Resource
|
609
|
+
end
|
610
|
+
|
611
|
+
it 'should build deep data for Resources' do
|
612
|
+
expect(subject.attributes[RDF::DC.relation.to_s].first.get_values(RDF::DC.relation).
|
613
|
+
first.get_values(RDF::DC.title)).to eq ['bnode']
|
614
|
+
end
|
615
|
+
|
616
|
+
it 'should include deep data in serializable_hash' do
|
617
|
+
expect(subject.serializable_hash[RDF::DC.relation.to_s].first.get_values(RDF::DC.relation).
|
618
|
+
first.get_values(RDF::DC.title)).to eq ['bnode']
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
622
|
+
describe 'attribute_serialization' do
|
623
|
+
describe '#to_json' do
|
624
|
+
it 'should return a string with correct objects' do
|
625
|
+
json_hash = JSON.parse(subject.to_json)
|
626
|
+
expect(json_hash['owner'].first['id']).to eq owner.rdf_subject.to_s
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
630
|
+
end
|
631
|
+
|
632
|
+
describe 'property methods' do
|
633
|
+
it 'should set and get properties' do
|
634
|
+
subject.title = 'Comet in Moominland'
|
635
|
+
expect(subject.title).to eq ['Comet in Moominland']
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
describe 'child nodes' do
|
640
|
+
it 'should return an object of the correct class when the value is built from the base URI' do
|
641
|
+
subject.owner = LD4L::FoafRDF::Person.new('456')
|
642
|
+
expect(subject.owner.first).to be_kind_of LD4L::FoafRDF::Person
|
643
|
+
end
|
644
|
+
|
645
|
+
it 'should return an object with the correct URI created with a URI' do
|
646
|
+
subject.owner = LD4L::FoafRDF::Person.new("http://vivo.cornell.edu/individual/JohnSmith")
|
647
|
+
expect(subject.owner.first.rdf_subject).to eq RDF::URI("http://vivo.cornell.edu/individual/JohnSmith")
|
648
|
+
end
|
649
|
+
|
650
|
+
it 'should return an object of the correct class when the value is a bnode' do
|
651
|
+
subject.owner = LD4L::FoafRDF::Person.new
|
652
|
+
expect(subject.owner.first).to be_kind_of LD4L::FoafRDF::Person
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
describe '#set_value' do
|
657
|
+
it 'should set a value in the graph' do
|
658
|
+
subject.set_value(RDF::DC.title, 'Comet in Moominland')
|
659
|
+
subject.query(:subject => subject.rdf_subject, :predicate => RDF::DC.title).each_statement do |s|
|
660
|
+
expect(s.object.to_s).to eq 'Comet in Moominland'
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
664
|
+
it 'should set a value in the when given a registered property symbol' do
|
665
|
+
subject.set_value(:title, 'Comet in Moominland')
|
666
|
+
expect(subject.title).to eq ['Comet in Moominland']
|
667
|
+
end
|
668
|
+
|
669
|
+
it "raise an error if the value is not a URI, Node, Literal, RdfResource, or string" do
|
670
|
+
expect{subject.set_value(RDF::DC.title, Object.new)}.to raise_error
|
671
|
+
end
|
672
|
+
|
673
|
+
it "should be able to accept a subject" do
|
674
|
+
expect{subject.set_value(RDF::URI("http://opaquenamespace.org/jokes"), RDF::DC.title, 'Comet in Moominland')}.not_to raise_error
|
675
|
+
expect(subject.query(:subject => RDF::URI("http://opaquenamespace.org/jokes"), :predicate => RDF::DC.title).statements.to_a.length).to eq 1
|
676
|
+
end
|
677
|
+
end
|
678
|
+
describe '#get_values' do
|
679
|
+
before do
|
680
|
+
subject.title = ['Comet in Moominland', "Finn Family Moomintroll"]
|
681
|
+
end
|
682
|
+
|
683
|
+
it 'should return values for a predicate uri' do
|
684
|
+
expect(subject.get_values(RDF::DC.title)).to eq ['Comet in Moominland', 'Finn Family Moomintroll']
|
685
|
+
end
|
686
|
+
|
687
|
+
it 'should return values for a registered predicate symbol' do
|
688
|
+
expect(subject.get_values(:title)).to eq ['Comet in Moominland', 'Finn Family Moomintroll']
|
689
|
+
end
|
690
|
+
|
691
|
+
it "should return values for other subjects if asked" do
|
692
|
+
expect(subject.get_values(RDF::URI("http://opaquenamespace.org/jokes"),:title)).to eq []
|
693
|
+
subject.set_value(RDF::URI("http://opaquenamespace.org/jokes"), RDF::DC.title, 'Comet in Moominland')
|
694
|
+
expect(subject.get_values(RDF::URI("http://opaquenamespace.org/jokes"),:title)).to eq ["Comet in Moominland"]
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
698
|
+
describe '#type' do
|
699
|
+
it 'should return the type configured on the parent class' do
|
700
|
+
expect(subject.type).to eq [LD4L::OreRDF::AggregationResource.type]
|
701
|
+
end
|
702
|
+
|
703
|
+
it 'should set the type' do
|
704
|
+
subject.type = RDF::URI('http://example.org/AnotherClass')
|
705
|
+
expect(subject.type).to eq [RDF::URI('http://example.org/AnotherClass')]
|
706
|
+
end
|
707
|
+
|
708
|
+
it 'should be the type in the graph' do
|
709
|
+
subject.query(:subject => subject.rdf_subject, :predicate => RDF.type).statements do |s|
|
710
|
+
expect(s.object).to eq RDF::URI('http://example.org/AnotherClass')
|
711
|
+
end
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
715
|
+
describe '#rdf_label' do
|
716
|
+
it 'should return an array of label values' do
|
717
|
+
expect(subject.rdf_label).to be_kind_of Array
|
718
|
+
end
|
719
|
+
|
720
|
+
it 'should return the default label values' do
|
721
|
+
subject.title = 'Comet in Moominland'
|
722
|
+
expect(subject.rdf_label).to eq ['Comet in Moominland']
|
723
|
+
end
|
724
|
+
|
725
|
+
it 'should prioritize configured label values' do
|
726
|
+
custom_label = RDF::URI('http://example.org/custom_label')
|
727
|
+
subject.class.configure :rdf_label => custom_label
|
728
|
+
subject << RDF::Statement(subject.rdf_subject, custom_label, RDF::Literal('New Label'))
|
729
|
+
subject.title = 'Comet in Moominland'
|
730
|
+
expect(subject.rdf_label).to eq ['New Label']
|
731
|
+
end
|
732
|
+
end
|
733
|
+
|
734
|
+
describe '#solrize' do
|
735
|
+
it 'should return a label for bnodes' do
|
736
|
+
expect(subject.solrize).to eq subject.rdf_label
|
737
|
+
end
|
738
|
+
|
739
|
+
it 'should return a string of the resource uri' do
|
740
|
+
subject.set_subject! 'http://example.org/moomin'
|
741
|
+
expect(subject.solrize).to eq 'http://example.org/moomin'
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
describe 'editing the graph' do
|
746
|
+
it 'should write properties when statements are added' do
|
747
|
+
subject << RDF::Statement.new(subject.rdf_subject, RDF::DC.title, 'Comet in Moominland')
|
748
|
+
expect(subject.title).to include 'Comet in Moominland'
|
749
|
+
end
|
750
|
+
|
751
|
+
it 'should delete properties when statements are removed' do
|
752
|
+
subject << RDF::Statement.new(subject.rdf_subject, RDF::DC.title, 'Comet in Moominland')
|
753
|
+
subject.delete RDF::Statement.new(subject.rdf_subject, RDF::DC.title, 'Comet in Moominland')
|
754
|
+
expect(subject.title).to eq []
|
755
|
+
end
|
756
|
+
end
|
757
|
+
|
758
|
+
describe 'big complex graphs' do
|
759
|
+
before do
|
760
|
+
class DummyPerson < ActiveTriples::Resource
|
761
|
+
configure :type => RDF::URI('http://example.org/Person')
|
762
|
+
property :foafname, :predicate => RDF::FOAF.name
|
763
|
+
property :publications, :predicate => RDF::FOAF.publications, :class_name => 'DummyDocument'
|
764
|
+
property :knows, :predicate => RDF::FOAF.knows, :class_name => DummyPerson
|
765
|
+
end
|
766
|
+
|
767
|
+
class DummyDocument < ActiveTriples::Resource
|
768
|
+
configure :type => RDF::URI('http://example.org/Document')
|
769
|
+
property :title, :predicate => RDF::DC.title
|
770
|
+
property :creator, :predicate => RDF::DC.creator, :class_name => 'DummyPerson'
|
771
|
+
end
|
772
|
+
|
773
|
+
LD4L::OreRDF::AggregationResource.property :item, :predicate => RDF::DC.relation, :class_name => DummyDocument
|
774
|
+
end
|
775
|
+
|
776
|
+
subject { LD4L::OreRDF::AggregationResource.new }
|
777
|
+
|
778
|
+
let (:document1) do
|
779
|
+
d = DummyDocument.new
|
780
|
+
d.title = 'Document One'
|
781
|
+
d
|
782
|
+
end
|
783
|
+
|
784
|
+
let (:document2) do
|
785
|
+
d = DummyDocument.new
|
786
|
+
d.title = 'Document Two'
|
787
|
+
d
|
788
|
+
end
|
789
|
+
|
790
|
+
let (:person1) do
|
791
|
+
p = DummyPerson.new
|
792
|
+
p.foafname = 'Alice'
|
793
|
+
p
|
794
|
+
end
|
795
|
+
|
796
|
+
let (:person2) do
|
797
|
+
p = DummyPerson.new
|
798
|
+
p.foafname = 'Bob'
|
799
|
+
p
|
800
|
+
end
|
801
|
+
|
802
|
+
let (:data) { <<END
|
803
|
+
_:1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/SomeClass> .
|
804
|
+
_:1 <http://purl.org/dc/terms/relation> _:2 .
|
805
|
+
_:2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Document> .
|
806
|
+
_:2 <http://purl.org/dc/terms/title> "Document One" .
|
807
|
+
_:2 <http://purl.org/dc/terms/creator> _:3 .
|
808
|
+
_:2 <http://purl.org/dc/terms/creator> _:4 .
|
809
|
+
_:4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Person> .
|
810
|
+
_:4 <http://xmlns.com/foaf/0.1/name> "Bob" .
|
811
|
+
_:3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/Person> .
|
812
|
+
_:3 <http://xmlns.com/foaf/0.1/name> "Alice" .
|
813
|
+
_:3 <http://xmlns.com/foaf/0.1/knows> _:4 ."
|
814
|
+
END
|
815
|
+
}
|
816
|
+
|
817
|
+
after do
|
818
|
+
Object.send(:remove_const, "DummyDocument")
|
819
|
+
Object.send(:remove_const, "DummyPerson")
|
820
|
+
end
|
821
|
+
|
822
|
+
it 'should allow access to deep nodes' do
|
823
|
+
document1.creator = [person1, person2]
|
824
|
+
document2.creator = person1
|
825
|
+
person1.knows = person2
|
826
|
+
subject.item = [document1]
|
827
|
+
expect(subject.item.first.creator.first.knows.first.foafname).to eq ['Bob']
|
828
|
+
end
|
829
|
+
end
|
830
|
+
end
|