active-fedora 2.3.4 → 2.3.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +5 -4
- data/History.txt +16 -0
- data/README.textile +1 -1
- data/active-fedora.gemspec +1 -1
- data/lib/active_fedora.rb +4 -4
- data/lib/active_fedora/relationships_helper.rb +889 -0
- data/lib/active_fedora/semantic_node.rb +53 -383
- data/lib/active_fedora/version.rb +1 -1
- data/spec/integration/base_spec.rb +87 -170
- data/spec/integration/datastream_spec.rb +3 -3
- data/spec/integration/datastreams_crud_spec.rb +1 -1
- data/spec/integration/rels_ext_datastream_spec.rb +4 -4
- data/spec/integration/semantic_node_spec.rb +369 -10
- data/spec/unit/active_fedora_spec.rb +42 -19
- data/spec/unit/base_extra_spec.rb +1 -0
- data/spec/unit/base_spec.rb +16 -20
- data/spec/unit/relationships_helper_spec.rb +842 -0
- data/spec/unit/semantic_node_spec.rb +49 -323
- metadata +88 -85
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
active-fedora (2.3.
|
4
|
+
active-fedora (2.3.5)
|
5
5
|
activeresource
|
6
6
|
equivalent-xml
|
7
7
|
facets
|
@@ -17,7 +17,7 @@ PATH
|
|
17
17
|
GEM
|
18
18
|
remote: http://rubygems.org/
|
19
19
|
specs:
|
20
|
-
RedCloth (4.2.
|
20
|
+
RedCloth (4.2.8)
|
21
21
|
activeresource (2.3.14)
|
22
22
|
activesupport (= 2.3.14)
|
23
23
|
activesupport (2.3.14)
|
@@ -26,7 +26,7 @@ GEM
|
|
26
26
|
daemons (1.1.4)
|
27
27
|
equivalent-xml (0.2.7)
|
28
28
|
nokogiri (>= 1.4.3)
|
29
|
-
facets (2.9.
|
29
|
+
facets (2.9.2)
|
30
30
|
fastercsv (1.5.4)
|
31
31
|
jettywrapper (0.0.10)
|
32
32
|
logger
|
@@ -39,7 +39,8 @@ GEM
|
|
39
39
|
mocha (0.9.12)
|
40
40
|
multipart-post (1.1.2)
|
41
41
|
nokogiri (1.5.0)
|
42
|
-
om (1.
|
42
|
+
om (1.4.0)
|
43
|
+
mediashelf-loggable
|
43
44
|
nokogiri (>= 1.4.2)
|
44
45
|
rake (0.9.2)
|
45
46
|
rbx-require-relative (0.0.5)
|
data/History.txt
CHANGED
@@ -1,4 +1,20 @@
|
|
1
|
+
2.3.7
|
2
|
+
|
3
|
+
HYDRA-650 -- Fixed relationship inheritance (Rick Johnson)
|
4
|
+
|
5
|
+
2.3.6
|
6
|
+
|
7
|
+
YANKED
|
8
|
+
Removed Bundler.require, which was causing odd dependency order resolving.
|
9
|
+
|
10
|
+
2.3.5
|
11
|
+
|
12
|
+
YANKED
|
13
|
+
branched so that trunk now require rails 3.
|
14
|
+
Named finders HYDRA-541 (Rick Johnson)
|
15
|
+
|
1
16
|
2.3.4
|
17
|
+
|
2
18
|
moved dirty assignment to NokogiriDatastream#update_values; added test (Benjamin Armintor)
|
3
19
|
Fixed HYDRA-590
|
4
20
|
|
data/README.textile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
h2. Description
|
2
2
|
|
3
|
-
RubyFedora and ActiveFedora provide a set of Ruby gems for creating and managing objects in the Fedora Repository Architecture ("http://fedora-commons.org":http://fedora-commons.org). ActiveFedora is loosely based on "ActiveRecord" in Rails.
|
3
|
+
RubyFedora and ActiveFedora provide a set of Ruby gems for creating and managing objects in the Fedora Repository Architecture ("http://fedora-commons.org":http://fedora-commons.org). ActiveFedora is loosely based on "ActiveRecord" in Rails. This version of ActiveFedora depends on Rails 2.3.11 and has been superceeded by ActiveFedora 3.x which requires Rails 3.
|
4
4
|
|
5
5
|
h2. Getting Help
|
6
6
|
|
data/active-fedora.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.add_dependency('solr-ruby', '>= 0.0.6')
|
19
19
|
s.add_dependency('xml-simple', '>= 1.0.12')
|
20
20
|
s.add_dependency('mime-types', '>= 1.16')
|
21
|
-
s.add_dependency('multipart-post', "1.1.2")
|
21
|
+
s.add_dependency('multipart-post', "= 1.1.2")
|
22
22
|
s.add_dependency('nokogiri')
|
23
23
|
s.add_dependency('om', '>= 1.0')
|
24
24
|
s.add_dependency('solrizer', '>1.0.0')
|
data/lib/active_fedora.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require "bundler/setup"
|
3
|
-
Bundler.require(:default)
|
2
|
+
# require "bundler/setup"
|
3
|
+
# Bundler.require(:default)
|
4
4
|
|
5
5
|
gem 'solr-ruby'
|
6
6
|
require "loggable"
|
@@ -68,14 +68,14 @@ module ActiveFedora #:nodoc:
|
|
68
68
|
# 2. If it does not find a solr.yml and the fedora.yml contains a solr url, it will raise an configuration error
|
69
69
|
# 3. If it does not find a solr.yml and the fedora.yml does not contain a solr url, it will look in: +Rails.root+/config, +current working directory+/config, then the solr.yml shipped with gem
|
70
70
|
def self.init( options={} )
|
71
|
-
logger.level = Logger::ERROR
|
71
|
+
logger.level = Logger::ERROR if logger.respond_to? :level ###MediaShelf StubLogger doesn't have a level= method
|
72
72
|
# Make config_options into a Hash if nil is passed in as the value
|
73
73
|
options = {} if options.nil?
|
74
74
|
|
75
75
|
# For backwards compatibility, handle cases where config_path (a String) is passed in as the argument rather than a config_options hash
|
76
76
|
# In all other cases, set config_path to config_options[:config_path], which is ok if it's nil
|
77
77
|
if options.is_a? String
|
78
|
-
logger.warn "DEPRECATION WARNING: Calling ActiveFedora.init with a path as an argument is deprecated. Use ActiveFedora.init(:
|
78
|
+
logger.warn "DEPRECATION WARNING: Calling ActiveFedora.init with a path as an argument is deprecated. Use ActiveFedora.init(:fedora_config_path=>#{options})"
|
79
79
|
@config_options = {:fedora_config_path=>options}
|
80
80
|
else
|
81
81
|
@config_options = options
|
@@ -0,0 +1,889 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
# This module is meant to extend semantic node to add functionality based on a relationship's name
|
3
|
+
# It is meant to turn a relationship into just another attribute in a model.
|
4
|
+
# The notion of a "relationship name" is used _internally_ to distinguish between the relationships you've set up using has_relationship and the implicit relationships that are based on the predicates themselves.
|
5
|
+
#
|
6
|
+
# @example ActiveFedora
|
7
|
+
# has_relationship "parents", :is_member_of
|
8
|
+
#
|
9
|
+
# obj.parents is a relationship in ActiveFedora while :is_member_of is the literal RDF relationship in Fedora
|
10
|
+
#
|
11
|
+
# There are also several helper methods created for any relationship declared in ActiveFedora. For the above example
|
12
|
+
# the following methods are created:
|
13
|
+
#
|
14
|
+
# obj.parents_append(object) Appends an object to the "parents" relationship
|
15
|
+
# obj.parents_remove(object) Removes an object from the "parents" relationship
|
16
|
+
# obj.parents_query Returns the query used against solr to retrieve objects linked via the "parents" relationship
|
17
|
+
#
|
18
|
+
# Note: ActiveFedora relationships can reflect filters ...
|
19
|
+
# If you define the solr_fq parameter in your has_relationship call some objects will be filtered out:
|
20
|
+
#
|
21
|
+
# has_relationship "parents", :is_member_of, :solr_fq=>"eyes:blue"
|
22
|
+
#
|
23
|
+
# Then obj.parents will only return parents where their eyes are blue.
|
24
|
+
module RelationshipsHelper
|
25
|
+
|
26
|
+
include MediaShelfClassLevelInheritableAttributes
|
27
|
+
ms_inheritable_attributes :class_relationships_desc
|
28
|
+
|
29
|
+
def self.included(klass)
|
30
|
+
klass.extend(ClassMethods)
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
# ** EXPERIMENTAL **
|
35
|
+
#
|
36
|
+
# Return array of objects for a given relationship name
|
37
|
+
# @param [String] Name of relationship to find
|
38
|
+
# @return [Array] Returns array of objects linked via the relationship name given
|
39
|
+
def find_relationship_by_name(name)
|
40
|
+
rels = nil
|
41
|
+
if inbound_relationship_names.include?(name)
|
42
|
+
rels = relationships_by_name(false)[:inbound][name]
|
43
|
+
elsif outbound_relationship_names.include?(name)
|
44
|
+
rels = relationships_by_name[:self][name]
|
45
|
+
end
|
46
|
+
rels = [] if rels.nil?
|
47
|
+
return rels
|
48
|
+
end
|
49
|
+
|
50
|
+
# ** EXPERIMENTAL **
|
51
|
+
#
|
52
|
+
# Internal method that ensures a relationship subject such as :self and :inbound
|
53
|
+
# exist within the relationships_desc hash tracking relationships metadata.
|
54
|
+
# This method just calls the class method counterpart of this method.
|
55
|
+
# @param [Symbol] Subject name to register (will probably be something like :self or :inbound)
|
56
|
+
def register_relationship_desc_subject(subject)
|
57
|
+
self.class.register_relationship_desc_subject(subject)
|
58
|
+
end
|
59
|
+
|
60
|
+
# ** EXPERIMENTAL **
|
61
|
+
#
|
62
|
+
# Internal method that adds a relationship description for a
|
63
|
+
# relationship name and predicate pair to either an outbound (:self)
|
64
|
+
# or inbound (:inbound) relationship types. This method just calls the class method counterpart of this method.
|
65
|
+
# @param [Symbol] Subject name to register
|
66
|
+
# @param [String] Name of relationship being registered
|
67
|
+
# @param [Symbol] Fedora ontology predicate to use
|
68
|
+
# @param [Hash] Any options passed to has_relationship such as :type, :solr_fq, etc.
|
69
|
+
def register_relationship_desc(subject, name, predicate, opts={})
|
70
|
+
self.class.register_relationship_desc(subject, name, predicate, opts)
|
71
|
+
end
|
72
|
+
|
73
|
+
# ** EXPERIMENTAL **
|
74
|
+
#
|
75
|
+
# Gets the relationships hash with subject mapped to relationship
|
76
|
+
# names instead of relationship predicates (unlike the "relationships" method in SemanticNode)
|
77
|
+
# It has an optional parameter of outbound_only that defaults true.
|
78
|
+
# If false it will include inbound relationships in the results.
|
79
|
+
# Also, it will only reload outbound relationships if the relationships hash has changed
|
80
|
+
# since the last time this method was called.
|
81
|
+
# @param [Boolean] if false it will include inbound relationships (defaults to true)
|
82
|
+
# @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
|
83
|
+
def relationships_by_name(outbound_only=true)
|
84
|
+
#make sure to update if relationships have been updated
|
85
|
+
if @relationships_are_dirty == true
|
86
|
+
@relationships_by_name = relationships_by_name_from_class()
|
87
|
+
@relationships_are_dirty = false
|
88
|
+
end
|
89
|
+
|
90
|
+
#this will get called normally on first fetch if relationships are not dirty
|
91
|
+
@relationships_by_name ||= relationships_by_name_from_class()
|
92
|
+
outbound_only ? @relationships_by_name : @relationships_by_name.merge(:inbound=>inbound_relationships_by_name)
|
93
|
+
end
|
94
|
+
|
95
|
+
# ** EXPERIMENTAL **
|
96
|
+
#
|
97
|
+
# Gets relationships by name from the class using the current relationships hash
|
98
|
+
# and relationship name,predicate pairs.
|
99
|
+
# @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
|
100
|
+
def relationships_by_name_from_class()
|
101
|
+
rels = {}
|
102
|
+
relationship_predicates.each_pair do |subj, names|
|
103
|
+
if relationships.has_key?(subj)
|
104
|
+
rels[subj] = {}
|
105
|
+
names.each_pair do |name, predicate|
|
106
|
+
rels[subj][name] = (relationships[subj].has_key?(predicate) ? relationships[subj][predicate] : [])
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
return rels
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
# ** EXPERIMENTAL **
|
115
|
+
#
|
116
|
+
# Return hash of relationships_by_name defined within other objects' RELS-EXT
|
117
|
+
# It returns a hash of relationship name to arrays of objects. It requeries
|
118
|
+
# solr each time this method is called.
|
119
|
+
# @return [Hash] Return hash of each relationship name mapped to an Array of objects linked to this object via inbound relationships
|
120
|
+
def inbound_relationships_by_name
|
121
|
+
rels = {}
|
122
|
+
if relationships_desc.has_key?(:inbound)&&!relationships_desc[:inbound].empty?()
|
123
|
+
inbound_rels = inbound_relationships
|
124
|
+
|
125
|
+
if relationship_predicates.has_key?(:inbound)
|
126
|
+
relationship_predicates[:inbound].each do |name, predicate|
|
127
|
+
rels[name] = inbound_rels.has_key?(predicate) ? inbound_rels[predicate] : []
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
return rels
|
132
|
+
end
|
133
|
+
|
134
|
+
# ** EXPERIMENTAL **
|
135
|
+
#
|
136
|
+
# Return hash of outbound relationship names and predicate pairs
|
137
|
+
# @return [Hash] A hash of outbound relationship names mapped to predicates used
|
138
|
+
def outbound_relationship_predicates
|
139
|
+
relationship_predicates.has_key?(:self) ? relationship_predicates[:self] : {}
|
140
|
+
end
|
141
|
+
|
142
|
+
# ** EXPERIMENTAL **
|
143
|
+
#
|
144
|
+
# Return hash of inbound relationship names and predicate pairs
|
145
|
+
# @return [Hash] A hash of inbound relationship names mapped to predicates used
|
146
|
+
def inbound_relationship_predicates
|
147
|
+
relationship_predicates.has_key?(:inbound) ? relationship_predicates[:inbound] : {}
|
148
|
+
end
|
149
|
+
|
150
|
+
# ** EXPERIMENTAL **
|
151
|
+
#
|
152
|
+
# Return hash of relationship names and predicate pairs (inbound and outbound).
|
153
|
+
# This method calls the class method version of this method to get the static settings
|
154
|
+
# defined in the class definition.
|
155
|
+
# @return [Hash] A hash of relationship names (inbound and outbound) mapped to predicates used
|
156
|
+
def relationship_predicates
|
157
|
+
@relationship_predicates ||= relationship_predicates_from_class
|
158
|
+
end
|
159
|
+
|
160
|
+
# ** EXPERIMENTAL **
|
161
|
+
#
|
162
|
+
# Return hash of relationship names and predicate pairs from class.
|
163
|
+
# It retrieves this information via the relationships_desc hash in the class.
|
164
|
+
# @return [Hash] A hash of relationship names (inbound and outbound) mapped to predicates used
|
165
|
+
def relationship_predicates_from_class
|
166
|
+
rels = {}
|
167
|
+
relationships_desc.each_pair do |subj, names|
|
168
|
+
rels[subj] = {}
|
169
|
+
names.each_pair do |name, args|
|
170
|
+
rels[subj][name] = args[:predicate]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
return rels
|
174
|
+
end
|
175
|
+
|
176
|
+
# ** EXPERIMENTAL **
|
177
|
+
#
|
178
|
+
# Return array all relationship names
|
179
|
+
# @return [Array] of relationship names for relationships declared via has_relationship in the class
|
180
|
+
def relationship_names
|
181
|
+
names = []
|
182
|
+
relationships_desc.each_key do |subject|
|
183
|
+
names = names.concat(relationships_desc[subject].keys)
|
184
|
+
end
|
185
|
+
names
|
186
|
+
end
|
187
|
+
|
188
|
+
# ** EXPERIMENTAL **
|
189
|
+
#
|
190
|
+
# Return array of relationship names for all inbound relationships (coming from other objects' RELS-EXT and Solr)
|
191
|
+
# @return [Array] of inbound relationship names for relationships declared via has_relationship in the class
|
192
|
+
def inbound_relationship_names
|
193
|
+
relationships_desc.has_key?(:inbound) ? relationships_desc[:inbound].keys : []
|
194
|
+
end
|
195
|
+
|
196
|
+
# ** EXPERIMENTAL **
|
197
|
+
#
|
198
|
+
# Return array of relationship names for all outbound relationships (coming from this object's RELS-EXT)
|
199
|
+
# @return [Array] of outbound relationship names for relationships declared via has_relationship in the class
|
200
|
+
def outbound_relationship_names
|
201
|
+
relationships_desc.has_key?(:self) ? relationships_desc[:self].keys : []
|
202
|
+
end
|
203
|
+
|
204
|
+
# ** EXPERIMENTAL **
|
205
|
+
#
|
206
|
+
# Return hash of relationships_by_name defined within this object's RELS-EXT
|
207
|
+
# It returns a hash of relationship name to arrays of objects
|
208
|
+
# @return [Hash] Return hash of each relationship name mapped to an Array of objects linked to this object via outbound relationships
|
209
|
+
def outbound_relationships_by_name
|
210
|
+
relationships_desc.has_key?(:self) ? relationships_by_name[:self] : {}
|
211
|
+
end
|
212
|
+
|
213
|
+
# ** EXPERIMENTAL **
|
214
|
+
#
|
215
|
+
# Returns true if the given relationship name is a relationship
|
216
|
+
# @param [String] Name of relationship
|
217
|
+
# @param [Boolean] If false checks inbound relationships as well (defaults to true)
|
218
|
+
def is_relationship_name?(name, outbound_only=true)
|
219
|
+
if outbound_only
|
220
|
+
outbound_relationship_names.include?(name)
|
221
|
+
else
|
222
|
+
(outbound_relationship_names.include?(name)||inbound_relationship_names.include?(name))
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# ** EXPERIMENTAL **
|
227
|
+
#
|
228
|
+
# Return hash that persists relationship metadata defined by has_relationship calls
|
229
|
+
# @return [Hash] Hash of relationship subject (:self or :inbound) mapped to nested hashs of each relationship name mapped to another hash relationship options
|
230
|
+
# @example For the following relationship
|
231
|
+
#
|
232
|
+
# has_relationship "audio_records", :has_part, :type=>AudioRecord
|
233
|
+
#
|
234
|
+
# Results in the following returned by relationships_desc
|
235
|
+
# {:self=>{"audio_records"=>{:type=>AudioRecord, :singular=>nil, :predicate=>:has_part, :inbound=>false}}}
|
236
|
+
def relationships_desc
|
237
|
+
@relationships_desc ||= relationships_desc_from_class
|
238
|
+
end
|
239
|
+
|
240
|
+
# ** EXPERIMENTAL **
|
241
|
+
#
|
242
|
+
# Get class instance variable relationships_desc that holds has_relationship metadata
|
243
|
+
# @return [Hash] Hash of relationship subject (:self or :inbound) mapped to nested hashs of each relationship name mapped to another hash relationship options
|
244
|
+
def relationships_desc_from_class
|
245
|
+
self.class.relationships_desc
|
246
|
+
end
|
247
|
+
|
248
|
+
# ** EXPERIMENTAL **
|
249
|
+
#
|
250
|
+
# Return the value of :type for the relationship for name passed in if defined
|
251
|
+
# It defaults to ActiveFedora::Base.
|
252
|
+
# @return [Class] the name of the class defined for a relationship by the :type option if present
|
253
|
+
def relationship_model_type(name)
|
254
|
+
if is_relationship_name?(name,true)
|
255
|
+
subject = outbound_relationship_names.include?(name)? :self : :inbound
|
256
|
+
if relationships_desc[subject][name].has_key?(:type)
|
257
|
+
return class_from_name(relationships_desc[subject][name][:type])
|
258
|
+
end
|
259
|
+
end
|
260
|
+
return nil
|
261
|
+
end
|
262
|
+
|
263
|
+
# ** EXPERIMENTAL **
|
264
|
+
#
|
265
|
+
# Add an outbound relationship for given relationship name
|
266
|
+
# See ActiveFedora::SemanticNode::ClassMethods.has_relationship
|
267
|
+
# @param [String] Name of relationship
|
268
|
+
# @param [ActiveFedora::Base] object to add to the relationship (expects ActvieFedora::Base to be an ancestor)
|
269
|
+
# @return [Boolean] returns true if add operation successful
|
270
|
+
def add_relationship_by_name(name, object)
|
271
|
+
if is_relationship_name?(name,true)
|
272
|
+
if relationships_desc[:self][name].has_key?(:type)
|
273
|
+
klass = class_from_name(relationships_desc[:self][name][:type])
|
274
|
+
unless klass.nil?
|
275
|
+
(assert_conforms_to 'object', object, klass)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
#r = ActiveFedora::Relationship.new({:subject=>:self,:predicate=>outbound_relationship_predicates[name],:object=>object})
|
279
|
+
#add_relationship(r)
|
280
|
+
add_relationship(outbound_relationship_predicates[name],object)
|
281
|
+
else
|
282
|
+
false
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# ** EXPERIMENTAL **
|
287
|
+
#
|
288
|
+
# Remove an object for the given relationship name
|
289
|
+
# @param [String] Relationship name
|
290
|
+
# @param [ActiveFedora::Base] object to remove
|
291
|
+
# @return [Boolean] return true if remove operation successful
|
292
|
+
def remove_relationship_by_name(name, object)
|
293
|
+
if is_relationship_name?(name,true)
|
294
|
+
remove_relationship(outbound_relationship_predicates[name],object)
|
295
|
+
else
|
296
|
+
return false
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# ** EXPERIMENTAL **
|
301
|
+
#
|
302
|
+
# Throws an assertion error if conforms_to? returns false for object and model_class
|
303
|
+
# @param [String] Name of object (just label for output)
|
304
|
+
# @param [ActiveFedora::Base] Expects to be an object that has ActiveFedora::Base as an ancestor of its class
|
305
|
+
# @param [Class] The model class used in conforms_to? check on object
|
306
|
+
def assert_conforms_to(name, object, model_class)
|
307
|
+
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)
|
308
|
+
end
|
309
|
+
|
310
|
+
# ** EXPERIMENTAL **
|
311
|
+
#
|
312
|
+
# Checks that this object is matches the model class passed in.
|
313
|
+
# It requires two steps to pass to return true
|
314
|
+
# 1. It has a hasModel relationship of the same model
|
315
|
+
# 2. kind_of? returns true for the model passed in
|
316
|
+
# This method can most often be used to detect if an object from Fedora that was created
|
317
|
+
# with a different model was then used to populate this object.
|
318
|
+
# @param [Class] the model class name to check if an object conforms_to that model
|
319
|
+
# @return [Boolean] true if this object conforms to the given model name
|
320
|
+
def conforms_to?(model_class)
|
321
|
+
if self.kind_of?(model_class)
|
322
|
+
#check has model and class match
|
323
|
+
if relationships[:self].has_key?(:has_model)
|
324
|
+
r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:has_model, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(self.class))
|
325
|
+
if relationships[:self][:has_model].first.to_s.eql?(r.object.to_s)
|
326
|
+
return true
|
327
|
+
else
|
328
|
+
raise "has_model relationship check failed for model #{model_class} raising exception, expected: '#{r.object.to_s}' actual: '#{relationships[:self][:has_model].to_s}'"
|
329
|
+
end
|
330
|
+
else
|
331
|
+
raise "has_model relationship does not exist for model #{model_class} check raising exception"
|
332
|
+
end
|
333
|
+
else
|
334
|
+
raise "kind_of? check failed for model #{model_class}, actual #{self.class} raising exception"
|
335
|
+
end
|
336
|
+
return false
|
337
|
+
end
|
338
|
+
|
339
|
+
# Returns a Class symbol for the given string for the class name
|
340
|
+
# @param [String] the class name as a string
|
341
|
+
# @return [Class] the class as a Class object
|
342
|
+
def class_from_name(name)
|
343
|
+
klass = name.to_s.split('::').inject(Kernel) {|scope, const_name|
|
344
|
+
scope.const_get(const_name)}
|
345
|
+
(!klass.nil? && klass.is_a?(::Class)) ? klass : nil
|
346
|
+
end
|
347
|
+
|
348
|
+
# Call this method to return the query used against solr to retrieve any
|
349
|
+
# objects linked via the relationship name given.
|
350
|
+
#
|
351
|
+
# Instead of this method you can also use the helper method
|
352
|
+
# [relationship_name]_query, i.e. method "parts_query" for relationship "parts" to return the same value
|
353
|
+
# @param [String] The name of the relationship defined in the model
|
354
|
+
# @return [String] The query used when querying solr for objects for this relationship
|
355
|
+
# @example
|
356
|
+
# Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
|
357
|
+
# #points to all parents linked via is_member_of
|
358
|
+
# has_relationship "parents", :is_member_of
|
359
|
+
# #returns only parents that have a level value set to "series"
|
360
|
+
# has_relationship "series_parents", :is_member_of, :solr_fq=>level_t:series"
|
361
|
+
# end
|
362
|
+
# s = SampleAFObjRelationshipFilterQuery.new
|
363
|
+
# obj = ActiveFedora::Base.new
|
364
|
+
# s.parents_append(obj)
|
365
|
+
# s.series_parents_query
|
366
|
+
# #=> "(id:changeme\\:13020 AND level_t:series)"
|
367
|
+
# SampleAFObjRelationshipFilterQuery.relationship_query("series_parents")
|
368
|
+
# #=> "(id:changeme\\:13020 AND level_t:series)"
|
369
|
+
def relationship_query(relationship_name)
|
370
|
+
query = ""
|
371
|
+
if self.class.is_bidirectional_relationship?(relationship_name)
|
372
|
+
id_array = []
|
373
|
+
predicate = outbound_relationship_predicates["#{relationship_name}_outbound"]
|
374
|
+
if !outbound_relationships[predicate].nil?
|
375
|
+
outbound_relationships[predicate].each do |rel|
|
376
|
+
id_array << rel.gsub("info:fedora/", "")
|
377
|
+
end
|
378
|
+
end
|
379
|
+
query = self.class.bidirectional_relationship_query(pid,relationship_name,id_array)
|
380
|
+
elsif outbound_relationship_names.include?(relationship_name)
|
381
|
+
id_array = []
|
382
|
+
predicate = outbound_relationship_predicates[relationship_name]
|
383
|
+
if !outbound_relationships[predicate].nil?
|
384
|
+
outbound_relationships[predicate].each do |rel|
|
385
|
+
id_array << rel.gsub("info:fedora/", "")
|
386
|
+
end
|
387
|
+
end
|
388
|
+
query = self.class.outbound_relationship_query(relationship_name,id_array)
|
389
|
+
elsif inbound_relationship_names.include?(relationship_name)
|
390
|
+
query = self.class.inbound_relationship_query(pid,relationship_name)
|
391
|
+
end
|
392
|
+
query
|
393
|
+
end
|
394
|
+
|
395
|
+
## Deprecated method checks for HYDRA-541 methods renamed
|
396
|
+
#
|
397
|
+
# Old Name New Name
|
398
|
+
# named_relationship find_relationship_by_name
|
399
|
+
# register_named_subject register_relationship_desc_subject
|
400
|
+
# register_named_relationship register_relationship_desc
|
401
|
+
# named_relationships relationships_by_name
|
402
|
+
# named_relationships_from_class relationships_by_name_from_class
|
403
|
+
# named_inbound_relationships inbound_relationship_names
|
404
|
+
# outbound_named_relationship_predicates outbound_relationship_predicates
|
405
|
+
# inbound_named_relationship_predicates inbound_relationship_predicates
|
406
|
+
# named_relationship_predicates relationship_predicates
|
407
|
+
# named_relationship_predicates_from_class relationship_predicates_from_class
|
408
|
+
# named_outbound_relationships outbound_relationships_by_name
|
409
|
+
# is_named_relationship? is_relationship_name?
|
410
|
+
# named_relationships_desc relationships_desc
|
411
|
+
# named_relationships_desc_from_class relationships_desc_from_class
|
412
|
+
# named_relationship_type relationship_model_type
|
413
|
+
# add_named_relationship add_relationship_by_name
|
414
|
+
# remove_named_relationship remove_relationship_by_name
|
415
|
+
# assert_kind_of_model assert_conforms_to
|
416
|
+
# kind_of_model? conforms_to?
|
417
|
+
# named_relationship_query relationship_query
|
418
|
+
# CLASS METHODS
|
419
|
+
# named_relationships_desc relationships_desc
|
420
|
+
# register_named_subject register_relationship_desc_subject
|
421
|
+
# register_named_relationship register_relationship_desc
|
422
|
+
# create_named_relationship_method create_relationship_name_methods
|
423
|
+
# create_bidirectional_named_relationship_methods create_bidirectional_relationship_name_methods
|
424
|
+
# outbound_named_relationship_query outbound_relationship_query
|
425
|
+
# inbound_named_relationship_query inbound_relationship_query
|
426
|
+
# bidirectional_named_relationship_query bidirectional_relationship_query
|
427
|
+
# named_predicate_exists_with_different_name? predicate_exists_with_different_relationship_name?
|
428
|
+
|
429
|
+
# @deprecated Please use {#find_relationship_by_name} instead.
|
430
|
+
def named_relationship(name)
|
431
|
+
logger.warn("Deprecation: named_relationship has been deprecated. Please call find_relationship_by_name instead.")
|
432
|
+
find_relationship_by_name(name)
|
433
|
+
end
|
434
|
+
|
435
|
+
# @deprecated Please use {#register_relationship_desc_subject} instead.
|
436
|
+
def register_named_subject(subject)
|
437
|
+
logger.warn("Deprecation: register_named_subject has been deprecated. Please call register_relationship_desc_subject instead.")
|
438
|
+
register_relationship_desc_subject(subject)
|
439
|
+
end
|
440
|
+
|
441
|
+
# @deprecated Please use {#register_relationship_desc} instead.
|
442
|
+
def register_named_relationship(subject, name, predicate, opts)
|
443
|
+
logger.warn("Deprecation: register_named_relationship has been deprecated. Please call register_relationship_desc instead.")
|
444
|
+
register_relationship_desc(subject, name, predicate, opts)
|
445
|
+
end
|
446
|
+
|
447
|
+
# @deprecated Please use {#relationships_by_name} instead.
|
448
|
+
def named_relationships(outbound_only=true)
|
449
|
+
logger.warn("Deprecation: named_relationships has been deprecated. Please call relationships_by_name instead.")
|
450
|
+
relationships_by_name(outbound_only)
|
451
|
+
end
|
452
|
+
|
453
|
+
# @deprecated Please use {#relationships_by_name_from_class} instead.
|
454
|
+
def named_relationships_from_class
|
455
|
+
logger.warn("Deprecation: named_relationships_from_class has been deprecated. Please call relationships_by_name_from_class instead.")
|
456
|
+
relationships_by_name_from_class
|
457
|
+
end
|
458
|
+
|
459
|
+
# @deprecated Please use {#inbound_relationships_by_name} instead.
|
460
|
+
def named_inbound_relationships
|
461
|
+
logger.warn("Deprecation: named_inbound_relationships has been deprecated. Please call inbound_relationships_by_name instead.")
|
462
|
+
inbound_relationships_by_name
|
463
|
+
end
|
464
|
+
|
465
|
+
# @deprecated Please use {#outbound_relationships_by_name} instead.
|
466
|
+
def named_outbound_relationships
|
467
|
+
logger.warn("Deprecation: named_outbound_relationships has been deprecated. Please call outbound_relationships_by_name instead.")
|
468
|
+
outbound_relationships_by_name
|
469
|
+
end
|
470
|
+
|
471
|
+
# @deprecated Please use {#outbound_relationship_predicates} instead.
|
472
|
+
def outbound_named_relationship_predicates
|
473
|
+
logger.warn("Deprecation: outbound_named_relationship_predicates has been deprecated. Please call outbound_relationship_predicates instead.")
|
474
|
+
outbound_relationship_predicates
|
475
|
+
end
|
476
|
+
|
477
|
+
# @deprecated Please use {#inbound_relationship_predicates} instead.
|
478
|
+
def inbound_named_relationship_predicates
|
479
|
+
logger.warn("Deprecation: inbound_named_relationship_predicates has been deprecated. Please call inbound_relationship_predicates instead.")
|
480
|
+
inbound_relationship_predicates
|
481
|
+
end
|
482
|
+
|
483
|
+
# @deprecated Please use {#relationship_predicates} instead.
|
484
|
+
def named_relationship_predicates
|
485
|
+
logger.warn("Deprecation: named_relationship_predicates has been deprecated. Please call relationship_predicates instead.")
|
486
|
+
relationship_predicates
|
487
|
+
end
|
488
|
+
|
489
|
+
# @deprecated Please use {#relationship_predicates_from_class} instead.
|
490
|
+
def named_relationship_predicates_from_class
|
491
|
+
logger.warn("Deprecation: named_relationship_predicates_from_class has been deprecated. Please call relationship_predicates_from_class instead.")
|
492
|
+
relationship_predicates_from_class
|
493
|
+
end
|
494
|
+
|
495
|
+
# @deprecated Please use {#is_relationship_name?} instead.
|
496
|
+
def is_named_relationship?(name, outbound_only=true)
|
497
|
+
logger.warn("Deprecation: is_named_relationship? has been deprecated. Please call is_relationship_name? instead.")
|
498
|
+
is_relationship_name?(name,outbound_only)
|
499
|
+
end
|
500
|
+
|
501
|
+
# @deprecated Please use {#relationships_desc} instead.
|
502
|
+
def named_relationships_desc
|
503
|
+
logger.warn("Deprecation: named_relationships_desc has been deprecated. Please call relationships_desc instead.")
|
504
|
+
relationships_desc
|
505
|
+
end
|
506
|
+
|
507
|
+
# @deprecated Please use {#relationships_desc_from_class} instead.
|
508
|
+
def named_relationships_desc_from_class
|
509
|
+
logger.warn("Deprecation: named_relationships_desc_from_class has been deprecated. Please call relationships_desc_from_class instead.")
|
510
|
+
relationships_desc_from_class
|
511
|
+
end
|
512
|
+
|
513
|
+
# @deprecated Please use {#relationship_model_type} instead.
|
514
|
+
def named_relationship_type(name)
|
515
|
+
logger.warn("Deprecation: named_relationship_type has been deprecated. Please call relationship_model_type instead.")
|
516
|
+
relationship_model_type(name)
|
517
|
+
end
|
518
|
+
|
519
|
+
# @deprecated Please use {#add_relationship_by_name} instead.
|
520
|
+
def add_named_relationship(name,object)
|
521
|
+
logger.warn("Deprecation: add_named_relationship has been deprecated. Please call add_relationship_by_name instead.")
|
522
|
+
add_relationship_by_name(name,object)
|
523
|
+
end
|
524
|
+
|
525
|
+
# @deprecated Please use {#remove_relationship_by_name} instead.
|
526
|
+
def remove_named_relationship(name,object)
|
527
|
+
logger.warn("Deprecation: remove_named_relationship has been deprecated. Please call remove_relationship_by_name instead.")
|
528
|
+
remove_relationship_by_name(name,object)
|
529
|
+
end
|
530
|
+
|
531
|
+
# @deprecated Please use {#assert_conforms_to} instead.
|
532
|
+
def assert_kind_of_model(name,object,model_class)
|
533
|
+
logger.warn("Deprecation: assert_kind_of_model has been deprecated. Please call assert_conforms_to instead.")
|
534
|
+
assert_conforms_to(name,object,model_class)
|
535
|
+
end
|
536
|
+
|
537
|
+
# @deprecated Please use {#conforms_to?} instead.
|
538
|
+
def kind_of_model?(model_class)
|
539
|
+
logger.warn("Deprecation: kind_of_model? has been deprecated. Please call conforms_to? instead.")
|
540
|
+
conforms_to?(model_class)
|
541
|
+
end
|
542
|
+
|
543
|
+
# @deprecated Please use {#relationship_query} instead.
|
544
|
+
def named_relationship_query(relationship_name)
|
545
|
+
logger.warn("Deprecation: named_relationship_query has been deprecated. Please call relationship_query instead.")
|
546
|
+
relationship_query(relationship_name)
|
547
|
+
end
|
548
|
+
|
549
|
+
module ClassMethods
|
550
|
+
|
551
|
+
# ** EXPERIMENTAL **
|
552
|
+
#
|
553
|
+
# Return hash that persists relationship metadata defined by has_relationship calls. If you implement a child class of ActiveFedora::Base it will inherit
|
554
|
+
# the relationship descriptions defined there by merging in the class
|
555
|
+
# instance variable values. It will also do this for any level of
|
556
|
+
# ancestors.
|
557
|
+
# @return [Hash] Hash of relationship subject (:self or :inbound) mapped to nested hashs of each relationship name mapped to another hash relationship options
|
558
|
+
# @example
|
559
|
+
# For the following relationship
|
560
|
+
#
|
561
|
+
# has_relationship "audio_records", :has_part, :type=>AudioRecord
|
562
|
+
#
|
563
|
+
# Results in the following returned by relationships_desc
|
564
|
+
# {:self=>{"audio_records"=>{:type=>AudioRecord, :singular=>nil, :predicate=>:has_part, :inbound=>false}}}
|
565
|
+
def relationships_desc
|
566
|
+
#get any relationship descriptions from superclasses
|
567
|
+
if @class_relationships_desc.nil?
|
568
|
+
@class_relationships_desc ||= Hash[:self => {}]
|
569
|
+
|
570
|
+
#get super classes
|
571
|
+
super_klasses = []
|
572
|
+
#insert in reverse order so the child overwrites anything in parent
|
573
|
+
super_klass = self.superclass
|
574
|
+
while !super_klass.nil?
|
575
|
+
super_klasses.insert(0,super_klass)
|
576
|
+
super_klass = super_klass.superclass
|
577
|
+
end
|
578
|
+
|
579
|
+
super_klasses.each do |super_klass|
|
580
|
+
if super_klass.respond_to?(:relationships_desc)
|
581
|
+
super_rels = super_klass.relationships_desc
|
582
|
+
super_rels.each_pair do |subject,rels|
|
583
|
+
@class_relationships_desc[subject] = {} unless @class_relationships_desc.has_key?(subject)
|
584
|
+
@class_relationships_desc[subject].merge!(rels)
|
585
|
+
end
|
586
|
+
end
|
587
|
+
end
|
588
|
+
end
|
589
|
+
@class_relationships_desc
|
590
|
+
end
|
591
|
+
|
592
|
+
# ** EXPERIMENTAL **
|
593
|
+
#
|
594
|
+
# Internal method that ensures a relationship subject such as :self and :inbound
|
595
|
+
# exist within the relationships_desc hash tracking relationships metadata.
|
596
|
+
# @param [Symbol] Subject name to register (will probably be something like :self or :inbound)
|
597
|
+
def register_relationship_desc_subject(subject)
|
598
|
+
unless relationships_desc.has_key?(subject)
|
599
|
+
relationships_desc[subject] = {}
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
# ** EXPERIMENTAL **
|
604
|
+
#
|
605
|
+
# Internal method that adds relationship name and predicate pair to either an outbound (:self)
|
606
|
+
# or inbound (:inbound) relationship types. Refer to ActiveFedora::SemanticNode.has_relationship for information on what metadata will be persisted.
|
607
|
+
# @param [Symbol] Subject name to register
|
608
|
+
# @param [String] Name of relationship being registered
|
609
|
+
# @param [Symbol] Fedora ontology predicate to use
|
610
|
+
# @param [Hash] Any options passed to has_relationship such as :type, :solr_fq, etc.
|
611
|
+
def register_relationship_desc(subject, name, predicate, opts={})
|
612
|
+
register_relationship_desc_subject(subject)
|
613
|
+
opts.merge!({:predicate=>predicate})
|
614
|
+
relationships_desc[subject][name] = opts
|
615
|
+
end
|
616
|
+
|
617
|
+
# Tests if the relationship name passed is in bidirectional
|
618
|
+
# @param [String] relationship name to test
|
619
|
+
# @return [Boolean]
|
620
|
+
def is_bidirectional_relationship?(relationship_name)
|
621
|
+
(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"))
|
622
|
+
end
|
623
|
+
|
624
|
+
# ** EXPERIMENTAL **
|
625
|
+
#
|
626
|
+
# Used in has_relationship call to create dynamic helper methods to
|
627
|
+
# append and remove objects to and from a relationship
|
628
|
+
# @param [String] relationship name to create helper methods for
|
629
|
+
# @example
|
630
|
+
# For the following relationship
|
631
|
+
#
|
632
|
+
# has_relationship "audio_records", :has_part, :type=>AudioRecord
|
633
|
+
#
|
634
|
+
# Methods audio_records_append and audio_records_remove are created.
|
635
|
+
# Boths methods take an object that is kind_of? ActiveFedora::Base as a parameter
|
636
|
+
def create_relationship_name_methods(name)
|
637
|
+
append_method_name = "#{name.to_s.downcase}_append"
|
638
|
+
remove_method_name = "#{name.to_s.downcase}_remove"
|
639
|
+
self.send(:define_method,:"#{append_method_name}") {|object| add_relationship_by_name(name,object)}
|
640
|
+
self.send(:define_method,:"#{remove_method_name}") {|object| remove_relationship_by_name(name,object)}
|
641
|
+
end
|
642
|
+
|
643
|
+
# ** EXPERIMENTAL **
|
644
|
+
# Similar to +create_relationship_name_methods+ except it is used when an ActiveFedora::Base model class
|
645
|
+
# declares has_bidirectional_relationship. we are merely creating an alias for outbound portion of bidirectional
|
646
|
+
# @param [String] bidirectional relationship name
|
647
|
+
# @param [String] outbound relationship method name associated with the bidirectional relationship ([bidirectional_name]_outbound)
|
648
|
+
# @example
|
649
|
+
# has_bidirectional_relationship "members", :has_collection_member, :is_member_of_collection
|
650
|
+
#
|
651
|
+
# Method members_outbound_append and members_outbound_remove added
|
652
|
+
# This method will create members_append which does same thing as members_outbound_append
|
653
|
+
# and will create members_remove which does same thing as members_outbound_remove
|
654
|
+
def create_bidirectional_relationship_name_methods(name,outbound_name)
|
655
|
+
append_method_name = "#{name.to_s.downcase}_append"
|
656
|
+
remove_method_name = "#{name.to_s.downcase}_remove"
|
657
|
+
self.send(:define_method,:"#{append_method_name}") {|object| add_relationship_by_name(outbound_name,object)}
|
658
|
+
self.send(:define_method,:"#{remove_method_name}") {|object| remove_relationship_by_name(outbound_name,object)}
|
659
|
+
end
|
660
|
+
|
661
|
+
# Returns a solr query for retrieving objects specified in an outbound relationship.
|
662
|
+
# This method is mostly used by internal method calls.
|
663
|
+
# It utilizes any solr_fq value defined within a relationship to attach a query filter when
|
664
|
+
# querying solr on top of just the predicate being used.
|
665
|
+
# Because it is static it
|
666
|
+
# needs the pids defined within RELS-EXT for this relationship to be passed in.
|
667
|
+
# If you are calling this method directly to get the query you should use the
|
668
|
+
# ActiveFedora::SemanticNode.relationship_query instead or use the helper method
|
669
|
+
# [relationship_name]_query, i.e. method "parts_query" for relationship "parts". This
|
670
|
+
# method would only be called directly if you had something like an array of outbound pids
|
671
|
+
# already in something like a solr document for object that has these relationships.
|
672
|
+
# @param [String] The name of the relationship defined in the model
|
673
|
+
# @param [Array] An array of pids to include in the query
|
674
|
+
# @return [String]
|
675
|
+
# @example
|
676
|
+
# Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
|
677
|
+
# #points to all parents linked via is_member_of
|
678
|
+
# has_relationship "parents", :is_member_of
|
679
|
+
# #returns only parents that have a level value set to "series"
|
680
|
+
# has_relationship "series_parents", :is_member_of, :solr_fq=>"level_t:series"
|
681
|
+
# end
|
682
|
+
# s = SampleAFObjRelationshipFilterQuery.new
|
683
|
+
# obj = ActiveFedora::Base.new
|
684
|
+
# s.series_parents_append(obj)
|
685
|
+
# s.series_parents_query
|
686
|
+
# #=> "(id:changeme\\:13020 AND level_t:series)"
|
687
|
+
# SampleAFObjRelationshipFilterQuery.outbound_relationship_query("series_parents",["id:changeme:13020"])
|
688
|
+
# #=> "(id:changeme\\:13020 AND level_t:series)"
|
689
|
+
def outbound_relationship_query(relationship_name,outbound_pids)
|
690
|
+
query = ActiveFedora::SolrService.construct_query_for_pids(outbound_pids)
|
691
|
+
subject = :self
|
692
|
+
if relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
|
693
|
+
solr_fq = relationships_desc[subject][relationship_name][:solr_fq]
|
694
|
+
unless query.empty?
|
695
|
+
#substitute in the filter query for each pid so that it is applied to each in the query
|
696
|
+
query_parts = query.split(/OR/)
|
697
|
+
query = ""
|
698
|
+
query_parts.each_with_index do |query_part,index|
|
699
|
+
query_part.strip!
|
700
|
+
query << " OR " if index > 0
|
701
|
+
query << "(#{query_part} AND #{solr_fq})"
|
702
|
+
end
|
703
|
+
else
|
704
|
+
query = solr_fq
|
705
|
+
end
|
706
|
+
end
|
707
|
+
query
|
708
|
+
end
|
709
|
+
|
710
|
+
# Returns a solr query for retrieving objects specified in an inbound relationship.
|
711
|
+
# This method is mostly used by internal method calls.
|
712
|
+
# It utilizes any solr_fq value defined within a relationship to attach a query filter
|
713
|
+
# on top of just the predicate being used. Because it is static it
|
714
|
+
# needs the pid of the object that has the inbound relationships passed in.
|
715
|
+
# If you are calling this method directly to get the query you should use the
|
716
|
+
# ActiveFedora::SemanticNode.relationship_query instead or use the helper method
|
717
|
+
# [relationship_name]_query, i.e. method "parts_query" for relationship "parts". This
|
718
|
+
# method would only be called directly if you were working only with Solr and already
|
719
|
+
# had the pid for the object in something like a solr document.
|
720
|
+
# @param [String] The pid for the object that has these inbound relationships
|
721
|
+
# @param [String] The name of the relationship defined in the model
|
722
|
+
# @return [String]
|
723
|
+
# @example
|
724
|
+
# Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
|
725
|
+
# #returns all parts
|
726
|
+
# has_relationship "parts", :is_part_of, :inbound=>true
|
727
|
+
# #returns only parts that have level to "series"
|
728
|
+
# has_relationship "series_parts", :is_part_of, :inbound=>true, :solr_fq=>"level_t:series"
|
729
|
+
# end
|
730
|
+
# s = SampleAFObjRelationshipFilterQuery.new
|
731
|
+
# s.pid
|
732
|
+
# #=> id:changeme:13020
|
733
|
+
# s.series_parts_query
|
734
|
+
# #=> "is_part_of_s:info\\:fedora/changeme\\:13021 AND level_t:series"
|
735
|
+
# SampleAFObjRelationshipFilterQuery.inbound_relationship_query(s.pid,"series_parts")
|
736
|
+
# #=> "is_part_of_s:info\\:fedora/changeme\\:13021 AND level_t:series"
|
737
|
+
def inbound_relationship_query(pid,relationship_name)
|
738
|
+
query = ""
|
739
|
+
subject = :inbound
|
740
|
+
if relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name)
|
741
|
+
predicate = relationships_desc[subject][relationship_name][:predicate]
|
742
|
+
internal_uri = "info:fedora/#{pid}"
|
743
|
+
escaped_uri = internal_uri.gsub(/(:)/, '\\:')
|
744
|
+
query = "#{predicate}_s:#{escaped_uri}"
|
745
|
+
if relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
|
746
|
+
solr_fq = relationships_desc[subject][relationship_name][:solr_fq]
|
747
|
+
query << " AND " unless query.empty?
|
748
|
+
query << solr_fq
|
749
|
+
end
|
750
|
+
end
|
751
|
+
query
|
752
|
+
end
|
753
|
+
|
754
|
+
# Returns a solr query for retrieving objects specified in a bidirectional relationship.
|
755
|
+
# This method is mostly used by internal method calls.
|
756
|
+
# It usea of solr_fq value defined within a relationship to attach a query filter
|
757
|
+
# on top of just the predicate being used. Because it is static it
|
758
|
+
# needs the pids defined within RELS-EXT for the outbound relationship as well as the pid of the
|
759
|
+
# object for the inbound portion of the relationship.
|
760
|
+
# If you are calling this method directly to get the query you should use the
|
761
|
+
# ActiveFedora::SemanticNode.relationship_query instead or use the helper method
|
762
|
+
# [relationship_name]_query, i.e. method "bi_parts_query" for relationship "bi_parts". This
|
763
|
+
# method would only be called directly if you had something like an array of outbound pids
|
764
|
+
# already in something like a solr document for object that has these relationships.
|
765
|
+
# @param [String] The pid for the object that has these inbound relationships
|
766
|
+
# @param [String] The name of the relationship defined in the model
|
767
|
+
# @param [Array] An array of pids to include in the query
|
768
|
+
# @return [String]
|
769
|
+
# @example
|
770
|
+
# Class SampleAFObjRelationshipFilterQuery < ActiveFedora::Base
|
771
|
+
# has_bidirectional_relationship "bi_series_parts", :has_part, :is_part_of, :solr_fq=>"level_t:series"
|
772
|
+
# end
|
773
|
+
# s = SampleAFObjRelationshipFilterQuery.new
|
774
|
+
# obj = ActiveFedora::Base.new
|
775
|
+
# s.bi_series_parts_append(obj)
|
776
|
+
# s.pid
|
777
|
+
# #=> "changeme:13025"
|
778
|
+
# obj.pid
|
779
|
+
# #=> id:changeme:13026
|
780
|
+
# s.bi_series_parts_query
|
781
|
+
# #=> "(id:changeme\\:13026 AND level_t:series) OR (is_part_of_s:info\\:fedora/changeme\\:13025 AND level_t:series)"
|
782
|
+
# SampleAFObjRelationshipFilterQuery.bidirectional_relationship_query(s.pid,"series_parents",["id:changeme:13026"])
|
783
|
+
# #=> "(id:changeme\\:13026 AND level_t:series) OR (is_part_of_s:info\\:fedora/changeme\\:13025 AND level_t:series)"
|
784
|
+
def bidirectional_relationship_query(pid,relationship_name,outbound_pids)
|
785
|
+
outbound_query = outbound_relationship_query("#{relationship_name}_outbound",outbound_pids)
|
786
|
+
inbound_query = inbound_relationship_query(pid,"#{relationship_name}_inbound")
|
787
|
+
query = outbound_query # use outbound_query by default
|
788
|
+
if !inbound_query.empty?
|
789
|
+
query << " OR (" + inbound_relationship_query(pid,"#{relationship_name}_inbound") + ")"
|
790
|
+
end
|
791
|
+
return query
|
792
|
+
end
|
793
|
+
|
794
|
+
# Check if a relationship has any solr query filters defined by has_relationship call
|
795
|
+
# @param [Symbol] subject to use such as :self or :inbound
|
796
|
+
# @param [String] relationship name
|
797
|
+
# @return [Boolean] true if the relationship has a query filter defined
|
798
|
+
def relationship_has_solr_filter_query?(subject, relationship_name)
|
799
|
+
relationships_desc.has_key?(subject) && relationships_desc[subject].has_key?(relationship_name) && relationships_desc[subject][relationship_name].has_key?(:solr_fq)
|
800
|
+
end
|
801
|
+
|
802
|
+
# ** EXPERIMENTAL **
|
803
|
+
#
|
804
|
+
# Check to make sure a subject,name, and predicate triple does not already exist
|
805
|
+
# with the same subject but different name.
|
806
|
+
# This method is used to ensure conflicting has_relationship calls are not made because
|
807
|
+
# predicates cannot be reused across relationship names. Otherwise, the mapping of relationship name
|
808
|
+
# to predicate in RELS-EXT would be broken.
|
809
|
+
# @param [Symbol] subject to check (:self or :inbound)
|
810
|
+
# @param [String] relationship name
|
811
|
+
# @param [Symbol] symbol for Fedora relationship ontology predicate
|
812
|
+
def predicate_exists_with_different_relationship_name?(subject,name,predicate)
|
813
|
+
if relationships_desc.has_key?(subject)
|
814
|
+
relationships_desc[subject].each_pair do |existing_name, args|
|
815
|
+
return true if !args[:predicate].nil? && args[:predicate] == predicate && existing_name != name
|
816
|
+
end
|
817
|
+
end
|
818
|
+
return false
|
819
|
+
end
|
820
|
+
|
821
|
+
## Deprecated class method checks for HYDRA-541 methods renamed
|
822
|
+
#
|
823
|
+
# Old Name New Name
|
824
|
+
# named_relationships_desc relationships_desc
|
825
|
+
# register_named_subject register_relationship_desc_subject
|
826
|
+
# register_named_relationship register_relationship_desc
|
827
|
+
# create_named_relationship_method create_relationship_name_methods
|
828
|
+
# create_bidirectional_named_relationship_methods create_bidirectional_relationship_name_methods
|
829
|
+
# outbound_named_relationship_query outbound_relationship_query
|
830
|
+
# inbound_named_relationship_query inbound_relationship_query
|
831
|
+
# bidirectional_named_relationship_query bidirectional_relationship_query
|
832
|
+
# named_predicate_exists_with_different_name? predicate_exists_with_different_relationship_name?
|
833
|
+
|
834
|
+
# @deprecated Please use {#relationships_desc} instead.
|
835
|
+
def named_relationships_desc
|
836
|
+
logger.warn("Deprecation: named_relationships_desc has been deprecated. Please call relationships_desc instead.")
|
837
|
+
relationships_desc
|
838
|
+
end
|
839
|
+
|
840
|
+
# @deprecated Please use {#register_relationship_desc_subject} instead.
|
841
|
+
def register_named_subject(subject)
|
842
|
+
logger.warn("Deprecation: register_named_subject has been deprecated. Please call register_relationship_desc_subject instead.")
|
843
|
+
register_relationship_desc_subject(subject)
|
844
|
+
end
|
845
|
+
|
846
|
+
# @deprecated Please use {#register_relationship_desc} instead.
|
847
|
+
def register_named_relationship(subject, name, predicate, opts)
|
848
|
+
logger.warn("Deprecation: register_named_relationship has been deprecated. Please call register_relationship_desc instead.")
|
849
|
+
register_relationship_desc(subject, name, predicate, opts)
|
850
|
+
end
|
851
|
+
|
852
|
+
# @deprecated Please use {#create_relationship_name_methods} instead.
|
853
|
+
def create_named_relationship_methods(name)
|
854
|
+
logger.warn("Deprecation: create_named_relationship_methods has been deprecated. Please call create_relationship_name_methods instead.")
|
855
|
+
create_relationship_name_methods(name)
|
856
|
+
end
|
857
|
+
|
858
|
+
# @deprecated Please use {#create_bidirectional_relationship_name_methods} instead.
|
859
|
+
def create_bidirectional_named_relationship_methods(name,outbound_name)
|
860
|
+
logger.warn("Deprecation: create_bidirectional_named_relationship_methods has been deprecated. Please call create_bidirectional_relationship_name_methods instead.")
|
861
|
+
create_bidirectional_relationship_name_methods(name,outbound_name)
|
862
|
+
end
|
863
|
+
|
864
|
+
# @deprecated Please use {#outbound_relationship_query} instead.
|
865
|
+
def outbound_named_relationship_query(relationship_name,outbound_pids)
|
866
|
+
logger.warn("Deprecation: outbound_named_relationship_query has been deprecated. Please call outbound_relationship_query instead.")
|
867
|
+
outbound_relationship_query(relationship_name,outbound_pids)
|
868
|
+
end
|
869
|
+
|
870
|
+
# @deprecated Please use {#inbound_relationship_query} instead.
|
871
|
+
def inbound_named_relationship_query(pid,relationship_name)
|
872
|
+
logger.warn("Deprecation: inbound_named_relationship_query has been deprecated. Please call inbound_relationship_query instead.")
|
873
|
+
inbound_relationship_query(pid,relationship_name)
|
874
|
+
end
|
875
|
+
|
876
|
+
# @deprecated Please use {#bidirectional_relationship_query} instead.
|
877
|
+
def bidirectional_named_relationship_query(pid,relationship_name,outbound_pids)
|
878
|
+
logger.warn("Deprecation: bidirectional_named_relationship_query has been deprecated. Please call bidirectional_relationship_query instead.")
|
879
|
+
bidirectional_relationship_query(pid,relationship_name,outbound_pids)
|
880
|
+
end
|
881
|
+
|
882
|
+
# @deprecated Please use {#predicate_exists_with_different_relationship_name?} instead.
|
883
|
+
def named_predicate_exists_with_different_name?(subject,name,predicate)
|
884
|
+
logger.warn("Deprecation: named_predicate_exists_with_different_name? has been deprecated. Please call predicate_exists_with_different_relationship_name? instead.")
|
885
|
+
predicate_exists_with_different_relationship_name?(subject,name,predicate)
|
886
|
+
end
|
887
|
+
end
|
888
|
+
end
|
889
|
+
end
|