active-fedora 1.2.6 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/active-fedora.gemspec +5 -2
- data/lib/active_fedora/base.rb +19 -4
- data/lib/active_fedora/nokogiri_datastream.rb +228 -6
- data/lib/active_fedora/semantic_node.rb +23 -3
- data/lib/fedora/connection.rb +7 -4
- data/spec/fixtures/dino_jpg_no_file_ext +0 -0
- data/spec/fixtures/hydrangea_fixture_mods_article1.foxml.xml +58 -11
- data/spec/fixtures/mods_articles/hydrangea_article1.xml +24 -16
- data/spec/integration/base_spec.rb +145 -60
- data/spec/integration/nokogiri_datastream_spec.rb +60 -0
- data/spec/unit/base_named_datastream_spec.rb +3 -1
- data/spec/unit/nokogiri_datastream_spec.rb +110 -4
- data/spec/unit/semantic_node_spec.rb +45 -0
- metadata +7 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.2.
|
1
|
+
1.2.7
|
data/active-fedora.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{active-fedora}
|
8
|
-
s.version = "1.2.
|
8
|
+
s.version = "1.2.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Matt Zumwalt", "McClain Looney"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-11-14}
|
13
13
|
s.description = %q{ActiveFedora provides for creating and managing objects in the Fedora Repository Architecture.}
|
14
14
|
s.email = %q{matt.zumwalt@yourmediashelf.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -220,6 +220,7 @@ Gem::Specification.new do |s|
|
|
220
220
|
"solr/config/solrconfig-1.5.xml",
|
221
221
|
"spec/fixtures/changeme155.xml",
|
222
222
|
"spec/fixtures/dino.jpg",
|
223
|
+
"spec/fixtures/dino_jpg_no_file_ext",
|
223
224
|
"spec/fixtures/hydrangea_fixture_mods_article1.foxml.xml",
|
224
225
|
"spec/fixtures/minivan.jpg",
|
225
226
|
"spec/fixtures/mods_articles/hydrangea_article1.xml",
|
@@ -238,6 +239,7 @@ Gem::Specification.new do |s|
|
|
238
239
|
"spec/integration/metadata_datastream_helper_spec.rb",
|
239
240
|
"spec/integration/model_spec.rb",
|
240
241
|
"spec/integration/mods_article_integration_spec.rb",
|
242
|
+
"spec/integration/nokogiri_datastream_spec.rb",
|
241
243
|
"spec/integration/rels_ext_datastream_spec.rb",
|
242
244
|
"spec/integration/repository_spec.rb",
|
243
245
|
"spec/integration/rf_fedora_object_spec.rb",
|
@@ -300,6 +302,7 @@ Gem::Specification.new do |s|
|
|
300
302
|
"spec/integration/metadata_datastream_helper_spec.rb",
|
301
303
|
"spec/integration/model_spec.rb",
|
302
304
|
"spec/integration/mods_article_integration_spec.rb",
|
305
|
+
"spec/integration/nokogiri_datastream_spec.rb",
|
303
306
|
"spec/integration/rels_ext_datastream_spec.rb",
|
304
307
|
"spec/integration/repository_spec.rb",
|
305
308
|
"spec/integration/rf_fedora_object_spec.rb",
|
data/lib/active_fedora/base.rb
CHANGED
@@ -249,10 +249,19 @@ module ActiveFedora
|
|
249
249
|
# Add the given file as a datastream in the object
|
250
250
|
#
|
251
251
|
# @param [File] file the file to add
|
252
|
-
# @param [Hash] opts options: :dsid, :label
|
252
|
+
# @param [Hash] opts options: :dsid, :label, :mimeType
|
253
253
|
def add_file_datastream(file, opts={})
|
254
254
|
label = opts.has_key?(:label) ? opts[:label] : ""
|
255
|
-
|
255
|
+
attrs = {:dsLabel => label, :controlGroup => 'M', :blob => file}
|
256
|
+
if opts.has_key?(:mime_type)
|
257
|
+
attrs.merge!({:mimeType=>opts[:mime_type]})
|
258
|
+
elsif opts.has_key?(:mimeType)
|
259
|
+
attrs.merge!({:mimeType=>opts[:mimeType]})
|
260
|
+
elsif opts.has_key?(:content_type)
|
261
|
+
attrs.merge!({:mimeType=>opts[:content_type]})
|
262
|
+
end
|
263
|
+
|
264
|
+
ds = ActiveFedora::Datastream.new(attrs)
|
256
265
|
opts.has_key?(:dsid) ? ds.dsid=(opts[:dsid]) : nil
|
257
266
|
add_datastream(ds)
|
258
267
|
end
|
@@ -345,6 +354,12 @@ module ActiveFedora
|
|
345
354
|
unless named_datastreams_desc.has_key?(name) && named_datastreams_desc[name].has_key?(:type)
|
346
355
|
raise "Failed to add datastream. Named datastream #{name} not defined for object #{pid}."
|
347
356
|
end
|
357
|
+
|
358
|
+
if opts.has_key?(:mime_type)
|
359
|
+
opts.merge!({:content_type=>opts[:mime_type]})
|
360
|
+
elsif opts.has_key?(:mimeType)
|
361
|
+
opts.merge!({:content_type=>opts[:mimeType]})
|
362
|
+
end
|
348
363
|
opts.merge!(named_datastreams_desc[name])
|
349
364
|
|
350
365
|
label = opts.has_key?(:label) ? opts[:label] : ""
|
@@ -366,8 +381,8 @@ module ActiveFedora
|
|
366
381
|
if opts[:blob].respond_to?(:content_type)&&!opts[:blob].content_type.nil? && !opts.has_key?(:content_type)
|
367
382
|
opts.merge!({:content_type=>opts[:blob].content_type})
|
368
383
|
end
|
369
|
-
|
370
|
-
raise "The blob must respond to content_type or the hash must have :content_type property set" unless opts.has_key?(:content_type)
|
384
|
+
|
385
|
+
raise "The blob must respond to content_type or the hash must have :content_type or :mime_type property set" unless opts.has_key?(:content_type)
|
371
386
|
|
372
387
|
#throw error for mimeType mismatch
|
373
388
|
if named_datastreams_desc[name].has_key?(:mimeType) && !named_datastreams_desc[name][:mimeType].eql?(opts[:content_type])
|
@@ -10,8 +10,11 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
|
|
10
10
|
include Solrizer::XML::TerminologyBasedSolrizer # this adds support for calling .to_solr
|
11
11
|
|
12
12
|
# extend(OM::XML::Container::ClassMethods)
|
13
|
+
|
14
|
+
alias_method(:om_term_values, :term_values) unless method_defined?(:om_term_values)
|
15
|
+
alias_method(:om_update_values, :update_values) unless method_defined?(:om_update_values)
|
13
16
|
|
14
|
-
attr_accessor :ng_xml
|
17
|
+
attr_accessor :ng_xml, :internal_solr_doc
|
15
18
|
|
16
19
|
#constructor, calls up to ActiveFedora::Datastream's constructor
|
17
20
|
def initialize(attrs=nil)
|
@@ -79,9 +82,20 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
|
|
79
82
|
return xml.to_xml {|config| config.no_declaration}
|
80
83
|
end
|
81
84
|
|
82
|
-
#
|
85
|
+
# ** Experimental **
|
86
|
+
#
|
87
|
+
# This method is called by ActiveFedora::Base.load_instance_from_solr
|
88
|
+
# in order to initialize a nokogiri datastreams values from a solr document.
|
89
|
+
# This method merely sets the internal_solr_doc to the document passed in.
|
90
|
+
# Then any calls to get_values get values from the solr document on demand
|
91
|
+
# instead of directly from the xml stored in Fedora. This should be used
|
92
|
+
# for read-only purposes only, and instances where you want to improve performance by
|
93
|
+
# getting data from solr instead of Fedora.
|
94
|
+
#
|
95
|
+
# See ActiveFedora::Base.load_instance_from_solr and +get_values_from_solr+ for more information.
|
83
96
|
def from_solr(solr_doc)
|
84
|
-
#
|
97
|
+
#just initialize internal_solr_doc since any value retrieval will be done via lazy loading on this doc on-demand
|
98
|
+
@internal_solr_doc = solr_doc
|
85
99
|
end
|
86
100
|
|
87
101
|
def solrize_accessor(accessor_name, accessor_info, opts={})
|
@@ -109,7 +123,6 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
|
|
109
123
|
solrize_accessor(child_accessor_name, child_accessor_info, opts={:solr_doc=>solr_doc, :parents=>parents+[{accessor_name=>nodeset.index(node)}] })
|
110
124
|
end
|
111
125
|
end
|
112
|
-
|
113
126
|
end
|
114
127
|
|
115
128
|
def solrize_node(node, accessor_pointer, solr_doc = Solr::Document.new)
|
@@ -124,7 +137,195 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
|
|
124
137
|
solr_doc << Solr::Field.new(hierarchical_field_name => node.text)
|
125
138
|
end
|
126
139
|
end
|
127
|
-
|
140
|
+
|
141
|
+
# ** Experimental **
|
142
|
+
# This method is called by +get_values+ if this datastream has been initialized by calling from_solr method via
|
143
|
+
# ActiveFedora::Base.load_instance_from_solr. This method retrieves values from a preinitialized @internal_solr_doc instead of xml.
|
144
|
+
# This makes the datastream read-only and this method is not intended to be used in any other case.
|
145
|
+
#
|
146
|
+
# Values are retrieved from the @internal_solr_doc on-demand instead of via xml preloaded into memory.
|
147
|
+
# A term_pointer is passed in and if it contains hierarchical indexes it will detect which solr field values need to be returned.
|
148
|
+
#
|
149
|
+
# ====Example 1 (non-hierarchical term_pointer):
|
150
|
+
#
|
151
|
+
# term_pointer = [:image, :title_set, :title]
|
152
|
+
#
|
153
|
+
# Returns value of "image_title_set_title_t" in @internal_solr_doc
|
154
|
+
#
|
155
|
+
# ====Example 2 (hierarchical term_pointer that contains one or more indexes):
|
156
|
+
# term_pointer = [:image, {:title_set=>1}, :title]
|
157
|
+
#
|
158
|
+
# relevant xml:
|
159
|
+
# <image>
|
160
|
+
# <title_set>
|
161
|
+
# <title>Title 1</title>
|
162
|
+
# </title_set>
|
163
|
+
# </image>
|
164
|
+
# <image>
|
165
|
+
# <title_set>
|
166
|
+
# <title>Title 2</title>
|
167
|
+
# </title_set>
|
168
|
+
# <title_set>
|
169
|
+
# <title>Title 3</title>
|
170
|
+
# </title_set>
|
171
|
+
# </image>
|
172
|
+
#
|
173
|
+
# Repeating element nodes are indexed and will be stored in solr as follows:
|
174
|
+
# image_0_title_set_0_title_t = "Title 1"
|
175
|
+
# image_1_title_set_0_title_t = "Title 2"
|
176
|
+
# image_1_title_set_1_title_t = "Title 3"
|
177
|
+
#
|
178
|
+
# Even though no image element index is specified, only the second image element has two title_set elements so the expected return value is
|
179
|
+
# ["Title 3"]
|
180
|
+
#
|
181
|
+
# While loading from solr the xml hierarchy is not immediately apparent so we must detect first how many image elements with a title_set element exist
|
182
|
+
# and then check which of those elements have a second title element.
|
183
|
+
#
|
184
|
+
# As this nokogiri datastream is indexed in solr, a value at each level in the tree will be stored independently and therefore
|
185
|
+
# if 'image_0_title_set_0_title_t' exists in solr 'image_0_title_set_t' will also exist in solr.
|
186
|
+
# So, we will build up the relevant solr names incrementally for a given term_pointer. The last element in the
|
187
|
+
# solr_name will not contain an index.
|
188
|
+
#
|
189
|
+
# It then will do the following:
|
190
|
+
# Because no index is supplied for :image it will detect which indexes exist in solr
|
191
|
+
# image_0_title_set_t (found key and add 'image_0_title_set' to base solr_name list)
|
192
|
+
# image_1_title_set_t (found key and add 'image_0_title_set' to base solr_name list)
|
193
|
+
# image_2_title_set_t (not found and stop checking indexes for image)
|
194
|
+
# After iteration 1:
|
195
|
+
# bases = ["image_0_title_set","image_1_title_set"]
|
196
|
+
#
|
197
|
+
# Two image nodes were found and next sees index of 1 supplied for title_set so just uses index of 1 building off bases found in previous iteration
|
198
|
+
# image_0_title_set_1_title_t (not found remove 'image_0_title_set' from base solr_name list)
|
199
|
+
# image_1_title_set_1_title_t (found and replace 'image_1_title_set' with new base 'image_1_title_set_1_title')
|
200
|
+
#
|
201
|
+
# After iteration 2:
|
202
|
+
# bases = ["image_1_title_set_1_title"]
|
203
|
+
# It always looks ahead one element so we check if any elements are after title. There are not any other elements so we are done iterating.
|
204
|
+
# returns @internal_solr_doc["image_1_title_set_1_title_t"]
|
205
|
+
# @param [Array] term_pointer Term pointer similar to an xpath ie. [:image, :title_set, :title]
|
206
|
+
# @return [Array] If no values are found an empty Array is returned.
|
207
|
+
def get_values_from_solr(*term_pointer)
|
208
|
+
values = []
|
209
|
+
solr_doc = @internal_solr_doc
|
210
|
+
return values if solr_doc.nil?
|
211
|
+
begin
|
212
|
+
term = self.class.terminology.retrieve_term(*OM.pointers_to_flat_array(term_pointer, false))
|
213
|
+
#check if hierarchical term pointer
|
214
|
+
if is_hierarchical_term_pointer?(*term_pointer)
|
215
|
+
# if we are hierarchical need to detect all possible node values that exist
|
216
|
+
# we do this by building up the possible solr names parent by parent and/or child by child
|
217
|
+
# if an index is supplied for any node in the pointer it will be used
|
218
|
+
# otherwise it will include all nodes and indexes that exist in solr
|
219
|
+
bases = []
|
220
|
+
#add first item in term_pointer as start of bases
|
221
|
+
# then iterate through possible nodes that might exist
|
222
|
+
term_pointer.first.kind_of?(Hash) ? bases << term_pointer.first.keys.first : bases << term_pointer.first
|
223
|
+
for i in 1..(term_pointer.length-1)
|
224
|
+
#iterate in reverse so that we can modify the bases array while iterating
|
225
|
+
(bases.length-1).downto(0) do |j|
|
226
|
+
current_last = (term_pointer[i].kind_of?(Hash) ? term_pointer[i].keys.first : term_pointer[i])
|
227
|
+
if (term_pointer[i-1].kind_of?(Hash))
|
228
|
+
#just use index supplied instead of trying possibilities
|
229
|
+
index = term_pointer[i-1].values.first
|
230
|
+
solr_name_base = OM::XML::Terminology.term_hierarchical_name({bases[j]=>index},current_last)
|
231
|
+
solr_name = generate_solr_symbol(solr_name_base, term.data_type)
|
232
|
+
bases.delete_at(j)
|
233
|
+
#insert the new solr name base if found
|
234
|
+
bases.insert(j,solr_name_base) if has_solr_name?(solr_name,solr_doc)
|
235
|
+
else
|
236
|
+
#detect how many nodes exist
|
237
|
+
index = 0
|
238
|
+
current_base = bases[j]
|
239
|
+
bases.delete_at(j)
|
240
|
+
solr_name_base = OM::XML::Terminology.term_hierarchical_name({current_base=>index},current_last)
|
241
|
+
solr_name = generate_solr_symbol(solr_name_base, term.data_type)
|
242
|
+
#check for indexes that exist until we find all nodes
|
243
|
+
while has_solr_name?(solr_name,solr_doc) do
|
244
|
+
#only reinsert if it exists
|
245
|
+
bases.insert(j,solr_name_base)
|
246
|
+
index = index + 1
|
247
|
+
solr_name_base = OM::XML::Terminology.term_hierarchical_name({current_base=>index},current_last)
|
248
|
+
solr_name = generate_solr_symbol(solr_name_base, term.data_type)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
#all existing applicable solr_names have been found and we can now grab all values and build up our value array
|
255
|
+
bases.each do |base|
|
256
|
+
field_name = generate_solr_symbol(base.to_sym, term.data_type)
|
257
|
+
value = (solr_doc[field_name].nil? ? solr_doc[field_name.to_s]: solr_doc[field_name])
|
258
|
+
unless value.nil?
|
259
|
+
value.is_a?(Array) ? values.concat(value) : values << value
|
260
|
+
end
|
261
|
+
end
|
262
|
+
else
|
263
|
+
#this is not hierarchical and we can simply look for the solr name created using the terms without any indexes
|
264
|
+
generic_field_name_base = OM::XML::Terminology.term_generic_name(*term_pointer)
|
265
|
+
generic_field_name = generate_solr_symbol(generic_field_name_base, term.data_type)
|
266
|
+
value = (solr_doc[generic_field_name].nil? ? solr_doc[generic_field_name.to_s]: solr_doc[generic_field_name])
|
267
|
+
unless value.nil?
|
268
|
+
value.is_a?(Array) ? values.concat(value) : values << value
|
269
|
+
end
|
270
|
+
end
|
271
|
+
rescue Exception => e
|
272
|
+
#just do nothing since term does not exist and return emtpy values
|
273
|
+
raise e
|
274
|
+
end
|
275
|
+
values
|
276
|
+
end
|
277
|
+
|
278
|
+
def generate_solr_symbol(base, data_type)
|
279
|
+
Solrizer::XML::TerminologyBasedSolrizer.default_field_mapper.solr_name(base.to_sym, data_type)
|
280
|
+
end
|
281
|
+
|
282
|
+
# ** Experimental **
|
283
|
+
#@return [Boolean] true if either the key for name exists in solr or if its string value exists
|
284
|
+
#@param [String] name Name of key to look for
|
285
|
+
#@param [Solr::Document] solr_doc Solr doc to query
|
286
|
+
def has_solr_name?(name, solr_doc=Solr::Document.new)
|
287
|
+
!solr_doc[name].nil? || !solr_doc[name.to_s].nil?
|
288
|
+
end
|
289
|
+
|
290
|
+
# ** Experimental **
|
291
|
+
#@return true if the term_pointer contains an index
|
292
|
+
# ====Example:
|
293
|
+
# [:image, {:title_set=>1}, :title] return true
|
294
|
+
# [:image, :title_set, :title] return false
|
295
|
+
def is_hierarchical_term_pointer?(*term_pointer)
|
296
|
+
if term_pointer.length>1
|
297
|
+
term_pointer.each do |pointer|
|
298
|
+
if pointer.kind_of?(Hash)
|
299
|
+
return true
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
return false
|
304
|
+
end
|
305
|
+
|
306
|
+
# Update field values within the current datastream
|
307
|
+
# @param [Hash] params The params specifying which fields to update and their new values. Format: term_pointer => {index => value, ...}
|
308
|
+
# term_pointer must be a valind OM Term pointer (ie. [:name]). Strings will be ignored.
|
309
|
+
# @param [Hash] opts This is not currently used by the datastream-level update_indexed_attributes method
|
310
|
+
#
|
311
|
+
# Example:
|
312
|
+
# @mods_ds.update_indexed_attributes( {[{":person"=>"0"}, "role"]=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"} })
|
313
|
+
# => {"person_0_role"=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"}}
|
314
|
+
#
|
315
|
+
# @mods_ds.to_xml will return something like this:
|
316
|
+
# <mods>
|
317
|
+
# <mods:name type="person">
|
318
|
+
# <mods:role>
|
319
|
+
# <mods:roleTerm>role1</mods:roleTerm>
|
320
|
+
# </mods:role>
|
321
|
+
# <mods:role>
|
322
|
+
# <mods:roleTerm>role2</mods:roleTerm>
|
323
|
+
# </mods:role>
|
324
|
+
# <mods:role>
|
325
|
+
# <mods:roleTerm>role3</mods:roleTerm>
|
326
|
+
# </mods:role>
|
327
|
+
# </mods:name>
|
328
|
+
# </mods>
|
128
329
|
def update_indexed_attributes(params={}, opts={})
|
129
330
|
if self.class.terminology.nil?
|
130
331
|
raise "No terminology is set for this NokogiriDatastream class. Cannot perform update_indexed_attributes"
|
@@ -134,6 +335,7 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
|
|
134
335
|
current_params = params.clone
|
135
336
|
current_params.delete_if do |term_pointer,new_values|
|
136
337
|
if term_pointer.kind_of?(String)
|
338
|
+
logger.warn "WARNING: #{dsid} ignoring {#{term_pointer.inspect} => #{new_values.inspect}} because #{term_pointer.inspect} is a String (only valid OM Term Pointers will be used). Make sure your html has the correct field_selector tags in it."
|
137
339
|
true
|
138
340
|
else
|
139
341
|
!self.class.terminology.has_term?(*OM.destringify(term_pointer))
|
@@ -153,4 +355,24 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
|
|
153
355
|
term_values(*field_key)
|
154
356
|
end
|
155
357
|
|
156
|
-
|
358
|
+
# Override the method in OM::XML::TermValueOperators so that returns an error if we have loaded from solr since it should be read-only
|
359
|
+
#
|
360
|
+
# example term values hash: {[{":person"=>"0"}, "role", "text"]=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"}, [{:person=>1}, :family_name]=>"Andronicus", [{"person"=>"1"},:given_name]=>["Titus"],[{:person=>1},:role,:text]=>["otherrole1","otherrole2"] }
|
361
|
+
def update_values(params={})
|
362
|
+
if @internal_solr_doc
|
363
|
+
raise "No update performed, this object was initialized via Solr instead of Fedora and is therefore read-only. Please utilize ActiveFedora::Base.load_instance to first load object via Fedora instead."
|
364
|
+
else
|
365
|
+
om_update_values(params)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
#override OM::XML::term_values so can lazy load from solr if this datastream initialized using +from_solr+
|
370
|
+
def term_values(*term_pointer)
|
371
|
+
if @internal_solr_doc
|
372
|
+
#lazy load values from solr on demand
|
373
|
+
get_values_from_solr(*term_pointer)
|
374
|
+
else
|
375
|
+
om_term_values(*term_pointer)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
@@ -586,6 +586,22 @@ module ActiveFedora
|
|
586
586
|
self.send(:define_method,:"#{append_method_name}") {|object| add_named_relationship(name,object)}
|
587
587
|
self.send(:define_method,:"#{remove_method_name}") {|object| remove_named_relationship(name,object)}
|
588
588
|
end
|
589
|
+
|
590
|
+
# ** EXPERIMENTAL **
|
591
|
+
# Similar to +create_named_relationship_methods+ except we are merely creating an alias for outbound portion of bidirectional
|
592
|
+
#
|
593
|
+
# ====Example
|
594
|
+
# has_bidirectional_relationship "members", :has_collection_member, :is_member_of_collection
|
595
|
+
#
|
596
|
+
# Method members_outbound_append and members_outbound_remove added
|
597
|
+
# This method will create members_append which does same thing as members_outbound_append
|
598
|
+
# and will create members_remove which does same thing as members_outbound_remove
|
599
|
+
def create_bidirectional_named_relationship_methods(name,outbound_name)
|
600
|
+
append_method_name = "#{name.to_s.downcase}_append"
|
601
|
+
remove_method_name = "#{name.to_s.downcase}_remove"
|
602
|
+
self.send(:define_method,:"#{append_method_name}") {|object| add_named_relationship(outbound_name,object)}
|
603
|
+
self.send(:define_method,:"#{remove_method_name}") {|object| remove_named_relationship(outbound_name,object)}
|
604
|
+
end
|
589
605
|
|
590
606
|
def create_inbound_relationship_finders(name, predicate, opts = {})
|
591
607
|
class_eval <<-END
|
@@ -650,6 +666,7 @@ module ActiveFedora
|
|
650
666
|
end
|
651
667
|
|
652
668
|
# Generates relationship finders for predicates that point in both directions
|
669
|
+
# and registers predicate relationships for each direction.
|
653
670
|
#
|
654
671
|
# @name Name of the relationship method(s) to create
|
655
672
|
# @outbound_predicate Predicate used in outbound relationships
|
@@ -659,9 +676,12 @@ module ActiveFedora
|
|
659
676
|
def create_bidirectional_relationship_finders(name, outbound_predicate, inbound_predicate, opts={})
|
660
677
|
inbound_method_name = name.to_s+"_inbound"
|
661
678
|
outbound_method_name = name.to_s+"_outbound"
|
662
|
-
|
663
|
-
|
664
|
-
|
679
|
+
has_relationship(outbound_method_name, outbound_predicate, opts)
|
680
|
+
has_relationship(inbound_method_name, inbound_predicate, opts.merge!(:inbound=>true))
|
681
|
+
|
682
|
+
#create methods that mirror the outbound append and remove with our bidirectional name, assume just add and remove locally
|
683
|
+
create_bidirectional_named_relationship_methods(name,outbound_method_name)
|
684
|
+
|
665
685
|
class_eval <<-END
|
666
686
|
def #{name}(opts={})
|
667
687
|
if opts[:response_format] == :solr || opts[:response_format] == :load_from_solr
|
data/lib/fedora/connection.rb
CHANGED
@@ -188,11 +188,14 @@ module Fedora
|
|
188
188
|
# remote service and resources.
|
189
189
|
def http
|
190
190
|
http = Net::HTTP.new(@site.host, @site.port)
|
191
|
-
if(@site.is_a?(URI::HTTPS)
|
191
|
+
if(@site.is_a?(URI::HTTPS))
|
192
192
|
http.use_ssl = true
|
193
|
-
http.cert = OpenSSL::X509::Certificate.new( File.read(SSL_CLIENT_CERT_FILE) )
|
194
|
-
http.key = OpenSSL::PKey::RSA.new( File.read(SSL_CLIENT_KEY_FILE), SSL_CLIENT_KEY_PASS )
|
195
193
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
194
|
+
|
195
|
+
if (defined?(SSL_CLIENT_CERT_FILE) && !SSL_CLIENT_CERT_FILE.nil? && defined?(SSL_CLIENT_KEY_FILE) && !SSL_CLIENT_KEY_FILE.nil? && defined?(SSL_CLIENT_KEY_PASS) && !SSL_CLIENT_KEY_PASS.nil?)
|
196
|
+
http.cert = OpenSSL::X509::Certificate.new( File.read(SSL_CLIENT_CERT_FILE) )
|
197
|
+
http.key = OpenSSL::PKey::RSA.new( File.read(SSL_CLIENT_KEY_FILE), SSL_CLIENT_KEY_PASS )
|
198
|
+
end
|
196
199
|
end
|
197
200
|
http
|
198
201
|
end
|
@@ -212,4 +215,4 @@ module Fedora
|
|
212
215
|
(@site.user || @site.password ? { 'Authorization' => 'Basic ' + ["#{@site.user}:#{ @site.password}"].pack('m').delete("\r\n") } : {})
|
213
216
|
end
|
214
217
|
end
|
215
|
-
end
|
218
|
+
end
|
Binary file
|
@@ -89,13 +89,31 @@ xsi:schemaLocation="info:fedora/fedora-system:def/foxml# http://www.fedora.info/
|
|
89
89
|
<displayForm>NAME AS IT APPEARS</displayForm>
|
90
90
|
<affiliation>FACULTY, UNIVERSITY</affiliation>
|
91
91
|
<role>
|
92
|
-
<roleTerm authority="marcrelator" type="text">
|
92
|
+
<roleTerm authority="marcrelator" type="text">Creator</roleTerm>
|
93
93
|
</role>
|
94
|
+
</name>
|
95
|
+
<name type="personal">
|
96
|
+
<namePart type="family">Lacks</namePart>
|
97
|
+
<namePart type="given">Henrietta</namePart>
|
98
|
+
<displayForm>HeLa</displayForm>
|
99
|
+
<affiliation>Baltimore</affiliation>
|
94
100
|
<role>
|
95
|
-
<roleTerm type="text">
|
101
|
+
<roleTerm authority="marcrelator" type="text">Contributor</roleTerm>
|
96
102
|
</role>
|
97
103
|
</name>
|
98
|
-
|
104
|
+
<name type="corporate">
|
105
|
+
<namePart>NSF</namePart>
|
106
|
+
<role>
|
107
|
+
<roleTerm authority="marcrelator" type="text">Funder</roleTerm>
|
108
|
+
</role>
|
109
|
+
</name>
|
110
|
+
<name type="conference">
|
111
|
+
<namePart>some conference</namePart>
|
112
|
+
<role>
|
113
|
+
<roleTerm authority="marcrelator" type="text">Host</roleTerm>
|
114
|
+
</role>
|
115
|
+
</name>
|
116
|
+
|
99
117
|
<typeOfResource>text</typeOfResource>
|
100
118
|
<genre authority="local">journal article</genre>
|
101
119
|
|
@@ -158,7 +176,7 @@ xsi:schemaLocation="info:fedora/fedora-system:def/foxml# http://www.fedora.info/
|
|
158
176
|
<foxml:xmlContent>
|
159
177
|
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
160
178
|
<rdf:Description rdf:about="info:fedora/hydrangea:fixture_mods_article1">
|
161
|
-
<hasModel xmlns="info:fedora/fedora-system:def/relations-external#" rdf:resource="info:fedora/afmodel:
|
179
|
+
<hasModel xmlns="info:fedora/fedora-system:def/relations-external#" rdf:resource="info:fedora/afmodel:HydrangeaArticle"></hasModel>
|
162
180
|
</rdf:Description>
|
163
181
|
</rdf:RDF>
|
164
182
|
</foxml:xmlContent>
|
@@ -167,13 +185,42 @@ xsi:schemaLocation="info:fedora/fedora-system:def/foxml# http://www.fedora.info/
|
|
167
185
|
<foxml:datastream ID="rightsMetadata" STATE="A" CONTROL_GROUP="X" VERSIONABLE="true">
|
168
186
|
<foxml:datastreamVersion ID="rightsMetadata.0" LABEL="" CREATED="2010-06-17T19:56:23.335Z" MIMETYPE="text/xml" SIZE="19">
|
169
187
|
<foxml:xmlContent>
|
170
|
-
<
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
188
|
+
<rightsMetadata xmlns="http://hydra-collab.stanford.edu/schemas/rightsMetadata/v1">
|
189
|
+
<copyright>
|
190
|
+
<human>(c)2009 The Hydra Project</human>
|
191
|
+
<human type="someSpecialisedType">Blah Blah</human>
|
192
|
+
<human type="aDifferentType">More blah</human>
|
193
|
+
<machine><a rel="license" href="http://creativecommons.org/licenses/publicdomain/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/publicdomain/88x31.png" /></a><br />This work is in the <a rel="license" href="http://creativecommons.org/licenses/publicdomain/">Public Domain</a>.</machine>
|
194
|
+
</copyright>
|
195
|
+
<access type="discover">
|
196
|
+
<human></human>
|
197
|
+
<machine>
|
198
|
+
<policy>hydra-policy:4502</policy>
|
199
|
+
<group>public</group>
|
200
|
+
</machine>
|
201
|
+
</access>
|
202
|
+
<access type="read">
|
203
|
+
<human></human>
|
204
|
+
<machine>
|
205
|
+
<group>public</group>
|
206
|
+
</machine>
|
207
|
+
</access>
|
208
|
+
<access type="edit">
|
209
|
+
<human></human>
|
210
|
+
<machine>
|
211
|
+
<person>researcher1</person>
|
212
|
+
<group>archivist</group>
|
213
|
+
</machine>
|
214
|
+
</access>
|
215
|
+
<access type="etc">
|
216
|
+
<!-- etc -->
|
217
|
+
</access>
|
218
|
+
<use>
|
219
|
+
<human>You are free to re-distribute this object, but you cannot change it or sell it. </human>
|
220
|
+
<machine><a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/us/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-nd/3.0/us/88x31.png" /></a><br />This <span xmlns:dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/Sound" rel="dc:type">work</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/us/">Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License</a>.</machine>
|
221
|
+
</use>
|
222
|
+
|
223
|
+
</rightsMetadata>
|
177
224
|
</foxml:xmlContent>
|
178
225
|
</foxml:datastreamVersion>
|
179
226
|
</foxml:datastream>
|