active-fedora 3.1.0.pre2 → 3.1.0.pre3
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.
- data/Gemfile.lock +9 -1
- data/active-fedora.gemspec +2 -0
- data/lib/active_fedora.rb +2 -3
- data/lib/active_fedora/base.rb +9 -29
- data/lib/active_fedora/content_model.rb +1 -1
- data/lib/active_fedora/relationships_helper.rb +23 -27
- data/lib/active_fedora/rels_ext_datastream.rb +48 -42
- data/lib/active_fedora/semantic_node.rb +109 -136
- data/lib/active_fedora/version.rb +1 -1
- data/lib/tasks/active_fedora_dev.rake +0 -12
- data/spec/integration/base_spec.rb +44 -40
- data/spec/integration/rels_ext_datastream_spec.rb +31 -10
- data/spec/integration/semantic_node_spec.rb +40 -31
- data/spec/spec_helper.rb +4 -2
- data/spec/unit/active_fedora_spec.rb +6 -13
- data/spec/unit/base_spec.rb +16 -19
- data/spec/unit/content_model_spec.rb +4 -4
- data/spec/unit/relationships_helper_spec.rb +31 -12
- data/spec/unit/rels_ext_datastream_spec.rb +55 -25
- data/spec/unit/semantic_node_spec.rb +52 -121
- metadata +48 -20
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
active-fedora (3.1.0.
|
4
|
+
active-fedora (3.1.0.pre2)
|
5
5
|
activeresource (~> 3.0.0)
|
6
6
|
activesupport (~> 3.0.0)
|
7
7
|
equivalent-xml
|
@@ -11,6 +11,8 @@ PATH
|
|
11
11
|
multipart-post (= 1.1.2)
|
12
12
|
nokogiri
|
13
13
|
om (>= 1.0)
|
14
|
+
rdf
|
15
|
+
rdf-rdfxml
|
14
16
|
rubydora (~> 0.1.6)
|
15
17
|
solr-ruby (>= 0.0.6)
|
16
18
|
solrizer (> 1.0.0)
|
@@ -28,6 +30,7 @@ GEM
|
|
28
30
|
activemodel (= 3.0.10)
|
29
31
|
activesupport (= 3.0.10)
|
30
32
|
activesupport (3.0.10)
|
33
|
+
addressable (2.2.6)
|
31
34
|
akami (1.0.0)
|
32
35
|
gyoku (>= 0.4.0)
|
33
36
|
builder (2.1.2)
|
@@ -69,6 +72,11 @@ GEM
|
|
69
72
|
rake (0.9.2)
|
70
73
|
rbx-require-relative (0.0.5)
|
71
74
|
rcov (0.9.10)
|
75
|
+
rdf (0.3.4.1)
|
76
|
+
addressable (>= 2.2.6)
|
77
|
+
rdf-rdfxml (0.3.5)
|
78
|
+
nokogiri (>= 1.4.4)
|
79
|
+
rdf (>= 0.3.4)
|
72
80
|
rest-client (1.6.7)
|
73
81
|
mime-types (>= 1.16)
|
74
82
|
rsolr (1.0.2)
|
data/active-fedora.gemspec
CHANGED
@@ -28,6 +28,8 @@ Gem::Specification.new do |s|
|
|
28
28
|
s.add_dependency("equivalent-xml")
|
29
29
|
s.add_dependency("facets")
|
30
30
|
s.add_dependency("rubydora", '~>0.1.6')
|
31
|
+
s.add_dependency("rdf")
|
32
|
+
s.add_dependency("rdf-rdfxml")
|
31
33
|
s.add_development_dependency("yard")
|
32
34
|
s.add_development_dependency("RedCloth") # for RDoc formatting
|
33
35
|
s.add_development_dependency("rake")
|
data/lib/active_fedora.rb
CHANGED
@@ -79,15 +79,13 @@ module ActiveFedora #:nodoc:
|
|
79
79
|
# 2. If it does not find a solr.yml and the fedora.yml contains a solr url, it will raise an configuration error
|
80
80
|
# 3. If it does not find a solr.yml and the fedora.yml does not contain a solr url, it will look in: +Rails.root+/config, +current working directory+/config, then the solr.yml shipped with gem
|
81
81
|
def self.init( options={} )
|
82
|
-
logger.level = Logger::ERROR if logger.respond_to? :level ###MediaShelf StubLogger doesn't have a level= method
|
83
82
|
# Make config_options into a Hash if nil is passed in as the value
|
84
83
|
options = {} if options.nil?
|
85
84
|
|
86
85
|
# For backwards compatibility, handle cases where config_path (a String) is passed in as the argument rather than a config_options hash
|
87
86
|
# In all other cases, set config_path to config_options[:config_path], which is ok if it's nil
|
88
87
|
if options.is_a? String
|
89
|
-
|
90
|
-
@config_options = {:fedora_config_path=>options}
|
88
|
+
raise ArgumentError, "Calling ActiveFedora.init with a path as an argument has been removed. Use ActiveFedora.init(:fedora_config_path=>#{options})"
|
91
89
|
else
|
92
90
|
@config_options = options
|
93
91
|
end
|
@@ -290,6 +288,7 @@ module ActiveFedora
|
|
290
288
|
class UnknownAttributeError < NoMethodError; end; # :nodoc:
|
291
289
|
class ActiveFedoraConfigurationException < Exception; end # :nodoc:
|
292
290
|
class AssociationTypeMismatch < RuntimeError; end # :nodoc:
|
291
|
+
class UnregisteredPredicateError < RuntimeError; end
|
293
292
|
|
294
293
|
end
|
295
294
|
|
data/lib/active_fedora/base.rb
CHANGED
@@ -199,7 +199,8 @@ module ActiveFedora
|
|
199
199
|
if (ds_spec)
|
200
200
|
klass = ds_spec.first
|
201
201
|
datastreams[dsid] = klass.new(inner_object, dsid, true)
|
202
|
-
|
202
|
+
datastreams[dsid].model = self if klass == RelsExtDatastream
|
203
|
+
|
203
204
|
if ds_spec.last.class == Proc
|
204
205
|
ds_spec.last.call(datastreams[dsid])
|
205
206
|
end
|
@@ -286,7 +287,9 @@ module ActiveFedora
|
|
286
287
|
# Failing that, creates a new RelsExtDatastream and adds it to the object
|
287
288
|
def rels_ext
|
288
289
|
if !datastreams.has_key?("RELS-EXT")
|
289
|
-
|
290
|
+
ds = ActiveFedora::RelsExtDatastream.new(@inner_object,'RELS-EXT')
|
291
|
+
ds.model = self
|
292
|
+
add_datastream(ds)
|
290
293
|
end
|
291
294
|
return datastreams["RELS-EXT"]
|
292
295
|
end
|
@@ -719,35 +722,11 @@ module ActiveFedora
|
|
719
722
|
# Rely on rels_ext datastream to track relationships array
|
720
723
|
# Overrides accessor for relationships array used by SemanticNode.
|
721
724
|
# If outbound_only is false, inbound relationships will be included.
|
722
|
-
def relationships(outbound_only=true)
|
723
|
-
|
724
|
-
end
|
725
|
+
# def relationships(outbound_only=true)
|
726
|
+
# outbound_only ? rels_ext.relationships : rels_ext.relationships.merge(:inbound=>inbound_relationships)
|
727
|
+
# end
|
725
728
|
|
726
|
-
# Add a Rels-Ext relationship to the Object.
|
727
|
-
# @param predicate
|
728
|
-
# @param object Either a string URI or an object that responds to .pid
|
729
|
-
def add_relationship(predicate, obj, literal=false)
|
730
|
-
r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>predicate, :object=>obj, :is_literal=>literal)
|
731
|
-
unless relationship_exists?(r.subject, r.predicate, r.object)
|
732
|
-
rels_ext.add_relationship(r)
|
733
|
-
#need to call here to indicate update of named_relationships
|
734
|
-
@relationships_are_dirty = true
|
735
|
-
rels_ext.dirty = true
|
736
|
-
end
|
737
|
-
end
|
738
729
|
|
739
|
-
# ** EXPERIMENTAL **
|
740
|
-
#
|
741
|
-
# Remove a Rels-Ext relationship from the Object.
|
742
|
-
# @param predicate
|
743
|
-
# @param object Either a string URI or an object that responds to .pid
|
744
|
-
def remove_relationship(predicate, obj, literal=false)
|
745
|
-
r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>predicate, :object=>obj, :is_literal=>literal)
|
746
|
-
rels_ext.remove_relationship(r)
|
747
|
-
#need to call here to indicate update of named_relationships
|
748
|
-
@relationships_are_dirty = true
|
749
|
-
rels_ext.dirty = true
|
750
|
-
end
|
751
730
|
|
752
731
|
def inner_object # :nodoc
|
753
732
|
@inner_object
|
@@ -1007,6 +986,7 @@ module ActiveFedora
|
|
1007
986
|
#attributes = self.datastreams[name].attributes
|
1008
987
|
else
|
1009
988
|
ds = ar.first.new(inner_object, name)
|
989
|
+
ds.model = self if ar.first == RelsExtDatastream
|
1010
990
|
ds.dsLabel = ar[1]
|
1011
991
|
# If you called has_metadata with a block, pass the block into the Datastream class
|
1012
992
|
if ar.last.class == Proc
|
@@ -86,14 +86,7 @@ module ActiveFedora
|
|
86
86
|
# @param [Boolean] if false it will include inbound relationships (defaults to true)
|
87
87
|
# @return [Hash] Returns a hash of subject name (:self or :inbound) mapped to nested hashs of each relationship name mapped to an Array of objects linked via the relationship
|
88
88
|
def relationships_by_name(outbound_only=true)
|
89
|
-
|
90
|
-
if @relationships_are_dirty == true
|
91
|
-
@relationships_by_name = relationships_by_name_from_class()
|
92
|
-
@relationships_are_dirty = false
|
93
|
-
end
|
94
|
-
|
95
|
-
#this will get called normally on first fetch if relationships are not dirty
|
96
|
-
@relationships_by_name ||= relationships_by_name_from_class()
|
89
|
+
@relationships_by_name = relationships_by_name_from_class()
|
97
90
|
outbound_only ? @relationships_by_name : @relationships_by_name.merge(:inbound=>inbound_relationships_by_name)
|
98
91
|
end
|
99
92
|
|
@@ -105,11 +98,23 @@ module ActiveFedora
|
|
105
98
|
def relationships_by_name_from_class()
|
106
99
|
rels = {}
|
107
100
|
relationship_predicates.each_pair do |subj, names|
|
108
|
-
|
109
|
-
|
101
|
+
case subj
|
102
|
+
when :self
|
103
|
+
rels[:self] = {}
|
110
104
|
names.each_pair do |name, predicate|
|
111
|
-
|
105
|
+
set = []
|
106
|
+
res = relationships.query(:predicate => find_graph_predicate(predicate))
|
107
|
+
res.each_object do |o|
|
108
|
+
set << o.to_s
|
109
|
+
end
|
110
|
+
rels[:self][name] = set
|
112
111
|
end
|
112
|
+
when :inbound
|
113
|
+
#nop
|
114
|
+
# inbound = inbound_relationships
|
115
|
+
# names.each_pair do |name, predicate|
|
116
|
+
# rels[:inbound][name] = inbound[predicate]
|
117
|
+
# end
|
113
118
|
end
|
114
119
|
end
|
115
120
|
return rels
|
@@ -325,12 +330,13 @@ module ActiveFedora
|
|
325
330
|
def conforms_to?(model_class)
|
326
331
|
if self.kind_of?(model_class)
|
327
332
|
#check has model and class match
|
328
|
-
|
329
|
-
|
330
|
-
|
333
|
+
mod = relationships.first(:predicate=>find_graph_predicate(:has_model))
|
334
|
+
if mod
|
335
|
+
expected = ActiveFedora::ContentModel.pid_from_ruby_class(self.class)
|
336
|
+
if mod.object.to_s == expected
|
331
337
|
return true
|
332
338
|
else
|
333
|
-
raise "has_model relationship check failed for model #{model_class} raising exception, expected: '#{
|
339
|
+
raise "has_model relationship check failed for model #{model_class} raising exception, expected: '#{expected}' actual: '#{mod.object.to_s}'"
|
334
340
|
end
|
335
341
|
else
|
336
342
|
raise "has_model relationship does not exist for model #{model_class} check raising exception"
|
@@ -374,22 +380,12 @@ module ActiveFedora
|
|
374
380
|
def relationship_query(relationship_name)
|
375
381
|
query = ""
|
376
382
|
if self.class.is_bidirectional_relationship?(relationship_name)
|
377
|
-
id_array = []
|
378
383
|
predicate = outbound_relationship_predicates["#{relationship_name}_outbound"]
|
379
|
-
|
380
|
-
outbound_relationships[predicate].each do |rel|
|
381
|
-
id_array << rel.gsub("info:fedora/", "")
|
382
|
-
end
|
383
|
-
end
|
384
|
+
id_array = ids_for_outbound(predicate)
|
384
385
|
query = self.class.bidirectional_relationship_query(pid,relationship_name,id_array)
|
385
386
|
elsif outbound_relationship_names.include?(relationship_name)
|
386
|
-
id_array = []
|
387
387
|
predicate = outbound_relationship_predicates[relationship_name]
|
388
|
-
|
389
|
-
outbound_relationships[predicate].each do |rel|
|
390
|
-
id_array << rel.gsub("info:fedora/", "")
|
391
|
-
end
|
392
|
-
end
|
388
|
+
id_array = ids_for_outbound(predicate)
|
393
389
|
query = self.class.outbound_relationship_query(relationship_name,id_array)
|
394
390
|
elsif inbound_relationship_names.include?(relationship_name)
|
395
391
|
query = self.class.inbound_relationship_query(pid,relationship_name)
|
@@ -1,30 +1,28 @@
|
|
1
1
|
require 'active_support/core_ext/class/inheritable_attributes'
|
2
2
|
require 'solrizer/field_name_mapper'
|
3
3
|
require 'uri'
|
4
|
+
require 'rdf/rdfxml'
|
5
|
+
require 'rdf'
|
4
6
|
|
5
7
|
module ActiveFedora
|
6
8
|
class RelsExtDatastream < Datastream
|
7
9
|
|
8
|
-
include ActiveFedora::SemanticNode
|
9
10
|
include Solrizer::FieldNameMapper
|
11
|
+
attr_accessor :model
|
10
12
|
|
11
13
|
|
12
|
-
# def initialize(digital_object, dsid, exists_in_fedora=nil)
|
13
|
-
# super(digital_object, 'RELS-EXT')
|
14
|
-
# end
|
15
|
-
|
16
14
|
def changed?
|
17
|
-
relationships_are_dirty || super
|
15
|
+
(model && model.relationships_are_dirty) || super
|
18
16
|
end
|
19
17
|
|
20
18
|
def serialize!
|
21
|
-
self.content = to_rels_ext(
|
22
|
-
relationships_are_dirty = false
|
19
|
+
self.content = to_rels_ext() if model.relationships_are_dirty
|
20
|
+
model.relationships_are_dirty = false
|
23
21
|
end
|
24
22
|
|
25
23
|
|
26
24
|
def to_xml(fields_xml)
|
27
|
-
to_rels_ext(
|
25
|
+
to_rels_ext()
|
28
26
|
end
|
29
27
|
|
30
28
|
# Populate a RelsExtDatastream object based on the "datastream" content
|
@@ -35,38 +33,46 @@ module ActiveFedora
|
|
35
33
|
if (xml.nil?)
|
36
34
|
### maybe put the template here?
|
37
35
|
else
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
logger.warn "You have a predicate without a namespace #{f.name}. Verify your rels-ext is correct."
|
46
|
-
predicate = "#{f.name}"
|
47
|
-
end
|
48
|
-
is_obj = f["resource"]
|
49
|
-
object = is_obj ? f["resource"] : f.inner_text
|
50
|
-
r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>predicate, :object=>object, :is_literal=>!is_obj)
|
51
|
-
tmpl.add_relationship(r)
|
36
|
+
RDF::RDFXML::Reader.new(xml) do |reader|
|
37
|
+
reader.each_statement do |statement|
|
38
|
+
literal = statement.object.kind_of?(RDF::Literal)
|
39
|
+
predicate = self.short_predicate(statement.predicate)
|
40
|
+
object = literal ? statement.object.value : statement.object.to_str
|
41
|
+
tmpl.model.add_relationship(predicate, object)
|
42
|
+
end
|
52
43
|
end
|
53
|
-
tmpl.relationships_are_dirty = false
|
54
|
-
#tmpl.send(:dirty=, false)
|
44
|
+
tmpl.model.relationships_are_dirty = false
|
55
45
|
tmpl
|
56
46
|
end
|
57
47
|
end
|
48
|
+
|
49
|
+
# Creates a RELS-EXT datastream for insertion into a Fedora Object
|
50
|
+
# @param [String] pid
|
51
|
+
# @param [Hash] relationships (optional) @default self.relationships
|
52
|
+
# Note: This method is implemented on SemanticNode instead of RelsExtDatastream because SemanticNode contains the relationships array
|
53
|
+
def to_rels_ext()
|
54
|
+
xml = RDF::RDFXML::Writer.buffer do |writer|
|
55
|
+
model.relationships.each_statement do |statement|
|
56
|
+
writer << statement
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
xml
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.short_predicate(predicate)
|
65
|
+
predicate.to_str.gsub(/^[^#]+#/, '').underscore.to_sym
|
66
|
+
end
|
58
67
|
|
59
68
|
# Serialize the datastream's RDF relationships to solr
|
60
69
|
# @param [Hash] solr_doc @deafult an empty Hash
|
61
70
|
def to_solr(solr_doc = Hash.new)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
71
|
+
model.relationships.each_statement do |statement|
|
72
|
+
predicate = self.class.short_predicate(statement.predicate)
|
73
|
+
literal = statement.object.kind_of?(RDF::Literal)
|
74
|
+
val = literal ? statement.object.value : statement.object.to_str
|
75
|
+
::Solrizer::Extractor.insert_solr_field_value(solr_doc, solr_name(predicate, :symbol), val )
|
70
76
|
end
|
71
77
|
return solr_doc
|
72
78
|
end
|
@@ -82,22 +88,22 @@ module ActiveFedora
|
|
82
88
|
# Solr must be synchronized with RELS-EXT data in Fedora.
|
83
89
|
def from_solr(solr_doc)
|
84
90
|
#cycle through all possible predicates
|
85
|
-
|
91
|
+
ActiveFedora::Base.predicate_mappings[ActiveFedora::Base.default_predicate_namespace].keys.each do |predicate|
|
86
92
|
predicate_symbol = ActiveFedora::SolrService.solr_name(predicate, :symbol)
|
87
93
|
value = (solr_doc[predicate_symbol].nil? ? solr_doc[predicate_symbol.to_s]: solr_doc[predicate_symbol])
|
88
94
|
unless value.nil?
|
89
95
|
if value.is_a? Array
|
90
96
|
value.each do |obj|
|
91
|
-
o_uri = URI.parse(obj)
|
92
|
-
literal = o_uri.scheme.nil?
|
93
|
-
r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>predicate, :object=>obj, :is_literal=>literal)
|
94
|
-
add_relationship(
|
97
|
+
#o_uri = URI.parse(obj)
|
98
|
+
#literal = o_uri.scheme.nil?
|
99
|
+
#r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>predicate, :object=>obj, :is_literal=>literal)
|
100
|
+
model.add_relationship(predicate, obj)
|
95
101
|
end
|
96
102
|
else
|
97
|
-
o_uri = URI.parse(value)
|
98
|
-
literal = o_uri.scheme.nil?
|
99
|
-
r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>predicate, :object=>value, :is_literal=>literal)
|
100
|
-
add_relationship(
|
103
|
+
#o_uri = URI.parse(value)
|
104
|
+
#literal = o_uri.scheme.nil?
|
105
|
+
#r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>predicate, :object=>value, :is_literal=>literal)
|
106
|
+
model.add_relationship(predicate, value)
|
101
107
|
end
|
102
108
|
end
|
103
109
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
require 'active_support/core_ext/class/inheritable_attributes'
|
1
3
|
module ActiveFedora
|
2
4
|
module SemanticNode
|
3
5
|
extend ActiveSupport::Concern
|
@@ -6,67 +8,116 @@ module ActiveFedora
|
|
6
8
|
self.class_relationships = {}
|
7
9
|
self.class_named_relationships_desc = {}
|
8
10
|
end
|
9
|
-
attr_accessor :
|
11
|
+
attr_accessor :named_relationship_desc, :relationships_are_dirty, :load_from_solr, :subject #:internal_uri
|
12
|
+
|
10
13
|
#TODO I think we can remove named_relationship_desc from attr_accessor - jcoyne
|
11
14
|
|
12
15
|
def assert_kind_of(n, o,t)
|
13
16
|
raise "Assertion failure: #{n}: #{o} is not of type #{t}" unless o.kind_of?(t)
|
14
17
|
end
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
# Add a relationship to the Object.
|
20
|
+
# @param predicate
|
21
|
+
# @param object Either a string URI or an object that is a kind of ActiveFedora::Base
|
22
|
+
def add_relationship(predicate, obj, literal=false)
|
23
|
+
unless relationship_exists?(internal_uri, predicate, obj)
|
24
|
+
register_triple(internal_uri, predicate, obj)
|
25
|
+
#need to call here to indicate update of named_relationships
|
26
|
+
@relationships_are_dirty = true
|
27
|
+
rels_ext.dirty = true
|
28
|
+
end
|
20
29
|
end
|
21
|
-
|
22
|
-
|
30
|
+
|
31
|
+
# Add a RDF triple to the relationship graph
|
32
|
+
# @param pid a string represending the pid of the subject
|
33
|
+
# @param predicate a predicate symbol
|
34
|
+
# @param target an object to store
|
35
|
+
def register_triple(pid, predicate, target)
|
23
36
|
self.relationships_are_dirty = true
|
24
|
-
|
25
|
-
|
26
|
-
|
37
|
+
relationships.insert build_statement(pid, predicate, target)
|
38
|
+
|
39
|
+
# register_subject(subject)
|
40
|
+
# register_predicate(subject, predicate)
|
41
|
+
# relationships[subject][predicate] << object
|
27
42
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
43
|
+
|
44
|
+
# Create an RDF statement
|
45
|
+
# @param pid a string represending the pid of the subject
|
46
|
+
# @param predicate a predicate symbol
|
47
|
+
# @param target an object to store
|
48
|
+
def build_statement(pid, predicate, target)
|
49
|
+
raise "Not allowed anymore" if pid == :self
|
50
|
+
target = target.internal_uri if target.respond_to? :internal_uri
|
51
|
+
subject = RDF::URI.new(pid) #TODO cache
|
52
|
+
begin
|
53
|
+
literal = URI.parse(target).scheme.nil?
|
54
|
+
rescue URI::InvalidURIError
|
55
|
+
literal = false
|
32
56
|
end
|
57
|
+
object = literal ? RDF::Literal.new(target) : RDF::URI.new(target)
|
58
|
+
|
59
|
+
RDF::Statement.new(subject, find_graph_predicate(predicate), object)
|
60
|
+
|
33
61
|
end
|
34
|
-
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
62
|
+
|
63
|
+
def find_graph_predicate(predicate)
|
64
|
+
#TODO, these could be cached
|
65
|
+
case predicate
|
66
|
+
when :has_model, "hasModel", :hasModel
|
67
|
+
xmlns="info:fedora/fedora-system:def/model#"
|
68
|
+
begin
|
69
|
+
rel_predicate = ActiveFedora::Base.predicate_lookup(predicate,xmlns)
|
70
|
+
rescue UnregisteredPredicateError
|
71
|
+
xmlns = nil
|
72
|
+
rel_predicate = nil
|
73
|
+
end
|
74
|
+
else
|
75
|
+
xmlns="info:fedora/fedora-system:def/relations-external#"
|
76
|
+
begin
|
77
|
+
rel_predicate = ActiveFedora::Base.predicate_lookup(predicate,xmlns)
|
78
|
+
rescue UnregisteredPredicateError
|
79
|
+
xmlns = nil
|
80
|
+
rel_predicate = nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
unless xmlns && rel_predicate
|
85
|
+
rel_predicate, xmlns = ActiveFedora::Base.find_predicate(predicate)
|
86
|
+
end
|
87
|
+
self.class.vocabularies[xmlns][rel_predicate]
|
40
88
|
end
|
89
|
+
|
90
|
+
# def register_subject(subject)
|
91
|
+
# if !relationships.has_key?(subject)
|
92
|
+
# relationships[subject] = {}
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
|
96
|
+
# def register_predicate(subject, predicate)
|
97
|
+
# register_subject(subject)
|
98
|
+
# if !relationships[subject].has_key?(predicate)
|
99
|
+
# relationships[subject][predicate] = []
|
100
|
+
# end
|
101
|
+
# end
|
41
102
|
|
42
103
|
# ** EXPERIMENTAL **
|
43
|
-
#
|
44
|
-
# Remove
|
45
|
-
|
104
|
+
#
|
105
|
+
# Remove a Rels-Ext relationship from the Object.
|
106
|
+
# @param predicate
|
107
|
+
# @param object Either a string URI or an object that responds to .pid
|
108
|
+
def remove_relationship(predicate, obj, literal=false)
|
109
|
+
relationships.delete build_statement(internal_uri, predicate, obj)
|
46
110
|
@relationships_are_dirty = true
|
47
|
-
|
111
|
+
rels_ext.dirty = true
|
48
112
|
end
|
49
113
|
|
50
|
-
|
51
|
-
#
|
52
|
-
# Remove the subject, predicate, and object triple from the relationships hash
|
53
|
-
def unregister_triple(subject, predicate, object)
|
54
|
-
if relationship_exists?(subject, predicate, object)
|
55
|
-
relationships[subject][predicate].delete_if {|curObj| curObj == object}
|
56
|
-
relationships[subject].delete(predicate) if relationships[subject][predicate].nil? || relationships[subject][predicate].empty?
|
57
|
-
else
|
58
|
-
return false
|
59
|
-
end
|
60
|
-
end
|
114
|
+
|
61
115
|
|
62
116
|
# ** EXPERIMENTAL **
|
63
117
|
#
|
64
118
|
# Returns true if a relationship exists for the given subject, predicate, and object triple
|
65
119
|
def relationship_exists?(subject, predicate, object)
|
66
|
-
|
67
|
-
#cache the call in case it is retrieving inbound as well, don't want to hit solr too many times
|
68
|
-
cached_relationships = relationships(outbound_only)
|
69
|
-
cached_relationships.has_key?(subject)&&cached_relationships[subject].has_key?(predicate)&&cached_relationships[subject][predicate].include?(object)
|
120
|
+
relationships.has_statement? build_statement(subject, predicate, object)
|
70
121
|
end
|
71
122
|
|
72
123
|
def inbound_relationships(response_format=:uri)
|
@@ -92,17 +143,13 @@ module ActiveFedora
|
|
92
143
|
end
|
93
144
|
|
94
145
|
def outbound_relationships()
|
95
|
-
|
96
|
-
return relationships[:self].merge(relationships[internal_uri])
|
97
|
-
else
|
98
|
-
return relationships[:self]
|
99
|
-
end
|
146
|
+
relationships.statements
|
100
147
|
end
|
101
148
|
|
102
|
-
|
103
|
-
|
104
|
-
@
|
105
|
-
|
149
|
+
def relationships
|
150
|
+
# @relationships ||= {:self=>{}}
|
151
|
+
@subject ||= RDF::URI.new(internal_uri)
|
152
|
+
@relationships ||= RDF::Graph.new
|
106
153
|
end
|
107
154
|
|
108
155
|
def relationships_from_class
|
@@ -116,61 +163,6 @@ module ActiveFedora
|
|
116
163
|
return rels
|
117
164
|
end
|
118
165
|
|
119
|
-
# Creates a RELS-EXT datastream for insertion into a Fedora Object
|
120
|
-
# @param [String] pid
|
121
|
-
# @param [Hash] relationships (optional) @default self.relationships
|
122
|
-
# Note: This method is implemented on SemanticNode instead of RelsExtDatastream because SemanticNode contains the relationships array
|
123
|
-
def to_rels_ext(pid, relationships=self.relationships)
|
124
|
-
starter_xml = <<-EOL
|
125
|
-
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
126
|
-
<rdf:Description rdf:about="info:fedora/#{pid}">
|
127
|
-
</rdf:Description>
|
128
|
-
</rdf:RDF>
|
129
|
-
EOL
|
130
|
-
xml = REXML::Document.new(starter_xml)
|
131
|
-
|
132
|
-
# Iterate through the hash of predicates, adding an element to the RELS-EXT for each "object" in the predicate's corresponding array.
|
133
|
-
# puts ""
|
134
|
-
# puts "Iterating through a(n) #{self.class}"
|
135
|
-
# puts "=> whose relationships are #{self.relationships.inspect}"
|
136
|
-
# puts "=> and whose outbound relationships are #{self.outbound_relationships.inspect}"
|
137
|
-
self.outbound_relationships.each do |predicate, targets_array|
|
138
|
-
targets_array.each do |target|
|
139
|
-
xmlns=String.new
|
140
|
-
case predicate
|
141
|
-
when :has_model, "hasModel", :hasModel
|
142
|
-
xmlns="info:fedora/fedora-system:def/model#"
|
143
|
-
begin
|
144
|
-
rel_predicate = self.class.predicate_lookup(predicate,xmlns)
|
145
|
-
rescue UnregisteredPredicateError
|
146
|
-
xmlns = nil
|
147
|
-
rel_predicate = nil
|
148
|
-
end
|
149
|
-
else
|
150
|
-
xmlns="info:fedora/fedora-system:def/relations-external#"
|
151
|
-
begin
|
152
|
-
rel_predicate = self.class.predicate_lookup(predicate,xmlns)
|
153
|
-
rescue UnregisteredPredicateError
|
154
|
-
xmlns = nil
|
155
|
-
rel_predicate = nil
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
unless xmlns && rel_predicate
|
160
|
-
rel_predicate, xmlns = self.class.find_predicate(predicate)
|
161
|
-
end
|
162
|
-
# puts ". #{predicate} #{target} #{xmlns}"
|
163
|
-
literal = URI.parse(target).scheme.nil?
|
164
|
-
if literal
|
165
|
-
xml.root.elements["rdf:Description"].add_element(rel_predicate, {"xmlns" => "#{xmlns}"}).add_text(target)
|
166
|
-
else
|
167
|
-
xml.root.elements["rdf:Description"].add_element(rel_predicate, {"xmlns" => "#{xmlns}", "rdf:resource"=>target})
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
xml.to_s
|
172
|
-
end
|
173
|
-
|
174
166
|
def load_inbound_relationship(name, predicate, opts={})
|
175
167
|
opts = {:rows=>25}.merge(opts)
|
176
168
|
query = self.class.inbound_relationship_query(self.pid,"#{name}")
|
@@ -193,13 +185,18 @@ module ActiveFedora
|
|
193
185
|
end
|
194
186
|
end
|
195
187
|
|
196
|
-
|
188
|
+
|
189
|
+
def ids_for_outbound(predicate)
|
197
190
|
id_array = []
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
191
|
+
res = relationships.query(:predicate => find_graph_predicate(predicate))
|
192
|
+
res.each_object do |o|
|
193
|
+
id_array << o.to_s.gsub("info:fedora/", "")
|
202
194
|
end
|
195
|
+
id_array
|
196
|
+
end
|
197
|
+
|
198
|
+
def load_outbound_relationship(name, predicate, opts={})
|
199
|
+
id_array = ids_for_outbound(predicate)
|
203
200
|
if opts[:response_format] == :id_array && !self.class.relationship_has_solr_filter_query?(:self,"#{name}")
|
204
201
|
return id_array
|
205
202
|
else
|
@@ -222,7 +219,10 @@ module ActiveFedora
|
|
222
219
|
end
|
223
220
|
|
224
221
|
module ClassMethods
|
225
|
-
|
222
|
+
def vocabularies
|
223
|
+
@vocabularies ||= {"info:fedora/fedora-system:def/relations-external#" => RDF::Vocabulary.new("info:fedora/fedora-system:def/relations-external#"),
|
224
|
+
"info:fedora/fedora-system:def/model#" => RDF::Vocabulary.new("info:fedora/fedora-system:def/model#")}
|
225
|
+
end
|
226
226
|
|
227
227
|
# Allows for a relationship to be treated like any other attribute of a model class. You define
|
228
228
|
# relationships in your model class using this method. You then have access to several
|
@@ -478,7 +478,6 @@ module ActiveFedora
|
|
478
478
|
# ds.relationships # => {:self=>{:has_model=>["afmodel:SimpleThing"],:has_part=>["demo:20"]},:inbound=>{:is_part_of=>["demo:6"]}
|
479
479
|
def relationships
|
480
480
|
@class_relationships ||= Hash[:self => {}]
|
481
|
-
#class_relationships
|
482
481
|
end
|
483
482
|
|
484
483
|
|
@@ -495,31 +494,6 @@ module ActiveFedora
|
|
495
494
|
end
|
496
495
|
end
|
497
496
|
|
498
|
-
#alias_method :register_target, :register_object
|
499
|
-
|
500
|
-
# Creates a RELS-EXT datastream for insertion into a Fedora Object
|
501
|
-
# @param [String] pid of the object that the RELS-EXT datastream belongs to
|
502
|
-
# @param [Hash] relationships the relationships hash to transform into RELS-EXT RDF. @default the object's relationships hash
|
503
|
-
# Note: This method is implemented on SemanticNode instead of RelsExtDatastream because SemanticNode contains the relationships array
|
504
|
-
def relationships_to_rels_ext(pid, relationships=self.relationships)
|
505
|
-
starter_xml = <<-EOL
|
506
|
-
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
507
|
-
<rdf:Description rdf:about="info:fedora/#{pid}">
|
508
|
-
</rdf:Description>
|
509
|
-
</rdf:RDF>
|
510
|
-
EOL
|
511
|
-
xml = REXML::Document.new(starter_xml)
|
512
|
-
|
513
|
-
# Iterate through the hash of predicates, adding an element to the RELS-EXT for each "object" in the predicate's corresponding array.
|
514
|
-
self.outbound_relationships.each do |predicate, targets_array|
|
515
|
-
targets_array.each do |target|
|
516
|
-
#puts ". #{predicate} #{target}"
|
517
|
-
xml.root.elements["rdf:Description"].add_element(predicate_lookup(predicate), {"xmlns" => "info:fedora/fedora-system:def/relations-external#", "rdf:resource"=>target})
|
518
|
-
end
|
519
|
-
end
|
520
|
-
xml.to_s
|
521
|
-
end
|
522
|
-
|
523
497
|
# If predicate is a symbol, looks up the predicate in the predicate_mappings
|
524
498
|
# If predicate is not a Symbol, returns the predicate untouched
|
525
499
|
# @raise UnregisteredPredicateError if the predicate is a symbol but is not found in the predicate_mappings
|
@@ -559,6 +533,5 @@ module ActiveFedora
|
|
559
533
|
end
|
560
534
|
end
|
561
535
|
|
562
|
-
class UnregisteredPredicateError < RuntimeError; end
|
563
536
|
|
564
537
|
end
|