active-fedora 3.1.0.pre2 → 3.1.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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