active-fedora 1.0.2 → 1.0.4

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.
@@ -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