active-fedora 5.7.1 → 6.0.0.pre1

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