active-fedora 5.7.1 → 6.0.0.pre1

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.
Files changed (65) hide show
  1. data/.gitmodules +1 -1
  2. data/Gemfile +2 -1
  3. data/History.txt +0 -14
  4. data/Rakefile +1 -2
  5. data/active-fedora.gemspec +2 -2
  6. data/lib/active_fedora.rb +1 -16
  7. data/lib/active_fedora/associations.rb +8 -11
  8. data/lib/active_fedora/associations/association_collection.rb +2 -4
  9. data/lib/active_fedora/associations/has_and_belongs_to_many_association.rb +3 -12
  10. data/lib/active_fedora/associations/has_many_association.rb +0 -4
  11. data/lib/active_fedora/base.rb +6 -6
  12. data/lib/active_fedora/config.rb +0 -7
  13. data/lib/active_fedora/datastream.rb +0 -37
  14. data/lib/active_fedora/datastream_collections.rb +0 -10
  15. data/lib/active_fedora/datastreams.rb +0 -17
  16. data/lib/active_fedora/digital_object.rb +1 -1
  17. data/lib/active_fedora/file_configurator.rb +0 -22
  18. data/lib/active_fedora/fixture_loader.rb +1 -1
  19. data/lib/active_fedora/nokogiri_datastream.rb +9 -51
  20. data/lib/active_fedora/qualified_dublin_core_datastream.rb +1 -1
  21. data/lib/active_fedora/querying.rb +8 -4
  22. data/lib/active_fedora/rdf_datastream.rb +10 -9
  23. data/lib/active_fedora/rdf_node.rb +1 -1
  24. data/lib/active_fedora/rdf_node/term_proxy.rb +9 -5
  25. data/lib/active_fedora/relation.rb +1 -1
  26. data/lib/active_fedora/rels_ext_datastream.rb +1 -8
  27. data/lib/active_fedora/semantic_node.rb +0 -35
  28. data/lib/active_fedora/simple_datastream.rb +1 -1
  29. data/lib/active_fedora/solr_service.rb +6 -8
  30. data/lib/active_fedora/version.rb +1 -1
  31. data/lib/tasks/active_fedora_dev.rake +11 -3
  32. data/solr/conf/schema.xml +10 -1
  33. data/spec/integration/base_spec.rb +2 -347
  34. data/spec/integration/complex_rdf_datastream_spec.rb +1 -1
  35. data/spec/integration/full_featured_model_spec.rb +1 -9
  36. data/spec/integration/ntriples_datastream_spec.rb +4 -4
  37. data/spec/integration/om_datastream_spec.rb +2 -1
  38. data/spec/integration/rels_ext_datastream_spec.rb +1 -89
  39. data/spec/integration/scoped_query_spec.rb +4 -4
  40. data/spec/samples/hydra-mods_article_datastream.rb +2 -2
  41. data/spec/spec_helper.rb +3 -0
  42. data/spec/unit/base_spec.rb +7 -81
  43. data/spec/unit/datastream_spec.rb +0 -25
  44. data/spec/unit/has_many_collection_spec.rb +2 -27
  45. data/spec/unit/ntriples_datastream_spec.rb +28 -39
  46. data/spec/unit/om_datastream_spec.rb +13 -13
  47. data/spec/unit/qualified_dublin_core_datastream_spec.rb +1 -1
  48. data/spec/unit/query_spec.rb +1 -24
  49. data/spec/unit/semantic_node_spec.rb +0 -2
  50. data/spec/unit/simple_datastream_spec.rb +2 -2
  51. data/spec/unit/solr_config_options_spec.rb +1 -1
  52. metadata +76 -57
  53. checksums.yaml +0 -7
  54. data/.travis.yml +0 -8
  55. data/lib/active_fedora/file_management.rb +0 -81
  56. data/lib/active_fedora/metadata_datastream_helper.rb +0 -43
  57. data/lib/active_fedora/named_relationships.rb +0 -99
  58. data/lib/active_fedora/relationships.rb +0 -663
  59. data/spec/integration/base_file_management_spec.rb +0 -24
  60. data/spec/integration/has_many_associations_spec.rb +0 -64
  61. data/spec/integration/metadata_datastream_helper_spec.rb +0 -100
  62. data/spec/integration/semantic_node_spec.rb +0 -457
  63. data/spec/unit/base_file_management_spec.rb +0 -95
  64. data/spec/unit/has_and_belongs_to_many_collection_spec.rb +0 -59
  65. data/spec/unit/relationships_spec.rb +0 -871
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 3b46cdb4a2b08e962eb11208d25c8d1b62c20002
4
- data.tar.gz: a2db62d6d3c49b475e8cf1dd1faf1c64bd5e2799
5
- SHA512:
6
- metadata.gz: c41953687706d6ee968dc502263d0cb3abc6fe66b32c74af20f0bf2f03d0cb8d8f8360c6684abf6938c2a8e6ef4012739038aea9ac8c1993a85436756d760008
7
- data.tar.gz: c8ef58febdf589004777b45b83d079cce0df4beef6c35beebe4b4e7fbc50b7298535e8df56f8fc51a09744c72f83d47480027a5dd82de6b94a73d891b7c8a30a
@@ -1,8 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - "1.9.3"
4
- - "2.0.0"
5
-
6
- notifications:
7
- irc: "irc.freenode.org#projecthydra"
8
-
@@ -1,81 +0,0 @@
1
- module ActiveFedora
2
- module FileManagement
3
- extend ActiveSupport::Concern
4
- extend Deprecation
5
- self.deprecation_horizon = 'active-fedora 6.0'
6
-
7
- included do
8
- include ActiveFedora::Relationships
9
- Deprecation.silence(ActiveFedora::Relationships::ClassMethods) do
10
- has_relationship "collection_members", :has_collection_member
11
- has_relationship "part_of", :is_part_of
12
- has_bidirectional_relationship "parts", :has_part, :is_part_of
13
- end
14
- end
15
-
16
- # List the objects that assert isPartOf pointing at this object _plus_ all objects that this object asserts hasPart for
17
- # Note: Previous versions of ActiveFedora used hasCollectionMember to represent this type of relationship.
18
- # To accommodate this, until active-fedora-1.3, .file_assets will also return anything that this asserts hasCollectionMember for and will output a warning in the logs.
19
- #
20
- # @param [Hash] opts -- same options as auto-generated methods for relationships (ie. :response_format)
21
- # @return [Array of ActiveFedora objects, Array of PIDs, or Solr::Result] -- same options as auto-generated methods for relationships (ie. :response_format)
22
- def file_objects(opts={})
23
- cm_array = collection_members(:response_format=>:id_array)
24
-
25
- if !cm_array.empty?
26
- logger.warn "This object has collection member assertions. hasCollectionMember will no longer be used to track file_object relationships after active_fedora 1.3. Use isPartOf assertions in the RELS-EXT of child objects instead."
27
- if opts[:response_format] == :solr || opts[:response_format] == :load_from_solr
28
- logger.warn ":solr and :load_from_solr response formats for file_objects search only uses parts relationships (usage of hasCollectionMember is no longer supported)"
29
- result = parts(opts)
30
- else
31
- cm_result = collection_members(opts)
32
- parts_result = parts(opts)
33
- ary = cm_result+parts_result
34
- result = ary.uniq
35
- end
36
- else
37
- result = parts(opts)
38
- end
39
- return result
40
- end
41
-
42
- # Add the given obj as a child to the current object using an inbound is_part_of relationship
43
- #
44
- # @param [ActiveFedora::Base,String] obj the object or the pid of the object to add
45
- # @return [Boolean] whether saving the child object was successful
46
- # @example This will add an is_part_of relationship to the child_object's RELS-EXT datastream pointing at parent_object
47
- # parent_object.file_objects_append(child_object)
48
- def file_objects_append(obj)
49
- # collection_members_append(obj)
50
- unless obj.kind_of? ActiveFedora::Base
51
- begin
52
- obj = ActiveFedora::Base.find(obj)
53
- rescue ActiveFedora::ObjectNotFoundError
54
- "You must provide either an ActiveFedora object or a valid pid to add it as a file object. You submitted #{obj.inspect}"
55
- end
56
- end
57
- obj.add_relationship(:is_part_of, self)
58
- obj.save
59
- end
60
-
61
- # Add the given obj as a collection member to the current object using an outbound has_collection_member relationship.
62
- #
63
- # @param [ActiveFedora::Base] obj the file to add
64
- # @return [ActiveFedora::Base] obj returns self
65
- # @example This will add a has_collection_member relationship to the parent_object's RELS-EXT datastream pointing at child_object
66
- # parent_object.collection_members_append(child_object)
67
- def collection_members_append(obj)
68
- add_relationship(:has_collection_member, obj)
69
- return self
70
- end
71
-
72
- def collection_members_remove()
73
- # will rely on SemanticNode.remove_relationship once it is implemented
74
- end
75
-
76
- deprecation_deprecate :file_objects, :file_objects_append, :collection_members_append, :collection_members_remove
77
-
78
-
79
- end
80
- end
81
-
@@ -1,43 +0,0 @@
1
- require 'solrizer/field_name_mapper'
2
-
3
- module ActiveFedora::MetadataDatastreamHelper
4
- extend Deprecation
5
- self.deprecation_horizon = 'active-fedora 6.0'
6
-
7
- attr_accessor :fields, :xml_loaded
8
-
9
- module ClassMethods
10
-
11
- #get the Class's field list
12
- def fields
13
- @@classFields
14
- end
15
-
16
- end
17
-
18
- def self.included(klass)
19
- klass.extend(ClassMethods)
20
- klass.send(:include, Solrizer::FieldNameMapper)
21
- end
22
-
23
- def ensure_xml_loaded
24
- return if xml_loaded
25
- self.xml_loaded = true
26
- if new?
27
- ## Load up the template
28
- self.class.from_xml nil, self
29
- else
30
- self.class.from_xml content, self
31
- end
32
- end
33
- deprecation_deprecate :ensure_xml_loaded
34
-
35
- def serialize! # :nodoc:
36
- if changed?
37
- return unless xml_loaded or new?
38
- self.content = self.to_xml
39
- end
40
- end
41
- deprecation_deprecate :serialize!
42
-
43
- end
@@ -1,99 +0,0 @@
1
- module ActiveFedora
2
- module NamedRelationships
3
- extend ActiveSupport::Concern
4
- extend Deprecation
5
- self.deprecation_horizon = 'active-fedora 6.0'
6
-
7
- included do
8
- class_attribute :class_named_relationships_desc
9
- self.class_named_relationships_desc = {}
10
- end
11
-
12
- # ** EXPERIMENTAL **
13
- #
14
- # Check to make sure a subject,name, and predicate triple does not already exist
15
- # with the same subject but different name.
16
- # This method is used to ensure conflicting has_relationship calls are not made because
17
- # predicates cannot be reused across relationship names. Otherwise, the mapping of relationship name
18
- # to predicate in RELS-EXT would be broken.
19
- def named_predicate_exists_with_different_name?(subject,name,predicate)
20
- if named_relationships_desc.has_key?(subject)
21
- named_relationships_desc[subject].each_pair do |existing_name, args|
22
- return true if !args[:predicate].nil? && args[:predicate] == predicate && existing_name != name
23
- end
24
- end
25
- return false
26
- end
27
-
28
- # ** EXPERIMENTAL **
29
- #
30
- # Return hash that stores named relationship metadata defined by has_relationship calls
31
- # ====Example
32
- # For the following relationship
33
- #
34
- # has_relationship "audio_records", :has_part, :type=>AudioRecord
35
- # Results in the following returned by named_relationships_desc
36
- # {:self=>{"audio_records"=>{:type=>AudioRecord, :singular=>nil, :predicate=>:has_part, :inbound=>false}}}
37
- def named_relationships_desc
38
- @class_named_relationships_desc ||= Hash[:self => {}]
39
- #class_named_relationships_desc
40
- end
41
-
42
- # ** EXPERIMENTAL **
43
- #
44
- # Internal method that ensures a relationship subject such as :self and :inbound
45
- # exist within the named_relationships_desc hash tracking named relationships metadata.
46
- def register_named_subject(subject)
47
- unless named_relationships_desc.has_key?(subject)
48
- named_relationships_desc[subject] = {}
49
- end
50
- end
51
-
52
- # ** EXPERIMENTAL **
53
- #
54
- # Internal method that adds relationship name and predicate pair to either an outbound (:self)
55
- # or inbound (:inbound) relationship types.
56
- def register_named_relationship(subject, name, predicate, opts)
57
- register_named_subject(subject)
58
- opts.merge!({:predicate=>predicate})
59
- named_relationships_desc[subject][name] = opts
60
- end
61
-
62
- # ** EXPERIMENTAL **
63
- #
64
- # Used in has_relationship call to create dynamic helper methods to
65
- # append and remove objects to and from a named relationship
66
- # ====Example
67
- # For the following relationship
68
- #
69
- # has_relationship "audio_records", :has_part, :type=>AudioRecord
70
- #
71
- # Methods audio_records_append and audio_records_remove are created.
72
- # Boths methods take an object that is kind_of? ActiveFedora::Base as a parameter
73
- def create_named_relationship_methods(name)
74
- append_method_name = "#{name.to_s.downcase}_append"
75
- remove_method_name = "#{name.to_s.downcase}_remove"
76
- self.send(:define_method,:"#{append_method_name}") {|object| add_named_relationship(name,object)}
77
- self.send(:define_method,:"#{remove_method_name}") {|object| remove_named_relationship(name,object)}
78
- end
79
-
80
- # ** EXPERIMENTAL **
81
- # Similar to +create_named_relationship_methods+ except we are merely creating an alias for outbound portion of bidirectional
82
- #
83
- # ====Example
84
- # has_bidirectional_relationship "members", :has_collection_member, :is_member_of_collection
85
- #
86
- # Method members_outbound_append and members_outbound_remove added
87
- # This method will create members_append which does same thing as members_outbound_append
88
- # and will create members_remove which does same thing as members_outbound_remove
89
- def create_bidirectional_named_relationship_methods(name,outbound_name)
90
- append_method_name = "#{name.to_s.downcase}_append"
91
- remove_method_name = "#{name.to_s.downcase}_remove"
92
- self.send(:define_method,:"#{append_method_name}") {|object| add_named_relationship(outbound_name,object)}
93
- self.send(:define_method,:"#{remove_method_name}") {|object| remove_named_relationship(outbound_name,object)}
94
- end
95
-
96
-
97
- deprecation_deprecate :named_predicate_exists_with_different_name?, :named_relationships_desc, :register_named_subject, :register_named_relationship, :create_named_relationship_methods, :create_bidirectional_named_relationship_methods
98
- end
99
- end
@@ -1,663 +0,0 @@
1
- module ActiveFedora
2
- module Relationships
3
- extend ActiveSupport::Concern
4
- extend Deprecation
5
- self.deprecation_horizon = 'active-fedora 6.0'
6
-
7
-
8
- # Return array of objects for a given relationship name
9
- # @param [String] Name of relationship to find
10
- # @return [Array] Returns array of objects linked via the relationship name given
11
- #
12
- # @deprecated find_relationship_by_name will be removed in active-fedora 6.0
13
- def find_relationship_by_name(name)
14
- rels = nil
15
- if inbound_relationship_names.include?(name)
16
- rels = relationships_by_name(false)[:inbound][name]
17
- elsif outbound_relationship_names.include?(name)
18
- rels = relationships_by_name[:self][name]
19
- end
20
- rels = [] if rels.nil?
21
- return rels
22
- end
23
-
24
- # Return array of relationship names for all inbound relationships (coming from other objects' RELS-EXT and Solr)
25
- # @return [Array] of inbound relationship names for relationships declared via has_relationship in the class
26
- def inbound_relationship_names
27
- relationships_desc.has_key?(:inbound) ? relationships_desc[:inbound].keys : []
28
- end
29
-
30
- # Return hash of relationships_by_name defined within other objects' RELS-EXT
31
- # It returns a hash of relationship name to arrays of objects. It requeries
32
- # solr each time this method is called.
33
- # @return [Hash] Return hash of each relationship name mapped to an Array of objects linked to this object via inbound relationships
34
- def inbound_relationships_by_name
35
- rels = {}
36
- if relationships_desc.has_key?(:inbound)&&!relationships_desc[:inbound].empty?()
37
- inbound_rels = inbound_relationships
38
-
39
- if relationship_predicates.has_key?(:inbound)
40
- relationship_predicates[:inbound].each do |name, predicate|
41
- rels[name] = inbound_rels.has_key?(predicate) ? inbound_rels[predicate] : []
42
- end
43
- end
44
- end
45
- return rels
46
- end
47
-
48
-
49
- # Call this method to return the query used against solr to retrieve any
50
- # objects linked via the relationship name given.
51
- #
52
- # Instead of this method you can also use the helper method
53
- # [relationship_name]_query, i.e. method "parts_query" for relationship "parts" to return the same value
54
- # @param [String] The name of the relationship defined in the model
55
- # @return [String] The query used when querying solr for objects for this relationship
56
- # @example
57
- # Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
58
- # #points to all parents linked via is_member_of
59
- # has_relationship "parents", :is_member_of
60
- # #returns only parents that have a level value set to "series"
61
- # has_relationship "series_parents", :is_member_of, :solr_fq=>level_t:series"
62
- # end
63
- # s = SampleAFObjRelationshipFilterQuery.new
64
- # obj = ActiveFedora::Base.new
65
- # s.parents_append(obj)
66
- # s.series_parents_query
67
- # #=> "(id:changeme\\:13020 AND level_t:series)"
68
- # SampleAFObjRelationshipFilterQuery.relationship_query("series_parents")
69
- # #=> "(id:changeme\\:13020 AND level_t:series)"
70
- def relationship_query(relationship_name)
71
- query = ""
72
- if self.class.is_bidirectional_relationship?(relationship_name)
73
- predicate = outbound_relationship_predicates["#{relationship_name}_outbound"]
74
- id_array = ids_for_outbound(predicate)
75
- query = self.class.bidirectional_relationship_query(pid,relationship_name,id_array)
76
- elsif outbound_relationship_names.include?(relationship_name)
77
- predicate = outbound_relationship_predicates[relationship_name]
78
- id_array = ids_for_outbound(predicate)
79
- query = self.class.outbound_relationship_query(relationship_name,id_array)
80
- elsif inbound_relationship_names.include?(relationship_name)
81
- query = self.class.inbound_relationship_query(pid,relationship_name)
82
- end
83
- query
84
- end
85
-
86
-
87
- # Gets the relationships hash with subject mapped to relationship
88
- # names instead of relationship predicates (unlike the "relationships" method in SemanticNode)
89
- # It has an optional parameter of outbound_only that defaults true.
90
- # If false it will include inbound relationships in the results.
91
- # Also, it will only reload outbound relationships if the relationships hash has changed
92
- # since the last time this method was called.
93
- # @param [Boolean] if false it will include inbound relationships (defaults to true)
94
- # @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
95
- def relationships_by_name(outbound_only=true)
96
- Deprecation.silence(ActiveFedora::Relationships) do
97
- @relationships_by_name = relationships_by_name_from_class()
98
- end
99
- outbound_only ? @relationships_by_name : @relationships_by_name.merge(:inbound=>inbound_relationships_by_name)
100
- end
101
-
102
- # Gets relationships by name from the class using the current relationships hash
103
- # and relationship name,predicate pairs.
104
- # @return [Hash] returns the outbound relationships with :self mapped to nested hashs of each relationship name mapped to an Array of objects linked via the relationship
105
- def relationships_by_name_from_class()
106
- rels = {}
107
- relationship_predicates.each_pair do |subj, names|
108
- case subj
109
- when :self
110
- rels[:self] = {}
111
- names.each_pair do |name, predicate|
112
- set = []
113
- res = relationships.query(:predicate => Predicates.find_graph_predicate(predicate))
114
- res.each_object do |o|
115
- set << o.to_s
116
- end
117
- rels[:self][name] = set
118
- end
119
- when :inbound
120
- #nop
121
- end
122
- end
123
- return rels
124
- end
125
-
126
-
127
-
128
- # Throws an assertion error if conforms_to? returns false for object and model_class
129
- # @param [String] Name of object (just label for output)
130
- # @param [ActiveFedora::Base] Expects to be an object that has ActiveFedora::Base as an ancestor of its class
131
- # @param [Class] The model class used in conforms_to? check on object
132
- def assert_conforms_to(name, object, model_class)
133
- raise "Assertion failure: #{name}: #{object.pid} does not have model #{model_class}, it has model #{relationships[:self][:has_model]}" unless object.conforms_to?(model_class)
134
- end
135
-
136
-
137
-
138
- # Returns a Class symbol for the given string for the class name
139
- # @param [String] the class name as a string
140
- # @return [Class] the class as a Class object
141
- def class_from_name(name)
142
- klass = name.to_s.split('::').inject(Kernel) {|scope, const_name|
143
- scope.const_get(const_name)}
144
- (!klass.nil? && klass.is_a?(::Class)) ? klass : nil
145
- end
146
-
147
- # Return array of relationship names for all outbound relationships (coming from this object's RELS-EXT)
148
- # @return [Array] of outbound relationship names for relationships declared via has_relationship in the class
149
- def outbound_relationship_names
150
- relationships_desc.has_key?(:self) ? relationships_desc[:self].keys : []
151
- end
152
-
153
- # Returns true if the given relationship name is a relationship
154
- # @param [String] Name of relationship
155
- # @param [Boolean] If false checks inbound relationships as well (defaults to true)
156
- def is_relationship_name?(name, outbound_only=true)
157
- Deprecation.silence(ActiveFedora::Relationships) do
158
- if outbound_only
159
- outbound_relationship_names.include?(name)
160
- else
161
- (outbound_relationship_names.include?(name)||inbound_relationship_names.include?(name))
162
- end
163
- end
164
- end
165
-
166
-
167
- def load_inbound_relationship(name, predicate, opts={})
168
- opts = {:rows=>25}.merge(opts)
169
- query = self.class.inbound_relationship_query(self.pid,"#{name}")
170
- return [] if query.empty?
171
- if opts[:response_format] == :solr
172
- solr_result = SolrService.query query, :raw=>true, :rows=>opts[:rows]
173
- return solr_result
174
- else
175
- solr_result = SolrService.query(query, :rows=>opts[:rows])
176
- if opts[:response_format] == :id_array
177
- id_array = []
178
- solr_result.each do |hit|
179
- id_array << hit[SOLR_DOCUMENT_ID]
180
- end
181
- return id_array
182
- elsif opts[:response_format] == :load_from_solr || self.load_from_solr
183
- return ActiveFedora::SolrService.reify_solr_results(solr_result,{:load_from_solr=>true})
184
- else
185
- return ActiveFedora::SolrService.reify_solr_results(solr_result)
186
- end
187
- end
188
- end
189
-
190
-
191
-
192
- def load_bidirectional(name, inbound_method_name, outbound_method_name, opts)
193
- opts = {:rows=>25}.merge(opts)
194
- if opts[:response_format] == :solr || opts[:response_format] == :load_from_solr
195
- predicate = outbound_relationship_predicates["#{name}_outbound"]
196
- outbound_id_array = ids_for_outbound(predicate)
197
- query = self.class.bidirectional_relationship_query(self.pid,"#{name}",outbound_id_array)
198
- solr_result = SolrService.query(query, :rows=>opts[:rows])
199
-
200
- if opts[:response_format] == :solr
201
- return solr_result
202
- elsif opts[:response_format] == :load_from_solr || self.load_from_solr
203
- return ActiveFedora::SolrService.reify_solr_results(solr_result,{:load_from_solr=>true})
204
- else
205
- return ActiveFedora::SolrService.reify_solr_results(solr_result)
206
- end
207
- else
208
- ary = send(inbound_method_name,opts) + send(outbound_method_name, opts)
209
- return ary.uniq
210
- end
211
- end
212
-
213
- def load_outbound_relationship(name, predicate, opts={})
214
- id_array = ids_for_outbound(predicate)
215
- if opts[:response_format] == :id_array && !self.relationship_has_solr_filter_query?(:self,"#{name}")
216
- return id_array
217
- else
218
- query = self.class.outbound_relationship_query(name,id_array)
219
- solr_result = SolrService.query(query)
220
- if opts[:response_format] == :solr
221
- return solr_result
222
- elsif opts[:response_format] == :id_array
223
- return solr_result.map {|hit| hit[SOLR_DOCUMENT_ID] }
224
- elsif opts[:response_format] == :load_from_solr || self.load_from_solr
225
- return ActiveFedora::SolrService.reify_solr_results(solr_result,{:load_from_solr=>true})
226
- else
227
- return ActiveFedora::SolrService.reify_solr_results(solr_result)
228
- end
229
- end
230
- end
231
-
232
- # Check if a relationship has any solr query filters defined by has_relationship call
233
- # @param [Symbol] subject to use such as :self or :inbound
234
- # @param [String] relationship name
235
- # @return [Boolean] true if the relationship has a query filter defined
236
- def relationship_has_solr_filter_query?(subject, relationship_name)
237
- relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
238
- end
239
-
240
-
241
- # Add an outbound relationship for given relationship name
242
- # See ActiveFedora::SemanticNode::ClassMethods.has_relationship
243
- # @param [String] Name of relationship
244
- # @param [ActiveFedora::Base] object to add to the relationship (expects ActvieFedora::Base to be an ancestor)
245
- # @return [Boolean] returns true if add operation successful
246
- def add_relationship_by_name(name, object)
247
- Deprecation.silence(ActiveFedora::Relationships) do
248
- if is_relationship_name?(name,true)
249
- if relationships_desc[:self][name].has_key?(:type)
250
- klass = class_from_name(relationships_desc[:self][name][:type])
251
- unless klass.nil?
252
- (assert_conforms_to 'object', object, klass)
253
- end
254
- end
255
- add_relationship(outbound_relationship_predicates[name],object)
256
- else
257
- false
258
- end
259
- end
260
- end
261
-
262
- # Remove an object for the given relationship name
263
- # @param [String] Relationship name
264
- # @param [ActiveFedora::Base] object to remove
265
- # @return [Boolean] return true if remove operation successful
266
- def remove_relationship_by_name(name, object)
267
- if is_relationship_name?(name,true)
268
- remove_relationship(outbound_relationship_predicates[name],object)
269
- else
270
- return false
271
- end
272
- end
273
-
274
- deprecation_deprecate :find_relationship_by_name, :inbound_relationship_names, :inbound_relationships_by_name, :relationship_query, :relationships_by_name, :relationships_by_name_from_class, :assert_conforms_to, :class_from_name, :outbound_relationship_names, :is_relationship_name?, :load_inbound_relationship, :load_bidirectional, :load_outbound_relationship, :relationship_has_solr_filter_query?, :add_relationship_by_name, :remove_relationship_by_name
275
-
276
- module ClassMethods
277
- extend Deprecation
278
- # Tests if the relationship name passed is in bidirectional
279
- # @param [String] relationship name to test
280
- # @return [Boolean]
281
- def is_bidirectional_relationship?(relationship_name)
282
- (relationships_desc.has_key?(:self)&&relationships_desc.has_key?(:inbound)&&relationships_desc[:self].has_key?("#{relationship_name}_outbound") && relationships_desc[:inbound].has_key?("#{relationship_name}_inbound"))
283
- end
284
-
285
-
286
- # Returns a solr query for retrieving objects specified in an outbound relationship.
287
- # This method is mostly used by internal method calls.
288
- # It utilizes any solr_fq value defined within a relationship to attach a query filter when
289
- # querying solr on top of just the predicate being used.
290
- # Because it is static it
291
- # needs the pids defined within RELS-EXT for this relationship to be passed in.
292
- # If you are calling this method directly to get the query you should use the
293
- # ActiveFedora::SemanticNode.relationship_query instead or use the helper method
294
- # [relationship_name]_query, i.e. method "parts_query" for relationship "parts". This
295
- # method would only be called directly if you had something like an array of outbound pids
296
- # already in something like a solr document for object that has these relationships.
297
- # @param [String] The name of the relationship defined in the model
298
- # @param [Array] An array of pids to include in the query
299
- # @return [String]
300
- # @example
301
- # Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
302
- # #points to all parents linked via is_member_of
303
- # has_relationship "parents", :is_member_of
304
- # #returns only parents that have a level value set to "series"
305
- # has_relationship "series_parents", :is_member_of, :solr_fq=>"level_t:series"
306
- # end
307
- # s = SampleAFObjRelationshipFilterQuery.new
308
- # obj = ActiveFedora::Base.new
309
- # s.series_parents_append(obj)
310
- # s.series_parents_query
311
- # #=> "(id:changeme\\:13020 AND level_t:series)"
312
- # SampleAFObjRelationshipFilterQuery.outbound_relationship_query("series_parents",["id:changeme:13020"])
313
- # #=> "(id:changeme\\:13020 AND level_t:series)"
314
- def outbound_relationship_query(relationship_name,outbound_pids)
315
- query = ActiveFedora::SolrService.construct_query_for_pids(outbound_pids)
316
- subject = :self
317
- if relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
318
- solr_fq = relationships_desc[subject][relationship_name][:solr_fq]
319
- unless query.empty?
320
- #substitute in the filter query for each pid so that it is applied to each in the query
321
- query_parts = query.split(/OR/)
322
- query = ""
323
- query_parts.each_with_index do |query_part,index|
324
- query_part.strip!
325
- query << " OR " if index > 0
326
- query << "(#{query_part} AND #{solr_fq})"
327
- end
328
- else
329
- query = solr_fq
330
- end
331
- end
332
- query
333
- end
334
-
335
-
336
- # Returns a solr query for retrieving objects specified in an inbound relationship.
337
- # This method is mostly used by internal method calls.
338
- # It utilizes any solr_fq value defined within a relationship to attach a query filter
339
- # on top of just the predicate being used. Because it is static it
340
- # needs the pid of the object that has the inbound relationships passed in.
341
- # If you are calling this method directly to get the query you should use the
342
- # ActiveFedora::SemanticNode.relationship_query instead or use the helper method
343
- # [relationship_name]_query, i.e. method "parts_query" for relationship "parts". This
344
- # method would only be called directly if you were working only with Solr and already
345
- # had the pid for the object in something like a solr document.
346
- # @param [String] The pid for the object that has these inbound relationships
347
- # @param [String] The name of the relationship defined in the model
348
- # @return [String]
349
- # @example
350
- # Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
351
- # #returns all parts
352
- # has_relationship "parts", :is_part_of, :inbound=>true
353
- # #returns only parts that have level to "series"
354
- # has_relationship "series_parts", :is_part_of, :inbound=>true, :solr_fq=>"level_t:series"
355
- # end
356
- # s = SampleAFObjRelationshipFilterQuery.new
357
- # s.pid
358
- # #=> id:changeme:13020
359
- # s.series_parts_query
360
- # #=> "is_part_of_s:info\\:fedora/changeme\\:13021 AND level_t:series"
361
- # SampleAFObjRelationshipFilterQuery.inbound_relationship_query(s.pid,"series_parts")
362
- # #=> "is_part_of_s:info\\:fedora/changeme\\:13021 AND level_t:series"
363
- def inbound_relationship_query(pid,relationship_name)
364
- query = ""
365
- subject = :inbound
366
- if relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name)
367
- predicate = relationships_desc[subject][relationship_name][:predicate]
368
- query = ActiveFedora::SolrService.construct_query_for_rel(predicate => "info:fedora/#{pid}")
369
- if relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
370
- solr_fq = relationships_desc[subject][relationship_name][:solr_fq]
371
- query << " AND " unless query.empty?
372
- query << solr_fq
373
- end
374
- end
375
- query
376
- end
377
-
378
- # Returns a solr query for retrieving objects specified in a bidirectional relationship.
379
- # This method is mostly used by internal method calls.
380
- # It usea of solr_fq value defined within a relationship to attach a query filter
381
- # on top of just the predicate being used. Because it is static it
382
- # needs the pids defined within RELS-EXT for the outbound relationship as well as the pid of the
383
- # object for the inbound portion of the relationship.
384
- # If you are calling this method directly to get the query you should use the
385
- # ActiveFedora::SemanticNode.relationship_query instead or use the helper method
386
- # [relationship_name]_query, i.e. method "bi_parts_query" for relationship "bi_parts". This
387
- # method would only be called directly if you had something like an array of outbound pids
388
- # already in something like a solr document for object that has these relationships.
389
- # @param [String] The pid for the object that has these inbound relationships
390
- # @param [String] The name of the relationship defined in the model
391
- # @param [Array] An array of pids to include in the query
392
- # @return [String]
393
- # @example
394
- # Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
395
- # has_bidirectional_relationship "bi_series_parts", :has_part, :is_part_of, :solr_fq=>"level_t:series"
396
- # end
397
- # s = SampleAFObjRelationshipFilterQuery.new
398
- # obj = ActiveFedora::Base.new
399
- # s.bi_series_parts_append(obj)
400
- # s.pid
401
- # #=> "changeme:13025"
402
- # obj.pid
403
- # #=> id:changeme:13026
404
- # s.bi_series_parts_query
405
- # #=> "(id:changeme\\:13026 AND level_t:series) OR (is_part_of_s:info\\:fedora/changeme\\:13025 AND level_t:series)"
406
- # SampleAFObjRelationshipFilterQuery.bidirectional_relationship_query(s.pid,"series_parents",["id:changeme:13026"])
407
- # #=> "(id:changeme\\:13026 AND level_t:series) OR (is_part_of_s:info\\:fedora/changeme\\:13025 AND level_t:series)"
408
- def bidirectional_relationship_query(pid,relationship_name,outbound_pids)
409
- outbound_query = outbound_relationship_query("#{relationship_name}_outbound",outbound_pids)
410
- inbound_query = inbound_relationship_query(pid,"#{relationship_name}_inbound")
411
- query = outbound_query # use outbound_query by default
412
- if !inbound_query.empty?
413
- query << " OR (" + inbound_relationship_query(pid,"#{relationship_name}_inbound") + ")"
414
- end
415
- return query
416
- end
417
-
418
-
419
- # Internal method that ensures a relationship subject such as :self and :inbound
420
- # exist within the relationships_desc hash tracking relationships metadata.
421
- # @param [Symbol] Subject name to register (will probably be something like :self or :inbound)
422
- def register_relationship_desc_subject(subject)
423
- unless relationships_desc.has_key?(subject)
424
- relationships_desc[subject] = {}
425
- end
426
- end
427
-
428
- # Internal method that adds relationship name and predicate pair to either an outbound (:self)
429
- # or inbound (:inbound) relationship types. Refer to ActiveFedora::SemanticNode.has_relationship for information on what metadata will be persisted.
430
- # @param [Symbol] Subject name to register
431
- # @param [String] Name of relationship being registered
432
- # @param [Symbol] Fedora ontology predicate to use
433
- # @param [Hash] Any options passed to has_relationship such as :type, :solr_fq, etc.
434
- def register_relationship_desc(subject, name, predicate, opts={})
435
- register_relationship_desc_subject(subject)
436
- opts.merge!({:predicate=>predicate})
437
- relationships_desc[subject][name] = opts
438
- end
439
-
440
- # relationships are tracked as a hash of structure
441
- # @example
442
- # ds.relationships # => {:self=>{:has_model=>["afmodel:SimpleThing"],:has_part=>["demo:20"]},:inbound=>{:is_part_of=>["demo:6"]}
443
- def relationships
444
- @class_relationships ||= Hash[:self => {}]
445
- end
446
-
447
-
448
- def register_subject(subject)
449
- if !relationships.has_key?(subject)
450
- relationships[subject] = {}
451
- end
452
- end
453
-
454
- def register_predicate(subject, predicate)
455
- register_subject(subject)
456
- if !relationships[subject].has_key?(predicate)
457
- relationships[subject][predicate] = []
458
- end
459
- end
460
-
461
- # Allows for a relationship to be treated like any other attribute of a model class. You define
462
- # relationships in your model class using this method. You then have access to several
463
- # helper methods to list, append, and remove objects from the list of relationships.
464
- # ====Examples to define two relationships
465
- # class AudioRecord < ActiveFedora::Base
466
- #
467
- # has_relationship "oral_history", :has_part, :inbound=>true, :type=>OralHistory
468
- # # returns all similar audio
469
- # has_relationship "similar_audio", :has_part, :type=>AudioRecord
470
- # #returns only similar audio with format wav
471
- # has_relationship "similar_audio_wav", :has_part, :solr_fq=>"format_t:wav"
472
- #
473
- # The first two parameters are required:
474
- # name: relationship name
475
- # predicate: predicate for the relationship
476
- # opts:
477
- # possible parameters
478
- # :inbound => if true loads an external relationship via Solr (defaults to false)
479
- # :type => The type of model to use when instantiated an object from the pid in this relationship (defaults to ActiveFedora::Base)
480
- # :solr_fq => Define a solr query here if you want to filter out some objects in your relationship (must be a properly formatted solr query)
481
- #
482
- # If inbound is true it expects the relationship to be defined by another object's RELS-EXT
483
- # and to load that relationship from Solr. Otherwise, if inbound is true the relationship is stored in
484
- # this object's RELS-EXT datastream
485
- #
486
- # Word of caution - The same predicate may not be used twice for two inbound or two outbound relationships. However, it may be used twice if one is inbound
487
- # and one is outbound as shown in the example above. A full list of possible predicates are defined by predicate_mappings
488
- #
489
- # For the oral_history relationship in the example above the following helper methods are created:
490
- # oral_history: returns array of OralHistory objects that have this AudioRecord with predicate :has_part
491
- # oral_history_ids: Return array of pids for OralHistory objects that have this AudioRecord with predicate :has_part
492
- # oral_history_query: Return solr query that can be used to retrieve related objects as solr documents
493
- #
494
- # For the outbound relationship "similar_audio" there are two additional methods to append and remove objects from that relationship
495
- # since it is managed internally:
496
- # similar_audio: Return array of AudioRecord objects that have been added to similar_audio relationship
497
- # similar_audio_ids: Return array of AudioRecord object pids that have been added to similar_audio relationship
498
- # similar_audio_query: Return solr query that can be used to retrieve related objects as solr documents
499
- # similar_audio_append: Add an AudioRecord object to the similar_audio relationship
500
- # similar_audio_remove: Remove an AudioRecord from the similar_audio relationship
501
- #
502
- # @deprecated use ActiveFedora::Base.has_many or ActiveFedora::Base.belongs_to. has_relationship will be removed in active-fedora 6.0
503
- def has_relationship(name, predicate, opts = {})
504
- opts = {:singular => nil, :inbound => false}.merge(opts)
505
- if opts[:inbound] == true
506
- register_relationship_desc(:inbound, name, predicate, opts)
507
- register_predicate(:inbound, predicate)
508
- create_inbound_relationship_finders(name, predicate, opts)
509
- else
510
- #raise "Duplicate use of predicate for named outbound relationship \"#{predicate.inspect}\" not allowed" if named_predicate_exists_with_different_name?(:self,name,predicate)
511
- register_relationship_desc(:self, name, predicate, opts)
512
- register_predicate(:self, predicate)
513
- create_relationship_name_methods(name)
514
- create_outbound_relationship_finders(name, predicate, opts)
515
- end
516
- end
517
- deprecation_deprecate :has_relationship
518
-
519
- # Used in has_relationship call to create dynamic helper methods to
520
- # append and remove objects to and from a relationship
521
- # @param [String] relationship name to create helper methods for
522
- # @example
523
- # For the following relationship
524
- #
525
- # has_relationship "audio_records", :has_part, :type=>AudioRecord
526
- #
527
- # Methods audio_records_append and audio_records_remove are created.
528
- # Boths methods take an object that is kind_of? ActiveFedora::Base as a parameter
529
- #
530
- # @deprecated create_relationship_name_methods will be removed in active-fedora 6.0
531
- def create_relationship_name_methods(name)
532
- append_method_name = "#{name.to_s.downcase}_append"
533
- remove_method_name = "#{name.to_s.downcase}_remove"
534
-
535
- self.send(:define_method,:"#{append_method_name}") {|object| Deprecation.silence(ActiveFedora::Relationships) { add_relationship_by_name(name,object) } }
536
- self.send(:define_method,:"#{remove_method_name}") {|object| Deprecation.silence(ActiveFedora::Relationships) {remove_relationship_by_name(name,object) } }
537
- end
538
-
539
-
540
- # Generates relationship finders for predicates that point in both directions
541
- #
542
- # @param [String] name of the relationship method(s) to create
543
- # @param [Symbol] outbound_predicate Predicate used in outbound relationships
544
- # @param [Symbol] inbound_predicate Predicate used in inbound relationships
545
- # @param [Hash] opts
546
- #
547
- # Example:
548
- # has_bidirectional_relationship("parts", :has_part, :is_part_of)
549
- #
550
- # will create three instance methods: parts_outbound, and parts_inbound and parts
551
- # the inbound and outbound methods are the same that would result from calling
552
- # create_inbound_relationship_finders and create_outbound_relationship_finders
553
- # The third method combines the results of both and handles generating appropriate
554
- # solr queries where necessary.
555
- #
556
- # @deprecated use ActiveFedora::Base.has_and_belongs_to_many. has_bidirectional_relationship will be removed in active-fedora 6.0
557
- def has_bidirectional_relationship(name, outbound_predicate, inbound_predicate, opts={})
558
- create_bidirectional_relationship_finders(name, outbound_predicate, inbound_predicate, opts)
559
- end
560
- deprecation_deprecate :has_bidirectional_relationship
561
-
562
- def create_inbound_relationship_finders(name, predicate, opts = {})
563
- class_eval <<-END, __FILE__, __LINE__
564
- def #{name}(opts={})
565
- Deprecation.silence(ActiveFedora::Relationships) do
566
- load_inbound_relationship('#{name}', '#{predicate}', opts)
567
- end
568
- end
569
- def #{name}_ids
570
- #{name}(:response_format => :id_array)
571
- end
572
- def #{name}_from_solr
573
- #{name}(:response_format => :load_from_solr)
574
- end
575
- def #{name}_query
576
- relationship_query("#{name}")
577
- end
578
- END
579
- end
580
-
581
- def create_outbound_relationship_finders(name, predicate, opts = {})
582
- class_eval <<-END, __FILE__, __LINE__
583
- def #{name}(opts={})
584
- Deprecation.silence(ActiveFedora::Relationships) do
585
- load_outbound_relationship(#{name.inspect}, #{predicate.inspect}, opts)
586
- end
587
- end
588
- def #{name}_ids
589
- #{name}(:response_format => :id_array)
590
- end
591
- def #{name}_from_solr
592
- #{name}(:response_format => :load_from_solr)
593
- end
594
- def #{name}_query
595
- relationship_query("#{name}")
596
- end
597
- END
598
- end
599
-
600
-
601
-
602
- # Generates relationship finders for predicates that point in both directions
603
- # and registers predicate relationships for each direction.
604
- #
605
- # @param [String] name Name of the relationship method(s) to create
606
- # @param [Symbol] outbound_predicate Predicate used in outbound relationships
607
- # @param [Symbol] inbound_predicate Predicate used in inbound relationships
608
- # @param [Hash] opts (optional)
609
- # @deprecated create_bidirectional_relationship_finders will be removed in active-fedora 6.0
610
- def create_bidirectional_relationship_finders(name, outbound_predicate, inbound_predicate, opts={})
611
- inbound_method_name = name.to_s+"_inbound"
612
- outbound_method_name = name.to_s+"_outbound"
613
- Deprecation.silence(ActiveFedora::Relationships::ClassMethods) do
614
- has_relationship(outbound_method_name, outbound_predicate, opts)
615
- has_relationship(inbound_method_name, inbound_predicate, opts.merge!(:inbound=>true))
616
-
617
- #create methods that mirror the outbound append and remove with our bidirectional name, assume just add and remove locally
618
- create_bidirectional_relationship_name_methods(name,outbound_method_name)
619
-
620
- end
621
-
622
- class_eval <<-END, __FILE__, __LINE__
623
- def #{name}(opts={})
624
- Deprecation.silence(ActiveFedora::Relationships) do
625
- load_bidirectional("#{name}", :#{inbound_method_name}, :#{outbound_method_name}, opts)
626
- end
627
- end
628
- def #{name}_ids
629
- #{name}(:response_format => :id_array)
630
- end
631
- def #{name}_from_solr
632
- #{name}(:response_format => :load_from_solr)
633
- end
634
- def #{name}_query
635
- relationship_query("#{name}")
636
- end
637
- END
638
- end
639
- deprecation_deprecate :create_bidirectional_relationship_finders
640
-
641
- # Similar to +create_relationship_name_methods+ except it is used when an ActiveFedora::Base model class
642
- # declares has_bidirectional_relationship. we are merely creating an alias for outbound portion of bidirectional
643
- # @param [String] bidirectional relationship name
644
- # @param [String] outbound relationship method name associated with the bidirectional relationship ([bidirectional_name]_outbound)
645
- # @example
646
- # has_bidirectional_relationship "members", :has_collection_member, :is_member_of_collection
647
- #
648
- # Method members_outbound_append and members_outbound_remove added
649
- # This method will create members_append which does same thing as members_outbound_append
650
- # and will create members_remove which does same thing as members_outbound_remove
651
- #
652
- # @deprecated create_bidirectional_relationship_name_methods will be removed in active-fedora 6.0
653
- def create_bidirectional_relationship_name_methods(name,outbound_name)
654
- append_method_name = "#{name.to_s.downcase}_append"
655
- remove_method_name = "#{name.to_s.downcase}_remove"
656
- self.send(:define_method,:"#{append_method_name}") {|object| add_relationship_by_name(outbound_name,object)}
657
- self.send(:define_method,:"#{remove_method_name}") {|object| remove_relationship_by_name(outbound_name,object)}
658
- end
659
- deprecation_deprecate :create_bidirectional_relationship_name_methods
660
-
661
- end
662
- end
663
- end