active-fedora 1.0.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ == Getting Help
2
+
3
+ * Project Homepage: <http://yourmediashelf.com/activefedora>
4
+ * Further documentation is available at <http://projects.mediashelf.us/show/active-fedora>
5
+ * Community Discussions & Mailing List are located at <http://groups.google.com/group/active-fedora>
6
+
1
7
  = afed-regem
2
8
 
3
9
  * FIX (url)
@@ -24,17 +30,21 @@ FIX (describe your package)
24
30
 
25
31
  == LICENSE:
26
32
 
27
- (The MIT License)
33
+ Copyright (c) 2009 Matt Zumwalt
34
+
35
+ This program is free software: you can redistribute it and/or modify
36
+ it under the terms of the GNU Lesser General Public License (LGPL) as
37
+ published by the Free Software Foundation, either version 3 of the License,
38
+ or (at your option) any later version.
28
39
 
29
- Copyright (c) 2009 FIXME full name
40
+ This program is distributed in the hope that it will be useful,
41
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
42
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43
+ GNU General Public License for more details.
30
44
 
31
- Permission is hereby granted, free of charge, to any person obtaining
32
- a copy of this software and associated documentation files (the
33
- 'Software'), to deal in the Software without restriction, including
34
- without limitation the rights to use, copy, modify, merge, publish,
35
- distribute, sublicense, and/or sell copies of the Software, and to
36
- permit persons to whom the Software is furnished to do so, subject to
37
- the following conditions:
45
+ You should have received a copy of the GNU Lesser General Public License
46
+ along with this program. If not, see <http://www.gnu.org/licenses/> or
47
+ see <http://www.gnu.org/licenses/lgpl.html>.
38
48
 
39
49
  The above copyright notice and this permission notice shall be
40
50
  included in all copies or substantial portions of the Software.
@@ -2,8 +2,12 @@ require 'rubygems'
2
2
  gem 'ruby-fedora'
3
3
  gem 'solr-ruby'
4
4
  module ActiveFedora #:nodoc:
5
- VERSION='1.0.2'
5
+ VERSION='1.0.4'
6
6
  end
7
+
8
+ SOLR_DOCUMENT_ID = "id" unless defined?(SOLR_DOCUMENT_ID)
9
+ ENABLE_SOLR_UPDATES = true unless defined?(ENABLE_SOLR_UPDATES)
10
+
7
11
  require 'ruby-fedora'
8
12
  require 'active_fedora/base.rb'
9
13
  require 'active_fedora/content_model.rb'
@@ -17,3 +21,4 @@ require 'active_fedora/relationship.rb'
17
21
  require 'active_fedora/rels_ext_datastream.rb'
18
22
  require 'active_fedora/semantic_node.rb'
19
23
  require 'active_fedora/solr_service.rb'
24
+
@@ -1,6 +1,10 @@
1
1
  require 'util/class_level_inheritable_attributes'
2
2
  require 'active_fedora/model'
3
3
  require 'active_fedora/semantic_node'
4
+
5
+ SOLR_DOCUMENT_ID = "id" unless defined?(SOLR_DOCUMENT_ID)
6
+ ENABLE_SOLR_UPDATES = true unless defined?(ENABLE_SOLR_UPDATES)
7
+
4
8
  module ActiveFedora
5
9
 
6
10
  # This class ties together many of the lower-level modules, and
@@ -29,6 +33,9 @@ module ActiveFedora
29
33
  include Model
30
34
  include SemanticNode
31
35
 
36
+ has_relationship "collection_members", :has_collection_member
37
+
38
+
32
39
  # Has this object been saved?
33
40
  def new_object?
34
41
  @new_object
@@ -63,21 +70,23 @@ module ActiveFedora
63
70
  #Saves a Base object, and any dirty datastreams, then updates
64
71
  #the Solr index for this object.
65
72
  def save
73
+ metadata_is_dirty = false
66
74
  # If it's a new object, set the conformsTo relationship for Fedora CMA
67
75
  if new_object?
68
76
  add_relationship(:conforms_to, ActiveFedora::ContentModel.pid_from_ruby_class(self.class))
77
+ metadata_is_dirty = true
69
78
  end
70
- @new_object =false
79
+ @new_object = false
71
80
  Fedora::Repository.instance.save(@inner_object)
72
81
  datastreams_in_memory.each do |k,ds|
73
82
  if ds.dirty? || ds.new_object?
