active-fedora 1.0.5 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/.hg/00changelog.i +0 -0
- data/.hg/branch +1 -0
- data/.hg/branch.cache +2 -0
- data/.hg/dirstate +0 -0
- data/.hg/hgrc +2 -0
- data/.hg/requires +2 -0
- data/.hg/store/00changelog.i +0 -0
- data/.hg/store/00manifest.i +0 -0
- data/.hg/store/data/.hgignore.i +0 -0
- data/.hg/store/data/.hgtags.i +0 -0
- data/.hg/store/data/_c_o_p_y_i_n_g.txt.i +0 -0
- data/.hg/store/data/_c_o_y_i_n_g._l_e_s_s_e_r.txt.i +0 -0
- data/.hg/store/data/_history.txt.i +0 -0
- data/.hg/store/data/_license.txt.i +0 -0
- data/.hg/store/data/_manifest.txt.i +0 -0
- data/.hg/store/data/_post_install.txt.i +0 -0
- data/.hg/store/data/_r_e_a_d_m_e.rdoc.i +0 -0
- data/.hg/store/data/_r_e_a_d_m_e.txt.i +0 -0
- data/.hg/store/data/_rakefile.i +0 -0
- data/.hg/store/data/_v_e_r_s_i_o_n.i +0 -0
- data/.hg/store/data/active-fedora.gemspec.i +0 -0
- data/.hg/store/data/active__fedora/_history.txt.i +0 -0
- data/.hg/store/data/active__fedora/_manifest.txt.i +0 -0
- data/.hg/store/data/active__fedora/_post_install.txt.i +0 -0
- data/.hg/store/data/active__fedora/_r_e_a_d_m_e.rdoc.i +0 -0
- data/.hg/store/data/active__fedora/_rakefile.i +0 -0
- data/.hg/store/data/active__fedora/lib/active__fedora.rb.i +0 -0
- data/.hg/store/data/active__fedora/script/console.i +0 -0
- data/.hg/store/data/active__fedora/script/destroy.i +0 -0
- data/.hg/store/data/active__fedora/script/generate.i +0 -0
- data/.hg/store/data/active__fedora/spec/active__fedora__spec.rb.i +0 -0
- data/.hg/store/data/active__fedora/spec/spec__helper.rb.i +0 -0
- data/.hg/store/data/config/fedora.yml.i +0 -0
- data/.hg/store/data/config/solr__mappings.yml.i +0 -0
- data/.hg/store/data/config/solr__mappings__af__0.1.yml.i +0 -0
- data/.hg/store/data/config/solr__mappings__bl__2.4.yml.i +0 -0
- data/.hg/store/data/lib/active-fedora.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/base.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/content__model.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/datastream.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/fedora__object.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/metadata__datastream.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/model.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/property.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/qualified__dublin__core__datastream.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/relationship.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/rels__ext__datastream.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/semantic__node.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/solr__mapper.rb.i +0 -0
- data/.hg/store/data/lib/active__fedora/solr__service.rb.i +0 -0
- data/.hg/store/data/lib/fedora/base.rb.i +0 -0
- data/.hg/store/data/lib/fedora/connection.rb.i +0 -0
- data/.hg/store/data/lib/fedora/datastream.rb.i +0 -0
- data/.hg/store/data/lib/fedora/fedora__object.rb.i +0 -0
- data/.hg/store/data/lib/fedora/formats.rb.i +0 -0
- data/.hg/store/data/lib/fedora/generic__search.rb.i +0 -0
- data/.hg/store/data/lib/fedora/repository.rb.i +0 -0
- data/.hg/store/data/lib/ruby-fedora.rb.i +0 -0
- data/.hg/store/data/lib/util/class__level__inheritable__attributes.rb.i +0 -0
- data/.hg/store/data/script/console.i +0 -0
- data/.hg/store/data/script/destroy.i +0 -0
- data/.hg/store/data/script/generate.i +0 -0
- data/.hg/store/data/solr/config/schema-1.5.xml.i +0 -0
- data/.hg/store/data/solr/config/schema.xml.i +0 -0
- data/.hg/store/data/solr/config/solrconfig-1.5.xml.i +0 -0
- data/.hg/store/data/spec/fixtures/changeme155.xml.i +0 -0
- data/.hg/store/data/spec/fixtures/dino.jpg.i +0 -0
- data/.hg/store/data/spec/fixtures/minivan.jpg.d +0 -0
- data/.hg/store/data/spec/fixtures/minivan.jpg.i +0 -0
- data/.hg/store/data/spec/fixtures/test__12.foxml.xml.i +0 -0
- data/.hg/store/data/spec/integration/active__fedora/base__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/active__fedora/datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/active__fedora/fedora__object__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/active__fedora/full__featured__model__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/active__fedora/model__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/active__fedora/rels__ext__datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/active__fedora/semantic__node__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/base__file__management__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/base__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/bug__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/datastreams__crud__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/fedora__object__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/full__featured__model__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/model__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/rels__ext__datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/repository__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/rf__fedora__object__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/semantic__node__spec.rb.i +0 -0
- data/.hg/store/data/spec/integration/solr__service__spec.rb.i +0 -0
- data/.hg/store/data/spec/samples/models/audio__record.rb.i +0 -0
- data/.hg/store/data/spec/samples/models/image.rb.i +0 -0
- data/.hg/store/data/spec/samples/models/oral__history.rb.i +0 -0
- data/.hg/store/data/spec/samples/models/seminar.rb.i +0 -0
- data/.hg/store/data/spec/samples/models/seminar__audio__file.rb.i +0 -0
- data/.hg/store/data/spec/samples/oh__qdc.xml.i +0 -0
- data/.hg/store/data/spec/samples/oral__history.rb.i +0 -0
- data/.hg/store/data/spec/samples/oral__history__sample.xml.i +0 -0
- data/.hg/store/data/spec/samples/oral__history__sample__model.rb.i +0 -0
- data/.hg/store/data/spec/samples/oral__history__xml.xml.i +0 -0
- data/.hg/store/data/spec/spec.opts.i +0 -0
- data/.hg/store/data/spec/spec__helper.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/base__cma__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/base__extra__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/base__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/content__model__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/inheritance__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/metadata__datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/model__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/property__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/qualified__dublin__core__datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/relationship__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/rels__ext__datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/semantic__node__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora/solr__service__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/active__fedora__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/base__cma__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/base__datastream__management__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/base__extra__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/base__file__management__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/base__loader__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/base__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/connection__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/content__model__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/datastream__concurrency__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/fedora__object__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/inheritance__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/metadata__datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/model__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/property__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/qualified__dublin__core__datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/relationship__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/rels__ext__datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/repository__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/rf__datastream__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/semantic__node__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/solr__config__options__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/solr__mapper__spec.rb.i +0 -0
- data/.hg/store/data/spec/unit/solr__service__spec.rb.i +0 -0
- data/.hg/store/data/tasks/rspec.rake.i +0 -0
- data/.hg/store/undo +0 -0
- data/.hg/undo.branch +1 -0
- data/.hg/undo.dirstate +0 -0
- data/.hgignore +7 -0
- data/.hgtags +14 -0
- data/COPYING.txt +674 -0
- data/COYING.LESSER.txt +165 -0
- data/History.txt +34 -0
- data/LICENSE +20 -0
- data/License.txt +58 -0
- data/Manifest.txt +1 -1
- data/README.rdoc +13 -54
- data/README.txt +59 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/active-fedora.gemspec +359 -0
- data/config/fedora.yml +16 -0
- data/config/solr_mappings.yml +14 -0
- data/config/solr_mappings_af_0.1.yml +16 -0
- data/config/solr_mappings_bl_2.4.yml +14 -0
- data/lib/active_fedora.rb +66 -6
- data/lib/active_fedora/base.rb +59 -23
- data/lib/active_fedora/datastream.rb +1 -1
- data/lib/active_fedora/metadata_datastream.rb +14 -7
- data/lib/active_fedora/model.rb +4 -4
- data/lib/active_fedora/rels_ext_datastream.rb +1 -1
- data/lib/active_fedora/semantic_node.rb +4 -3
- data/lib/active_fedora/solr_mapper.rb +17 -0
- data/lib/active_fedora/solr_service.rb +44 -2
- data/lib/fedora/base.rb +38 -0
- data/lib/fedora/connection.rb +210 -0
- data/lib/fedora/datastream.rb +56 -0
- data/lib/fedora/fedora_object.rb +161 -0
- data/lib/fedora/formats.rb +30 -0
- data/lib/fedora/generic_search.rb +71 -0
- data/lib/fedora/repository.rb +287 -0
- data/lib/ruby-fedora.rb +20 -0
- data/lib/util/class_level_inheritable_attributes.rb +23 -0
- data/script/console +15 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/solr/config/schema-1.5.xml +468 -0
- data/solr/config/schema.xml +174 -212
- data/solr/config/solrconfig-1.5.xml +1069 -0
- data/spec/active_fedora_spec.rb +7 -0
- data/spec/fixtures/changeme155.xml +255 -0
- data/spec/fixtures/dino.jpg +0 -0
- data/spec/fixtures/minivan.jpg +0 -0
- data/spec/fixtures/test_12.foxml.xml +121 -0
- data/spec/integration/base_file_management_spec.rb +20 -0
- data/spec/integration/base_spec.rb +196 -0
- data/spec/integration/bug_spec.rb +57 -0
- data/spec/integration/datastream_spec.rb +60 -0
- data/spec/integration/datastreams_crud_spec.rb +208 -0
- data/spec/integration/fedora_object_spec.rb +77 -0
- data/spec/integration/full_featured_model_spec.rb +207 -0
- data/spec/integration/model_spec.rb +54 -0
- data/spec/integration/rels_ext_datastream_spec.rb +67 -0
- data/spec/integration/repository_spec.rb +297 -0
- data/spec/integration/rf_fedora_object_spec.rb +95 -0
- data/spec/integration/semantic_node_spec.rb +95 -0
- data/spec/integration/solr_service_spec.rb +33 -0
- data/spec/samples/models/audio_record.rb +29 -0
- data/spec/samples/models/image.rb +5 -0
- data/spec/samples/models/oral_history.rb +50 -0
- data/spec/samples/models/seminar.rb +29 -0
- data/spec/samples/models/seminar_audio_file.rb +34 -0
- data/spec/samples/oh_qdc.xml +32 -0
- data/spec/samples/oral_history_sample.xml +38 -0
- data/spec/samples/oral_history_sample_model.rb +39 -0
- data/spec/samples/oral_history_xml.xml +35 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/unit/active_fedora_spec.rb +15 -0
- data/spec/unit/base_cma_spec.rb +25 -0
- data/spec/unit/base_datastream_management_spec.rb +119 -0
- data/spec/unit/base_extra_spec.rb +108 -0
- data/spec/unit/base_file_management_spec.rb +90 -0
- data/spec/unit/base_loader_spec.rb +43 -0
- data/spec/unit/base_spec.rb +584 -0
- data/spec/unit/connection_spec.rb +25 -0
- data/spec/unit/content_model_spec.rb +51 -0
- data/spec/unit/datastream_concurrency_spec.rb +59 -0
- data/spec/unit/datastream_spec.rb +85 -0
- data/spec/unit/fedora_object_spec.rb +66 -0
- data/spec/unit/inheritance_spec.rb +46 -0
- data/spec/unit/metadata_datastream_spec.rb +290 -0
- data/spec/unit/model_spec.rb +186 -0
- data/spec/unit/property_spec.rb +50 -0
- data/spec/unit/qualified_dublin_core_datastream_spec.rb +177 -0
- data/spec/unit/relationship_spec.rb +77 -0
- data/spec/unit/rels_ext_datastream_spec.rb +99 -0
- data/spec/unit/repository_spec.rb +136 -0
- data/spec/unit/rf_datastream_spec.rb +49 -0
- data/spec/unit/semantic_node_spec.rb +354 -0
- data/spec/unit/solr_config_options_spec.rb +98 -0
- data/spec/unit/solr_mapper_spec.rb +31 -0
- data/spec/unit/solr_service_spec.rb +83 -0
- data/tasks/hoe.rake +0 -0
- data/tasks/rspec.rake +29 -0
- metadata +373 -55
data/lib/active_fedora/base.rb
CHANGED
@@ -6,7 +6,7 @@ SOLR_DOCUMENT_ID = "id" unless defined?(SOLR_DOCUMENT_ID)
|
|
6
6
|
ENABLE_SOLR_UPDATES = true unless defined?(ENABLE_SOLR_UPDATES)
|
7
7
|
|
8
8
|
module ActiveFedora
|
9
|
-
|
9
|
+
|
10
10
|
# This class ties together many of the lower-level modules, and
|
11
11
|
# implements something akin to an ActiveRecord-alike interface to
|
12
12
|
# fedora. If you want to represent a fedora object in the ruby
|
@@ -32,6 +32,7 @@ module ActiveFedora
|
|
32
32
|
ms_inheritable_attributes :ds_specs
|
33
33
|
include Model
|
34
34
|
include SemanticNode
|
35
|
+
include SolrMapper
|
35
36
|
|
36
37
|
has_relationship "collection_members", :has_collection_member
|
37
38
|
|
@@ -56,7 +57,7 @@ module ActiveFedora
|
|
56
57
|
attrs = attrs.merge!({:pid=>Fedora::Repository.instance.nextid})
|
57
58
|
@new_object=true
|
58
59
|
else
|
59
|
-
@new_object=false
|
60
|
+
@new_object = attrs[:new_object] == false ? false : true
|
60
61
|
end
|
61
62
|
@inner_object = Fedora::FedoraObject.new(attrs)
|
62
63
|
@datastreams = {}
|
@@ -75,23 +76,24 @@ module ActiveFedora
|
|
75
76
|
#Saves a Base object, and any dirty datastreams, then updates
|
76
77
|
#the Solr index for this object.
|
77
78
|
def save
|
78
|
-
metadata_is_dirty = false
|
79
|
+
#@metadata_is_dirty = false
|
79
80
|
# If it's a new object, set the conformsTo relationship for Fedora CMA
|
80
81
|
if new_object?
|
81
|
-
|
82
|
-
|
82
|
+
result = create
|
83
|
+
else
|
84
|
+
result = update
|
83
85
|
end
|
84
86
|
@new_object = false
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
87
|
+
self.update_index if @metadata_is_dirty == true && ENABLE_SOLR_UPDATES
|
88
|
+
@metadata_is_dirty == false
|
89
|
+
return result
|
90
|
+
end
|
91
|
+
|
92
|
+
# Refreshes the object's info from Fedora
|
93
|
+
# Note: Currently just registers any new datastreams that have appeared in fedora
|
94
|
+
def refresh
|
95
|
+
inner_object.load_attributes_from_fedora
|
96
|
+
@datastreams = datastreams_in_fedora.merge(datastreams_in_memory)
|
95
97
|
end
|
96
98
|
|
97
99
|
#Deletes a Base object, also deletes the info indexed in Solr, and
|
@@ -115,7 +117,8 @@ module ActiveFedora
|
|
115
117
|
if @new_object
|
116
118
|
@datastreams = datastreams_in_memory
|
117
119
|
else
|
118
|
-
@datastreams = datastreams_in_fedora
|
120
|
+
@datastreams = (@datastreams == {}) ? datastreams_in_fedora : datastreams_in_memory
|
121
|
+
#@datastreams = datastreams_in_fedora.merge(datastreams_in_memory)
|
119
122
|
end
|
120
123
|
|
121
124
|
end
|
@@ -327,10 +330,11 @@ module ActiveFedora
|
|
327
330
|
def self.deserialize(doc) #:nodoc:
|
328
331
|
pid = doc.elements['/foxml:digitalObject'].attributes['PID']
|
329
332
|
|
330
|
-
proto = self.new(:pid=>pid)
|
333
|
+
proto = self.new(:pid=>pid, :new_object=>false)
|
331
334
|
proto.datastreams.each do |name,ds|
|
332
|
-
ds.new_object = false
|
333
335
|
doc.elements.each("//foxml:datastream[@ID='#{name}']") do |el|
|
336
|
+
# datastreams remain marked as new if the foxml doesn't have an entry for that datastream
|
337
|
+
ds.new_object = false
|
334
338
|
proto.datastreams[name]=ds.class.from_xml(ds, el)
|
335
339
|
end
|
336
340
|
end
|
@@ -343,7 +347,7 @@ module ActiveFedora
|
|
343
347
|
#system_create_date, system_modified_date, active_fedora_model_field,
|
344
348
|
#and the object id.
|
345
349
|
def fields
|
346
|
-
fields = {:id => {:values => [pid]}, :system_create_date => {:values => [self.create_date]}, :system_modified_date => {:values => [self.modified_date]}, :
|
350
|
+
fields = {:id => {:values => [pid]}, :system_create_date => {:values => [self.create_date], :type=>:date}, :system_modified_date => {:values => [self.modified_date], :type=>:date}, :active_fedora_model => {:values => [self.class.inspect], :type=>:symbol}}
|
347
351
|
datastreams.values.each do |ds|
|
348
352
|
fields.merge!(ds.fields) if ds.kind_of?(ActiveFedora::MetadataDatastream)
|
349
353
|
end
|
@@ -353,7 +357,7 @@ module ActiveFedora
|
|
353
357
|
#Returns the xml version of this object as a string.
|
354
358
|
def to_xml(xml=REXML::Document.new("<xml><fields/><content/></xml>"))
|
355
359
|
fields_xml = xml.root.elements['fields']
|
356
|
-
{:id => pid, :system_create_date => self.create_date, :system_modified_date => self.modified_date, :
|
360
|
+
{:id => pid, :system_create_date => self.create_date, :system_modified_date => self.modified_date, :active_fedora_model => self.class.inspect}.each_pair do |attribute_name, value|
|
357
361
|
el = REXML::Element.new(attribute_name.to_s)
|
358
362
|
el.text = value
|
359
363
|
fields_xml << el
|
@@ -366,7 +370,7 @@ module ActiveFedora
|
|
366
370
|
|
367
371
|
#Return a Solr::Document version of this object.
|
368
372
|
def to_solr(solr_doc = Solr::Document.new)
|
369
|
-
solr_doc << {SOLR_DOCUMENT_ID.to_sym => pid, :
|
373
|
+
solr_doc << {SOLR_DOCUMENT_ID.to_sym => pid, solr_name(:system_create, :date) => self.create_date, solr_name(:system_modified, :date) => self.modified_date, solr_name(:active_fedora_model, :symbol) => self.class.inspect}
|
370
374
|
datastreams.each_value do |ds|
|
371
375
|
solr_doc = ds.to_solr(solr_doc) if ds.kind_of?(ActiveFedora::MetadataDatastream) || ds.kind_of?(ActiveFedora::RelsExtDatastream)
|
372
376
|
end
|
@@ -440,7 +444,9 @@ module ActiveFedora
|
|
440
444
|
else
|
441
445
|
ds_array = datastreams.values
|
442
446
|
end
|
447
|
+
result = params.dup
|
443
448
|
params.each do |key,value|
|
449
|
+
result[key] = value.dup
|
444
450
|
ds_array.each do |dstream|
|
445
451
|
if dstream.fields[key.to_sym]
|
446
452
|
aname="#{key}_values"
|
@@ -454,13 +460,20 @@ module ActiveFedora
|
|
454
460
|
false
|
455
461
|
end
|
456
462
|
end
|
457
|
-
cpv.each
|
463
|
+
cpv.each do |y,z|
|
464
|
+
curval<<z #just append everything left
|
465
|
+
if y == "-1"
|
466
|
+
new_array_index = curval.length - 1
|
467
|
+
result[key][new_array_index.to_s] = params[key]["-1"]
|
468
|
+
end
|
469
|
+
end
|
458
470
|
curval.delete_if {|x| x == :delete || x == "" || x == nil}
|
459
471
|
dstream.send("#{aname}=", curval) #write it back to the ds
|
460
472
|
end
|
461
473
|
end
|
474
|
+
result[key].delete("-1")
|
462
475
|
end
|
463
|
-
|
476
|
+
return result
|
464
477
|
end
|
465
478
|
|
466
479
|
def self.pids_from_uris(uris)
|
@@ -485,6 +498,29 @@ module ActiveFedora
|
|
485
498
|
end
|
486
499
|
end
|
487
500
|
end
|
501
|
+
|
502
|
+
# Deals with preparing new object to be saved to Fedora, then pushes it and its datastreams into Fedora.
|
503
|
+
def create
|
504
|
+
add_relationship(:has_model, ActiveFedora::ContentModel.pid_from_ruby_class(self.class))
|
505
|
+
@metadata_is_dirty = true
|
506
|
+
update
|
507
|
+
#@datastreams = datastreams_in_fedora
|
508
|
+
end
|
509
|
+
|
510
|
+
# Pushes the object and all of its new or dirty datastreams into Fedora
|
511
|
+
def update
|
512
|
+
result = Fedora::Repository.instance.save(@inner_object)
|
513
|
+
datastreams_in_memory.each do |k,ds|
|
514
|
+
if ds.dirty? || ds.new_object?
|
515
|
+
if ds.kind_of?(ActiveFedora::MetadataDatastream) || ds.instance_of?(ActiveFedora::RelsExtDatastream)
|
516
|
+
@metadata_is_dirty = true
|
517
|
+
end
|
518
|
+
result = ds.save
|
519
|
+
end
|
520
|
+
end
|
521
|
+
refresh
|
522
|
+
return result
|
523
|
+
end
|
488
524
|
|
489
525
|
|
490
526
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module ActiveFedora
|
2
2
|
#this class represents a MetadataDatastream, a special case of ActiveFedora::Datastream
|
3
3
|
class MetadataDatastream < Datastream
|
4
|
+
|
5
|
+
include ActiveFedora::SolrMapper
|
6
|
+
|
4
7
|
attr_accessor :fields
|
5
8
|
|
6
9
|
#constructor, calls up to ActiveFedora::Datastream's constructor
|
@@ -110,13 +113,17 @@ module ActiveFedora
|
|
110
113
|
protected
|
111
114
|
|
112
115
|
def generate_solr_symbol(field_name, field_type) # :nodoc:
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
116
|
+
solr_name(field_name, field_type)
|
117
|
+
# #if field_name.to_s[-field_type.to_s.length - 1 .. -1] == "_#{field_type.to_s}"
|
118
|
+
# # return field_name.to_sym
|
119
|
+
# case field_type
|
120
|
+
# when :date
|
121
|
+
# return "#{field_name.to_s}_dt".to_sym
|
122
|
+
# when :string
|
123
|
+
# return "#{field_name.to_s}_t".to_sym
|
124
|
+
# else
|
125
|
+
# return "#{field_name.to_s}_t".to_sym
|
126
|
+
# end
|
120
127
|
end
|
121
128
|
|
122
129
|
end
|
data/lib/active_fedora/model.rb
CHANGED
@@ -56,14 +56,14 @@ module ActiveFedora
|
|
56
56
|
def find(args)
|
57
57
|
if args == :all
|
58
58
|
escaped_class_name = self.name.gsub(/(:)/, '\\:')
|
59
|
-
q = "
|
59
|
+
q = "active_fedora_model_s:#{escaped_class_name}"
|
60
60
|
elsif args.class == String
|
61
61
|
escaped_id = args.gsub(/(:)/, '\\:')
|
62
62
|
q = "#{SOLR_DOCUMENT_ID}:#{escaped_id}"
|
63
63
|
end
|
64
64
|
hits = SolrService.instance.conn.query(q).hits
|
65
65
|
results = hits.map do |hit|
|
66
|
-
obj = Fedora::Repository.instance.find_model(hit[
|
66
|
+
obj = Fedora::Repository.instance.find_model(hit[SOLR_DOCUMENT_ID], self)
|
67
67
|
#obj.inner_object.new_object = false
|
68
68
|
#return obj
|
69
69
|
end
|
@@ -77,7 +77,7 @@ module ActiveFedora
|
|
77
77
|
|
78
78
|
|
79
79
|
# If query is :all, this method will query Solr for all instances
|
80
|
-
# of self.type (based on
|
80
|
+
# of self.type (based on active_fedora_model_s as indexed
|
81
81
|
# by Solr). If the query is any other string, this method simply does
|
82
82
|
# a pid based search (id:query).
|
83
83
|
#
|
@@ -89,7 +89,7 @@ module ActiveFedora
|
|
89
89
|
def find_by_solr(query, args={})
|
90
90
|
if query == :all
|
91
91
|
escaped_class_name = self.name.gsub(/(:)/, '\\:')
|
92
|
-
SolrService.instance.conn.query("
|
92
|
+
SolrService.instance.conn.query("active_fedora_model_s:#{escaped_class_name}", args)
|
93
93
|
elsif query.class == String
|
94
94
|
escaped_id = query.gsub(/(:)/, '\\:')
|
95
95
|
SolrService.instance.conn.query("#{SOLR_DOCUMENT_ID}:#{escaped_id}", args)
|
@@ -43,7 +43,7 @@ module ActiveFedora
|
|
43
43
|
if subject == :self || subject == "info:fedora/#{self.pid}"
|
44
44
|
predicates.each_pair do |predicate, values|
|
45
45
|
values.each do |val|
|
46
|
-
solr_doc << Solr::Field.new("#{predicate}
|
46
|
+
solr_doc << Solr::Field.new("#{predicate}_s" => val)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
@@ -26,7 +26,8 @@ module ActiveFedora
|
|
26
26
|
:is_annotation_of => "isAnnotationOf",
|
27
27
|
:has_annotation => "hasAnnotation",
|
28
28
|
:has_equivalent => "hasEquivalent",
|
29
|
-
:conforms_to => "conformsTo"
|
29
|
+
:conforms_to => "conformsTo",
|
30
|
+
:has_model => "hasModel"]
|
30
31
|
PREDICATE_MAPPINGS.freeze
|
31
32
|
|
32
33
|
def self.included(klass)
|
@@ -147,14 +148,14 @@ module ActiveFedora
|
|
147
148
|
class_eval <<-END
|
148
149
|
def #{name}(opts={})
|
149
150
|
escaped_uri = self.internal_uri.gsub(/(:)/, '\\:')
|
150
|
-
solr_result = SolrService.instance.conn.query("#{predicate}
|
151
|
+
solr_result = SolrService.instance.conn.query("#{predicate}_s:\#{escaped_uri}")
|
151
152
|
if opts[:response_format] == :solr
|
152
153
|
return solr_result
|
153
154
|
else
|
154
155
|
if opts[:response_format] == :id_array
|
155
156
|
id_array = []
|
156
157
|
solr_result.hits.each do |hit|
|
157
|
-
id_array << hit[
|
158
|
+
id_array << hit[SOLR_DOCUMENT_ID]
|
158
159
|
end
|
159
160
|
return id_array
|
160
161
|
else
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'active_fedora/solr_service'
|
2
|
+
|
3
|
+
module ActiveFedora
|
4
|
+
module SolrMapper
|
5
|
+
|
6
|
+
# Generates solr field names from settings in solr_mappings
|
7
|
+
def solr_name(field_name, field_type)
|
8
|
+
name = field_name.to_s + ActiveFedora::SolrService.mappings[field_type.to_s].to_s
|
9
|
+
if field_name.kind_of?(Symbol)
|
10
|
+
return name.to_sym
|
11
|
+
else
|
12
|
+
return name.to_s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'solr'
|
2
2
|
module ActiveFedora
|
3
3
|
class SolrService
|
4
|
+
@@mappings = {}
|
4
5
|
attr_reader :conn
|
6
|
+
|
5
7
|
def self.register(host=nil, args={})
|
6
8
|
Thread.current[:solr_service]=self.new(host, args)
|
7
9
|
|
@@ -11,26 +13,29 @@ module ActiveFedora
|
|
11
13
|
opts = {:autocommit=>:on}.merge(args)
|
12
14
|
@conn = Solr::Connection.new(host, opts)
|
13
15
|
end
|
16
|
+
|
14
17
|
def self.instance
|
15
18
|
raise SolrNotInitialized unless Thread.current[:solr_service]
|
16
19
|
Thread.current[:solr_service]
|
17
20
|
end
|
21
|
+
|
18
22
|
def self.reify_solr_results(solr_result)
|
19
23
|
unless solr_result.is_a?(Solr::Response::Standard)
|
20
24
|
raise ArgumentError.new("Only solr responses (Solr::Response::Standard) are allowed. You provided a #{solr_result.class}")
|
21
25
|
end
|
22
26
|
results = []
|
23
27
|
solr_result.hits.each do |hit|
|
24
|
-
model_value = hit["
|
28
|
+
model_value = hit["active_fedora_model_s"].first
|
25
29
|
if model_value.include?("::")
|
26
30
|
classname = eval(model_value)
|
27
31
|
else
|
28
32
|
classname = Kernel.const_get(model_value)
|
29
33
|
end
|
30
|
-
results << Fedora::Repository.instance.find_model(hit[
|
34
|
+
results << Fedora::Repository.instance.find_model(hit[SOLR_DOCUMENT_ID], classname)
|
31
35
|
end
|
32
36
|
return results
|
33
37
|
end
|
38
|
+
|
34
39
|
def self.construct_query_for_pids(pid_array)
|
35
40
|
query = ""
|
36
41
|
pid_array.each_index do |i|
|
@@ -40,9 +45,46 @@ module ActiveFedora
|
|
40
45
|
query = "id:NEVER_USE_THIS_ID" if query.empty? || query == "id:"
|
41
46
|
return query
|
42
47
|
end
|
48
|
+
|
43
49
|
def self.escape_uri_for_query(uri)
|
44
50
|
return uri.gsub(/(:)/, '\\:')
|
45
51
|
end
|
52
|
+
|
53
|
+
def self.mappings
|
54
|
+
@@mappings
|
55
|
+
end
|
56
|
+
def self.mappings=(mappings)
|
57
|
+
@@mappings = mappings
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.logger
|
61
|
+
@logger ||= defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : Logger.new(STDOUT)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Loads solr mappings from yml file.
|
65
|
+
# @config_path This is the path to the directory where your mappings file is stored. @default "RAILS_ROOT/config/solr_mappings.yml"
|
66
|
+
# @mappings_file This is the filename for your solr mappings YAML file. @default solr_mappings.yml
|
67
|
+
def self.load_mappings( config_path=nil )
|
68
|
+
|
69
|
+
if config_path.nil?
|
70
|
+
if defined?(RAILS_ROOT)
|
71
|
+
config_path = File.join(RAILS_ROOT, "config", "solr_mappings.yml")
|
72
|
+
end
|
73
|
+
# Default to using the config file within the gem
|
74
|
+
if !File.exist?(config_path.to_s)
|
75
|
+
config_path = File.join(File.dirname(__FILE__), "..", "..", "config", "solr_mappings.yml")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
logger.info("FEDORA: loading SolrService mappings from #{File.expand_path(config_path)}")
|
80
|
+
|
81
|
+
@@mappings = YAML::load(File.open(config_path))
|
82
|
+
|
83
|
+
mappings["id"] = "id" unless mappings["id"]
|
84
|
+
end
|
85
|
+
|
86
|
+
self.load_mappings
|
87
|
+
|
46
88
|
end
|
47
89
|
class SolrNotInitialized < StandardError;end
|
48
90
|
end
|
data/lib/fedora/base.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'xmlsimple'
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
# {:q => 'test', :num => 5}.to_query # => 'q=test&num=5'
|
5
|
+
# let's avoid stomping on rails' version eh?
|
6
|
+
def to_fedora_query
|
7
|
+
self.collect { |key, value| "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}" }.sort * '&'
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.from_xml(xml)
|
11
|
+
XmlSimple.xml_in(xml, 'ForceArray' => false)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Fedora::BaseObject
|
16
|
+
attr_accessor :attributes, :blob, :uri
|
17
|
+
attr_reader :errors, :uri
|
18
|
+
attr_writer :new_object
|
19
|
+
|
20
|
+
# == Parameters
|
21
|
+
# attrs<Hash>:: object attributes
|
22
|
+
#-
|
23
|
+
def initialize(attrs = {})
|
24
|
+
@new_object = true
|
25
|
+
@attributes = attrs || {}
|
26
|
+
@errors = []
|
27
|
+
@blob = attributes.delete(:blob)
|
28
|
+
@repository = Fedora::Repository.instance
|
29
|
+
end
|
30
|
+
|
31
|
+
def [](key)
|
32
|
+
@attributes[key]
|
33
|
+
end
|
34
|
+
|
35
|
+
def new_object?
|
36
|
+
@new_object
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require "base64"
|
2
|
+
gem 'multipart-post'
|
3
|
+
require 'net/http/post/multipart'
|
4
|
+
require 'cgi'
|
5
|
+
require "mime/types"
|
6
|
+
require 'net/http'
|
7
|
+
require 'net/https'
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
module Fedora
|
12
|
+
# This class is based on ActiveResource::Connection so MIT license applies.
|
13
|
+
class ConnectionError < StandardError # :nodoc:
|
14
|
+
attr_reader :response
|
15
|
+
|
16
|
+
def initialize(response, message = nil)
|
17
|
+
@response = response
|
18
|
+
@message = message
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"Failed with #{response.code} #{response.message if response.respond_to?(:message)}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# 3xx Redirection
|
27
|
+
class Redirection < ConnectionError # :nodoc:
|
28
|
+
def to_s; response['Location'] ? "#{super} => #{response['Location']}" : super; end
|
29
|
+
end
|
30
|
+
|
31
|
+
# 4xx Client Error
|
32
|
+
class ClientError < ConnectionError; end # :nodoc:
|
33
|
+
|
34
|
+
# 400 Bad Request
|
35
|
+
class BadRequest < ClientError; end # :nodoc
|
36
|
+
|
37
|
+
# 401 Unauthorized
|
38
|
+
class UnauthorizedAccess < ClientError; end # :nodoc
|
39
|
+
|
40
|
+
# 403 Forbidden
|
41
|
+
class ForbiddenAccess < ClientError; end # :nodoc
|
42
|
+
|
43
|
+
# 404 Not Found
|
44
|
+
class ResourceNotFound < ClientError; end # :nodoc:
|
45
|
+
|
46
|
+
# 409 Conflict
|
47
|
+
class ResourceConflict < ClientError; end # :nodoc:
|
48
|
+
|
49
|
+
# 5xx Server Error
|
50
|
+
class ServerError < ConnectionError; end # :nodoc:
|
51
|
+
|
52
|
+
# 405 Method Not Allowed
|
53
|
+
class MethodNotAllowed < ClientError # :nodoc:
|
54
|
+
def allowed_methods
|
55
|
+
@response['Allow'].split(',').map { |verb| verb.strip.downcase.to_sym }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Class to handle connections to remote web services.
|
60
|
+
# This class is used by ActiveResource::Base to interface with REST
|
61
|
+
# services.
|
62
|
+
class Connection
|
63
|
+
attr_reader :site, :surrogate
|
64
|
+
attr_accessor :format
|
65
|
+
|
66
|
+
class << self
|
67
|
+
def requests
|
68
|
+
@@requests ||= []
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# The +site+ parameter is required and will set the +site+
|
73
|
+
# attribute to the URI for the remote resource service.
|
74
|
+
def initialize(site, format = ActiveResource::Formats[:xml], surrogate=nil)
|
75
|
+
raise ArgumentError, 'Missing site URI' unless site
|
76
|
+
self.site = site
|
77
|
+
self.format = format
|
78
|
+
@surrogate=surrogate
|
79
|
+
end
|
80
|
+
|
81
|
+
# Set URI for remote service.
|
82
|
+
def site=(site)
|
83
|
+
@site = site.is_a?(URI) ? site : URI.parse(site)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Execute a GET request.
|
87
|
+
# Used to get (find) resources.
|
88
|
+
def get(path, headers = {})
|
89
|
+
format.decode(request(:get, path, build_request_headers(headers)).body)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Execute a DELETE request (see HTTP protocol documentation if unfamiliar).
|
93
|
+
# Used to delete resources.
|
94
|
+
def delete(path, headers = {})
|
95
|
+
request(:delete, path, build_request_headers(headers))
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
def raw_get(path, headers = {})
|
101
|
+
request(:get, path, build_request_headers(headers))
|
102
|
+
end
|
103
|
+
def post(path, body='', headers={})
|
104
|
+
do_method(:post, path, body, headers)
|
105
|
+
end
|
106
|
+
def put( path, body='', headers={})
|
107
|
+
do_method(:put, path, body, headers)
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
def do_method(method, path, body = '', headers = {})
|
112
|
+
meth_map={:put=>Net::HTTP::Put::Multipart, :post=>Net::HTTP::Post::Multipart}
|
113
|
+
raise "undefined method: #{method}" unless meth_map.has_key? method
|
114
|
+
headers = build_request_headers(headers)
|
115
|
+
if body.respond_to?(:read)
|
116
|
+
if body.respond_to?(:original_filename?)
|
117
|
+
filename = File.basename(body.original_filename)
|
118
|
+
io = UploadIO.new(body, mime_type,filename)
|
119
|
+
elsif body.path
|
120
|
+
filename = File.basename(body.path)
|
121
|
+
else
|
122
|
+
filename="NOFILE"
|
123
|
+
end
|
124
|
+
mime_types = MIME::Types.of(filename)
|
125
|
+
mime_type ||= mime_types.empty? ? "application/octet-stream" : mime_types.first.content_type
|
126
|
+
|
127
|
+
io = nil
|
128
|
+
if body.is_a?(File)
|
129
|
+
io = UploadIO.new(body.path,mime_type)
|
130
|
+
else
|
131
|
+
io =UploadIO.new(body, mime_type, filename)
|
132
|
+
end
|
133
|
+
|
134
|
+
req = meth_map[method].new(path, {:file=>io}, headers)
|
135
|
+
multipart_request(req)
|
136
|
+
else
|
137
|
+
request(method, path, body.to_s, headers)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
def multipart_request(req)
|
141
|
+
result = nil
|
142
|
+
result = http.start do |conn|
|
143
|
+
conn.read_timeout=60600 #these can take a while
|
144
|
+
conn.request(req)
|
145
|
+
end
|
146
|
+
handle_response(result)
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
# Makes request to remote service.
|
151
|
+
def request(method, path, *arguments)
|
152
|
+
result = http.send(method, path, *arguments)
|
153
|
+
handle_response(result)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Handles response and error codes from remote service.
|
157
|
+
def handle_response(response)
|
158
|
+
case response.code.to_i
|
159
|
+
when 301,302
|
160
|
+
raise(Redirection.new(response))
|
161
|
+
when 200...400
|
162
|
+
response
|
163
|
+
when 400
|
164
|
+
raise(BadRequest.new(response))
|
165
|
+
when 401
|
166
|
+
raise(UnauthorizedAccess.new(response))
|
167
|
+
when 403
|
168
|
+
raise(ForbiddenAccess.new(response))
|
169
|
+
when 404
|
170
|
+
raise(ResourceNotFound.new(response))
|
171
|
+
when 405
|
172
|
+
raise(MethodNotAllowed.new(response))
|
173
|
+
when 409
|
174
|
+
raise(ResourceConflict.new(response))
|
175
|
+
when 422
|
176
|
+
raise(ResourceInvalid.new(response))
|
177
|
+
when 401...500
|
178
|
+
raise(ClientError.new(response))
|
179
|
+
when 500...600
|
180
|
+
raise(ServerError.new(response))
|
181
|
+
else
|
182
|
+
raise(ConnectionError.new(response, "Unknown response code: #{response.code}"))
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Creates new Net::HTTP instance for communication with
|
187
|
+
# remote service and resources.
|
188
|
+
def http
|
189
|
+
http = Net::HTTP.new(@site.host, @site.port)
|
190
|
+
http.use_ssl = @site.is_a?(URI::HTTPS)
|
191
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl
|
192
|
+
http
|
193
|
+
end
|
194
|
+
|
195
|
+
def default_header
|
196
|
+
@default_header ||= { 'Content-Type' => format.mime_type }
|
197
|
+
end
|
198
|
+
|
199
|
+
# Builds headers for request to remote service.
|
200
|
+
def build_request_headers(headers)
|
201
|
+
headers.merge!({"From"=>surrogate}) if @surrogate
|
202
|
+
authorization_header.update(default_header).update(headers)
|
203
|
+
end
|
204
|
+
|
205
|
+
# Sets authorization header; authentication information is pulled from credentials provided with site URI.
|
206
|
+
def authorization_header
|
207
|
+
(@site.user || @site.password ? { 'Authorization' => 'Basic ' + ["#{@site.user}:#{ @site.password}"].pack('m').delete("\r\n") } : {})
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|