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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active-fedora (3.1.0.pre1)
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)
@@ -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")
@@ -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
- logger.warn "DEPRECATION WARNING: Calling ActiveFedora.init with a path as an argument is deprecated. Use ActiveFedora.init(:fedora_config_path=>#{options})"
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
 
@@ -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
- #datastreams[dsid].dsLabel = ds_spec[1] #this shouldn't cause it to be dirty
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
- add_datastream(ActiveFedora::RelsExtDatastream.new(@inner_object,'RELS-EXT'))
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
- outbound_only ? rels_ext.relationships : rels_ext.relationships.merge(:inbound=>inbound_relationships)
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
@@ -24,7 +24,7 @@ module ActiveFedora
24
24
  else
25
25
  namespace = klass.pid_namespace
26
26
  end
27
- return "#{namespace}:#{sanitized_class_name}#{pid_suffix}"
27
+ return "info:fedora/#{namespace}:#{sanitized_class_name}#{pid_suffix}"
28
28
  end
29
29
 
30
30
  def self.models_asserted_by(obj)
@@ -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
- #make sure to update if relationships have been updated
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
- if relationships.has_key?(subj)
109
- rels[subj] = {}
101
+ case subj
102
+ when :self
103
+ rels[:self] = {}
110
104
  names.each_pair do |name, predicate|
111
- rels[subj][name] = (relationships[subj].has_key?(predicate) ? relationships[subj][predicate] : [])
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
- if relationships[:self].has_key?(:has_model)
329
- r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:has_model, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(self.class))
330
- if relationships[:self][:has_model].first.to_s.eql?(r.object.to_s)
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: '#{r.object.to_s}' actual: '#{relationships[:self][:has_model].to_s}'"
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
- if !outbound_relationships[predicate].nil?
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
- if !outbound_relationships[predicate].nil?
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(self.pid) if relationships_are_dirty
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(self.pid)
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
- node = Nokogiri::XML::Document.parse(xml)
39
- node.xpath("rdf:RDF/rdf:Description/*", {"rdf"=>"http://www.w3.org/1999/02/22-rdf-syntax-ns#"}).each do |f|
40
- if f.namespace
41
- ns_mapping = self.predicate_mappings[f.namespace.href]
42
- predicate = ns_mapping ? ns_mapping.invert[f.name] : nil
43
- predicate = "#{f.namespace.prefix}_#{f.name}" if predicate.nil?
44
- else
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
- self.relationships.each_pair do |subject, predicates|
63
- if subject == :self || subject == "info:fedora/#{self.pid}"
64
- predicates.each_pair do |predicate, values|
65
- values.each do |val|
66
- ::Solrizer::Extractor.insert_solr_field_value(solr_doc, solr_name(predicate, :symbol), val )
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
- self.class.predicate_mappings[self.class.default_predicate_namespace].keys.each do |predicate|
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(r)
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(r)
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 :internal_uri, :named_relationship_desc, :relationships_are_dirty, :load_from_solr
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
- def add_relationship(relationship)
17
- # Only accept ActiveFedora::Relationships as input arguments
18
- assert_kind_of 'relationship', relationship, ActiveFedora::Relationship
19
- register_triple(relationship.subject, relationship.predicate, relationship.object)
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
- def register_triple(subject, predicate, object)
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
- register_subject(subject)
25
- register_predicate(subject, predicate)
26
- relationships[subject][predicate] << object
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
- def register_subject(subject)
30
- if !relationships.has_key?(subject)
31
- relationships[subject] = {}
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 register_predicate(subject, predicate)
36
- register_subject(subject)
37
- if !relationships[subject].has_key?(predicate)
38
- relationships[subject][predicate] = []
39
- end
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 the given ActiveFedora::Relationship from this object
45
- def remove_relationship(relationship)
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
- unregister_triple(relationship.subject, relationship.predicate, relationship.object)
111
+ rels_ext.dirty = true
48
112
  end
49
113
 
50
- # ** EXPERIMENTAL **
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
- outbound_only = (subject != :inbound)
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
- if !internal_uri.nil? && !relationships[internal_uri].nil?
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
- # If outbound_only is false, inbound relationships will be included.
103
- def relationships(outbound_only=true)
104
- @relationships ||= relationships_from_class
105
- outbound_only ? @relationships : @relationships.merge(:inbound=>inbound_relationships)
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
- def load_outbound_relationship(name, predicate, opts={})
188
+
189
+ def ids_for_outbound(predicate)
197
190
  id_array = []
198
- if !outbound_relationships[predicate].nil?
199
- outbound_relationships[predicate].each do |rel|
200
- id_array << rel.gsub("info:fedora/", "")
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
- #include ActiveFedora::RelationshipsHelper::ClassMethods
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