74
- if ds.kind_of?(ActiveFedora::MetadataDatastream)
83
+ if ds.kind_of?(ActiveFedora::MetadataDatastream) || ds.instance_of?(ActiveFedora::RelsExtDatastream)
75
84
  metadata_is_dirty = true
76
85
  end
77
86
  ds.save
78
- end
79
- self.update_index if metadata_is_dirty == true
87
+ end
80
88
  end
89
+ self.update_index if metadata_is_dirty == true && ENABLE_SOLR_UPDATES
81
90
  end
82
91
 
83
92
  #Deletes a Base object, also deletes the info indexed in Solr, and
@@ -85,9 +94,14 @@ module ActiveFedora
85
94
  def delete
86
95
  Fedora::Repository.instance.delete(@inner_object)
87
96
  escaped_pid = self.pid.gsub(/(:)/, '\\:')
88
- SolrService.instance.conn.delete(escaped_pid)
97
+ SolrService.instance.conn.delete(escaped_pid) if ENABLE_SOLR_UPDATES
89
98
  end
90
99
 
100
+
101
+ #
102
+ # Datastream Management
103
+ #
104
+
91
105
  # Returns all known datastreams for the object. If the object has been
92
106
  # saved to fedora, the persisted datastreams will be included.
93
107
  # Datastreams that have been modified in memory are given preference over
@@ -104,7 +118,7 @@ module ActiveFedora
104
118
  def datastreams_in_fedora #:nodoc:
105
119
  mds = {}
106
120
  self.datastreams_xml['datastream'].each do |ds|
107
- ds.merge!({:pid => self.pid, :dsID => ds["dsid"]})
121
+ ds.merge!({:pid => self.pid, :dsID => ds["dsid"], :dsLabel => ds["label"]})
108
122
  if ds["dsid"] == "RELS-EXT"
109
123
  mds.merge!({ds["dsid"] => ActiveFedora::RelsExtDatastream.new(ds)})
110
124
  else
@@ -125,10 +139,17 @@ module ActiveFedora
125
139
  end
126
140
 
127
141
  # Adds datastream to the object. Saves the datastream to fedora upon adding.
128
- def add_datastream(datastream)
142
+ # If datastream does not have a DSID, a unique DSID is generated
143
+ # :prefix option will set the prefix on auto-generated DSID
144
+ # @returns DSID of the added datastream
145
+ def add_datastream(datastream, opts={})
129
146
  datastream.pid = self.pid
147
+ if datastream.dsid == nil || datastream.dsid.empty?
148
+ prefix = opts.has_key?(:prefix) ? opts[:prefix] : "DS"
149
+ datastream.dsid = generate_dsid(prefix)
150
+ end
130
151
  datastreams[datastream.dsid] = datastream
131
- return true
152
+ return datastream.dsid
132
153
  end
133
154
  def add(datastream) # :nodoc:
134
155
  warn "Warning: ActiveFedora::Base.add has been deprected. Use add_datastream"
@@ -161,6 +182,18 @@ module ActiveFedora
161
182
  return results
162
183
  end
163
184
 
185
+ # return a valid dsid that is not currently in use. Uses a prefix (default "DS") and an auto-incrementing integer
186
+ # Example: if there are already datastreams with IDs DS1 and DS2, this method will return DS3. If you specify FOO as the prefix, it will return FOO1.
187
+ def generate_dsid(prefix="DS")
188
+ keys = datastreams.keys
189
+ next_index = keys.select {|v| v =~ /(#{prefix}\d*$)/}.count + 1
190
+ new_dsid = prefix.to_s + next_index.to_s
191
+ # while keys.include?(new_dsid)
192
+ # next_index += 1
193
+ # new_dsid = prefix.to_s + rand(range).to_s
194
+ # end
195
+ end
196
+
164
197
  # Return the Dublin Core (DC) Datastream. You can also get at this via
165
198
  # the +datastreams["DC"]+.
166
199
  def dc
@@ -179,6 +212,38 @@ module ActiveFedora
179
212
  return datastreams["RELS-EXT"]
180
213
  end
181
214
 
215
+ #
216
+ # File Management
217
+ #
218
+
219
+ def add_file_datastream(file, opts={})
220
+ label = opts.has_key?(:label) ? opts[:label] : ""
221
+ ds = ActiveFedora::Datastream.new(:dsLabel => label, :controlGroup => 'M', :blob => file)
222
+ opts.has_key?(:dsid) ? ds.dsid=(opts[:dsid]) : nil
223
+ add_datastream(ds)
224
+ end
225
+
226
+ def file_objects
227
+ collection_members
228
+ end
229
+
230
+ def file_objects_append(obj)
231
+ collection_members_append(obj)
232
+ end
233
+
234
+ def collection_members_append(obj)
235
+ add_relationship(:has_collection_member, obj)
236
+ end
237
+
238
+ def collection_members_remove()
239
+ # will rely on SemanticNode.remove_relationship once it is implemented
240
+ end
241
+
242
+
243
+ #
244
+ # Relationships Management
245
+ #
246
+
182
247
  # @returns Hash of relationships, as defined by SemanticNode
183
248
  # Rely on rels_ext datastream to track relationships array
184
249
  # Overrides accessor for relationships array used by SemanticNode.
@@ -244,6 +309,10 @@ module ActiveFedora
244
309
  def label
245
310
  @inner_object.label
246
311
  end
312
+
313
+ def label=(new_label)
314
+ @inner_object.label = new_label
315
+ end
247
316
 
248
317
 
249
318
  def self.deserialize(doc) #:nodoc:
@@ -254,7 +323,8 @@ module ActiveFedora
254
323
  proto.datastreams[name]=ds.class.from_xml(ds, el)
255
324
  end
256
325
  end
257
- proto
326
+ proto.inner_object.new_object = false
327
+ return proto
258
328
  end
259
329
 
260
330
  #Return a hash of all available metadata fields for all
@@ -285,9 +355,8 @@ module ActiveFedora
285
355
 
286
356
  #Return a Solr::Document version of this object.
287
357
  def to_solr(solr_doc = Solr::Document.new)
288
- solr_doc << {:id => pid, :system_create_date => self.create_date, :system_modified_date => self.modified_date, :active_fedora_model_field => self.class.inspect}
358
+ solr_doc << {SOLR_DOCUMENT_ID.to_sym => pid, :system_create_date => self.create_date, :system_modified_date => self.modified_date, :active_fedora_model_field => self.class.inspect}
289
359
  datastreams.each_value do |ds|
290
- puts "updating solr for ds #{ds}" if ds.kind_of?(ActiveFedora::Datastream)
291
360
  solr_doc = ds.to_solr(solr_doc) if ds.kind_of?(ActiveFedora::MetadataDatastream) || ds.kind_of?(ActiveFedora::RelsExtDatastream)
292
361
  end
293
362
  return solr_doc
@@ -346,7 +415,19 @@ module ActiveFedora
346
415
  end
347
416
 
348
417
  end
349
-
418
+
419
+ def self.pids_from_uris(uris)
420
+ if uris.class == String
421
+ return uris.gsub("info:fedora/", "")
422
+ elsif uris.class == Array
423
+ arr = []
424
+ uris.each do |uri|
425
+ arr << uri.gsub("info:fedora/", "")
426
+ end
427
+ return arr
428
+ end
429
+ end
430
+
350
431
  private
351
432
  def configure_defined_datastreams
352
433
  if self.class.ds_specs
@@ -14,7 +14,7 @@ module ActiveFedora
14
14
 
15
15
  #Return the xml content representing this Datastream from Fedora
16
16
  def content
17
- result = Fedora::Repository.instance.fetch_custom(self.attributes[:pid], "datastreams/#{self.dsid}")
17
+ result = Fedora::Repository.instance.fetch_custom(self.attributes[:pid], "datastreams/#{self.dsid}/content")
18
18
  return result
19
19
  end
20
20
 
@@ -75,6 +75,7 @@ module ActiveFedora
75
75
  tmpl.send("#{f.name}_append", f.text)
76
76
  end
77
77
  tmpl.instance_variable_set(:@dirty, false)
78
+ tmpl.control_group= el.attributes['CONTROL_GROUP']
78
79
  tmpl
79
80
  end
80
81
 
@@ -1,4 +1,7 @@
1
1
  require 'active_fedora/fedora_object'
2
+
3
+ SOLR_DOCUMENT_ID = "id" unless defined?(SOLR_DOCUMENT_ID)
4
+
2
5
  module ActiveFedora
3
6
  # = ActiveFedora
4
7
  # This module mixes various methods into the including class,
@@ -56,11 +59,13 @@ module ActiveFedora
56
59
  q = "active_fedora_model_field:#{escaped_class_name}"
57
60
  elsif args.class == String
58
61
  escaped_id = args.gsub(/(:)/, '\\:')
59
- q = "id:#{escaped_id}"
62
+ q = "#{SOLR_DOCUMENT_ID}:#{escaped_id}"
60
63
  end
61
64
  hits = SolrService.instance.conn.query(q).hits
62
65
  results = hits.map do |hit|
63
66
  obj = Fedora::Repository.instance.find_model(hit["id"], self)
67
+ #obj.inner_object.new_object = false
68
+ #return obj
64
69
  end
65
70
  results.first
66
71
  end
@@ -87,7 +92,7 @@ module ActiveFedora
87
92
  SolrService.instance.conn.query("active_fedora_model_field:#{escaped_class_name}", args)
88
93
  elsif query.class == String
89
94
  escaped_id = query.gsub(/(:)/, '\\:')
90
- SolrService.instance.conn.query("id:#{escaped_id}", args)
95
+ SolrService.instance.conn.query("#{SOLR_DOCUMENT_ID}:#{escaped_id}", args)
91
96
  end
92
97
  end
93
98
 
@@ -26,6 +26,18 @@ module ActiveFedora
26
26
  EOL
27
27
  end
28
28
 
29
+ # Expects a RelsExtDatastream and a REXML Element as inputs.
30
+ def self.from_xml(tmpl, el)
31
+ #puts el.elements["./foxml:datastreamVersion[last()]/foxml:xmlContent/rdf:RDF/rdf:Description/"]
32
+ el.elements.each("./foxml:datastreamVersion[last()]/foxml:xmlContent/rdf:RDF/rdf:Description/*") do |f|
33
+ #puts "Element" + f.inspect
34
+ r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>ActiveFedora::SemanticNode::PREDICATE_MAPPINGS.invert[f.name], :object=>f.attributes["rdf:resource"])
35
+ tmpl.add_relationship(r)
36
+ end
37
+ tmpl.send(:dirty=, false)
38
+ tmpl
39
+ end
40
+
29
41
  def to_solr(solr_doc = Solr::Document.new)
30
42
  self.relationships.each_pair do |subject, predicates|
31
43
  if subject == :self || subject == "info:fedora/#{self.pid}"
@@ -6,8 +6,26 @@ module ActiveFedora
6
6
  attr_accessor :internal_uri, :relationships
7
7
 
8
8
  PREDICATE_MAPPINGS = Hash[:is_member_of => "isMemberOf",
9
+ :has_member => "hasMember",
9
10
  :is_part_of => "isPartOf",
10
11
  :has_part => "hasPart",
12
+ :is_member_of_collection => "isMemberOfCollection",
13
+ :has_collection_member => "hasCollectionMember",
14
+ :is_constituent_of => "isConstituentOf",
15
+ :has_constituent => "hasConstituent",
16
+ :is_subset_of => "isSubsetOf",
17
+ :has_subset => "hasSubset",
18
+ :is_derivation_of => "isDerivationOf",
19
+ :has_derivation => "hasDerivation",
20
+ :is_dependent_of => "isDependentOf",
21
+ :has_dependent => "hasDependent",
22
+ :is_description_of => "isDescriptionOf",
23
+ :has_description => "hasDescription",
24
+ :is_metadata_for => "isMetadataFor",
25
+ :has_metadata => "hasMetadata",
26
+ :is_annotation_of => "isAnnotationOf",
27
+ :has_annotation => "hasAnnotation",
28
+ :has_equivalent => "hasEquivalent",
11
29
  :conforms_to => "conformsTo"]
12
30
  PREDICATE_MAPPINGS.freeze
13
31
 
@@ -127,39 +145,53 @@ module ActiveFedora
127
145
 
128
146
  def create_inbound_relationship_finders(name, predicate, opts = {})
129
147
  class_eval <<-END
130
- def #{name}
148
+ def #{name}(opts={})
131
149
  escaped_uri = self.internal_uri.gsub(/(:)/, '\\:')
132
- hits = SolrService.instance.conn.query("#{predicate}_field:\#{escaped_uri}").hits
133
- results = []
134
- hits.each do |hit|
135
- classname = Kernel.const_get(hit["active_fedora_model_field"].first)
136
- results << Fedora::Repository.instance.find_model(hit["id"], classname)
150
+ solr_result = SolrService.instance.conn.query("#{predicate}_field:\#{escaped_uri}")
151
+ if opts[:response_format] == :solr
152
+ return solr_result
153
+ else
154
+ if opts[:response_format] == :id_array
155
+ id_array = []
156
+ solr_result.hits.each do |hit|
157
+ id_array << hit["id"]
158
+ end
159
+ return id_array
160
+ else
161
+ return ActiveFedora::SolrService.reify_solr_results(solr_result)
162
+ end
137
163
  end
138
- return results
139
164
  end
140
165
  def #{name}_ids
141
- escaped_uri = self.internal_uri.gsub(/(:)/, '\\:')
142
- SolrService.instance.conn.query("#{predicate}_field:\#{escaped_uri}")
166
+ #{name}(:response_format => :id_array)
143
167
  end
144
168
  END
145
169
  end
146
170
 
147
171
  def create_outbound_relationship_finders(name, predicate, opts = {})
148
172
  class_eval <<-END
149
- def #{name}
150
- results = []
151
- outbound_relationships[#{predicate.inspect}].each do |rel|
152
- uri_as_pid = rel.gsub("info:fedora/", "")
153
- results << Fedora::Repository.instance.find_model(uri_as_pid, ActiveFedora::Base)
173
+ def #{name}(opts={})
174
+ id_array = []
175
+ if !outbound_relationships[#{predicate.inspect}].nil?
176
+ outbound_relationships[#{predicate.inspect}].each do |rel|
177
+ id_array << rel.gsub("info:fedora/", "")
178
+ end
179
+ end
180
+ if opts[:response_format] == :id_array
181
+ return id_array
182
+ else
183
+ query = ActiveFedora::SolrService.construct_query_for_pids(id_array)
184
+ solr_result = SolrService.instance.conn.query(query)
185
+ if opts[:response_format] == :solr
186
+ return solr_result
187
+ else
188
+ return ActiveFedora::SolrService.reify_solr_results(solr_result)
189
+ end
154
190
  end
155
- return results
156
191
  end
157
192
  def #{name}_ids
158
- results = []
159
- outbound_relationships[#{predicate.inspect}].each do |rel|
160
- results << rel
161
- end
162
- end
193
+ #{name}(:response_format => :id_array)
194
+ end
163
195
  END
164
196
  end
165
197
 
@@ -15,6 +15,34 @@ module ActiveFedora
15
15
  raise SolrNotInitialized unless Thread.current[:solr_service]
16
16
  Thread.current[:solr_service]
17
17
  end
18
+ def self.reify_solr_results(solr_result)
19
+ unless solr_result.is_a?(Solr::Response::Standard)
20
+ raise ArgumentError.new("Only solr responses (Solr::Response::Standard) are allowed. You provided a #{solr_result.class}")
21
+ end
22
+ results = []
23
+ solr_result.hits.each do |hit|
24
+ model_value = hit["active_fedora_model_field"].first
25
+ if model_value.include?("::")
26
+ classname = eval(model_value)
27
+ else
28
+ classname = Kernel.const_get(model_value)
29
+ end
30
+ results << Fedora::Repository.instance.find_model(hit["id"], classname)
31
+ end
32
+ return results
33
+ end
34
+ def self.construct_query_for_pids(pid_array)
35
+ query = ""
36
+ pid_array.each_index do |i|
37
+ query << "#{SOLR_DOCUMENT_ID}:#{escape_uri_for_query(pid_array[i])}"
38
+ query << " OR " if i != pid_array.count-1
39
+ end
40
+ query = "id:NEVER_USE_THIS_ID" if query.empty? || query == "id:"
41
+ return query
42
+ end
43
+ def self.escape_uri_for_query(uri)
44
+ return uri.gsub(/(:)/, '\\:')
45
+ end
18
46
  end
19
47
  class SolrNotInitialized < StandardError;end
20
48
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-fedora
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - MediaShelf Inc.
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-26 00:00:00 -06:00
12
+ date: 2009-07-10 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 1.0.0
23
+ version: 1.0.3
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: solr-ruby
@@ -40,7 +40,7 @@ dependencies:
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
- version: 1.2.3
43
+ version: 1.4.1
44
44
  version:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: rspec
@@ -105,7 +105,7 @@ files:
105
105
  - lib/active_fedora/solr_service.rb
106
106
  - solr/config/schema.xml
107
107
  has_rdoc: true
108
- homepage: FIX (url)
108
+ homepage: "Project Homepage: <http://yourmediashelf.com/activefedora>"
109
109
  post_install_message: PostInstall.txt
110
110
  rdoc_options:
111
111
  - --main
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  version:
127
127
  requirements: []
128
128
 
129
- rubyforge_project: active-fedora
129
+ rubyforge_project: rubyfedora
130
130
  rubygems_version: 1.3.1
131
131
  signing_key:
132
132
  specification_version: 2