ruby-fedora 0.9.0 → 1.0.0

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/History.txt CHANGED
@@ -1,11 +1,4 @@
1
- == 0.0.1 2008-03-31
1
+ == 0.0.1 2009-02-04
2
2
 
3
- * very alpha enhancement:
3
+ * 1 major enhancement:
4
4
  * Initial release
5
-
6
- == 0.1.1 2008-04-16
7
- * Remove the gem dependency on active_resource
8
-
9
- == 0.1.2 2008-04-30
10
- * Rename FedoraRepository.fetch_conent to FedoraRepository.fetch_content
11
- * Support custom mime-type for Datastream with parameter :mimeType
data/Manifest.txt CHANGED
@@ -3,23 +3,9 @@ COPYING.txt
3
3
  History.txt
4
4
  License.txt
5
5
  Manifest.txt
6
+ PostInstall.txt
7
+ README.rdoc
6
8
  README.txt
7
- Rakefile
8
- config/hoe.rb
9
- config/requirements.rb
10
- lib/active_fedora.rb
11
- lib/active_fedora/base.rb
12
- lib/active_fedora/content_model.rb
13
- lib/active_fedora/datastream.rb
14
- lib/active_fedora/fedora_object.rb
15
- lib/active_fedora/metadata_datastream.rb
16
- lib/active_fedora/model.rb
17
- lib/active_fedora/property.rb
18
- lib/active_fedora/qualified_dublin_core_datastream.rb
19
- lib/active_fedora/relationship.rb
20
- lib/active_fedora/rels_ext_datastream.rb
21
- lib/active_fedora/semantic_node.rb
22
- lib/active_fedora/solr_service.rb
23
9
  lib/fedora/base.rb
24
10
  lib/fedora/connection.rb
25
11
  lib/fedora/datastream.rb
@@ -27,7 +13,7 @@ lib/fedora/fedora_object.rb
27
13
  lib/fedora/formats.rb
28
14
  lib/fedora/generic_search.rb
29
15
  lib/fedora/repository.rb
16
+ lib/fedora/repository.rb.orig
30
17
  lib/ruby-fedora.rb
31
18
  lib/util/class_level_inheritable_attributes.rb
32
- setup.rb
33
- solr/config/schema.xml
19
+ tasks/rspec.rake
data/PostInstall.txt ADDED
@@ -0,0 +1,7 @@
1
+
2
+ For more information on rfed-regem, see http://rfed-regem.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
data/README.rdoc ADDED
@@ -0,0 +1,48 @@
1
+ = rfed-regem
2
+
3
+ * FIX (url)
4
+
5
+ == DESCRIPTION:
6
+
7
+ FIX (describe your package)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * FIX (list of features or problems)
12
+
13
+ == SYNOPSIS:
14
+
15
+ FIX (code sample of usage)
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * FIX (list of requirements)
20
+
21
+ == INSTALL:
22
+
23
+ * FIX (sudo gem install, anything else)
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2009 FIXME full name
30
+
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:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/lib/fedora/base.rb CHANGED
@@ -2,7 +2,8 @@ require 'xmlsimple'
2
2
 
3
3
  class Hash
4
4
  # {:q => 'test', :num => 5}.to_query # => 'q=test&num=5'
5
- def to_query
5
+ # let's avoid stomping on rails' version eh?
6
+ def to_fedora_query
6
7
  self.collect { |key, value| "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}" }.sort * '&'
7
8
  end
8
9
 
@@ -1,4 +1,5 @@
1
1
  require 'fedora/base'
2
+ require 'fedora/repository'
2
3
 
3
4
  class Fedora::Datastream < Fedora::BaseObject
4
5
  def initialize(attrs = nil)
@@ -94,7 +94,7 @@ module Fedora
94
94
  params[:sessionToken] = options[:sessionToken] if options[:sessionToken]
95
95
  includes = fields.inject("") { |s, f| s += "&#{f}=true"; s }
96
96
 
97
- convert_xml(connection.get("#{fedora_url.path}/objects?#{params.to_query}#{includes}"))
97
+ convert_xml(connection.get("#{fedora_url.path}/objects?#{params.to_fedora_query}#{includes}"))
98
98
  end
99
99
  def find_model(pid, klazz)
100
100
  obj = self.find_objects("pid=#{pid}").first
@@ -121,7 +121,7 @@ module Fedora
121
121
  case object
122
122
  when Fedora::FedoraObject
123
123
  pid = (object.pid ? object : 'new')
124
- response = connection.post("#{url_for(pid)}?" + object.attributes.to_query, object.blob)
124
+ response = connection.post("#{url_for(pid)}?" + object.attributes.to_fedora_query, object.blob)
125
125
  if response.code == '201'
126
126
  object.pid = extract_pid(response)
127
127
  object.new_object = false
@@ -133,7 +133,7 @@ module Fedora
133
133
  raise ArgumentError, "Missing dsID attribute" if object.dsid.nil?
134
134
  extra_headers = {}
135
135
  extra_headers['Content-Type'] = object.attributes[:mimeType] if object.attributes[:mimeType]
136
- response = connection.post("#{url_for(object)}?" + object.attributes.to_query,
136
+ response = connection.post("#{url_for(object)}?" + object.attributes.to_fedora_query,
137
137
  object.blob, extra_headers)
138
138
  if response.code == '201'
139
139
  object.new_object = false
@@ -155,11 +155,11 @@ module Fedora
155
155
  raise ArgumentError, "Missing pid attribute" if object.nil? || object.pid.nil?
156
156
  case object
157
157
  when Fedora::FedoraObject
158
- response = connection.put("#{url_for(object)}?" + object.attributes.to_query)
158
+ response = connection.put("#{url_for(object)}?" + object.attributes.to_fedora_query)
159
159
  response.code == '307'
160
160
  when Fedora::Datastream
161
161
  raise ArgumentError, "Missing dsID attribute" if object.dsid.nil?
162
- response = connection.put("#{url_for(object)}?" + object.attributes.to_query, object.blob)
162
+ response = connection.put("#{url_for(object)}?" + object.attributes.to_fedora_query, object.blob)
163
163
  response.code == '201'
164
164
  else
165
165
  raise ArgumentError, "Unknown object type"
@@ -197,7 +197,7 @@ module Fedora
197
197
  end
198
198
 
199
199
  extra_params.delete(:format) if method == :export
200
- connection.raw_get("#{url_for(object)}#{path}?#{extra_params.to_query}").body
200
+ connection.raw_get("#{url_for(object)}#{path}?#{extra_params.to_fedora_query}").body
201
201
  end
202
202
 
203
203
  def describe_repository
@@ -0,0 +1,248 @@
1
+ require 'facets/hash/symbolize_keys'
2
+
3
+ require 'fedora/base'
4
+ require 'fedora/connection'
5
+ require 'fedora/formats'
6
+ require 'fedora/fedora_object'
7
+ require 'fedora/datastream'
8
+
9
+ module Fedora
10
+ NAMESPACE = "fedora:info/"
11
+ ALL_FIELDS = [
12
+ :pid, :label, :fType, :cModel, :state, :ownerId, :cDate, :mDate, :dcmDate,
13
+ :bMech, :title, :creator, :subject, :description, :contributor,
14
+ :date, :type, :format, :identifier, :source, :language, :relation, :coverage, :rights
15
+ ]
16
+
17
+ class Repository
18
+
19
+ attr_accessor :repository_name, :base_url, :fedora_version, :pid_namespace, :pid_delimiter
20
+
21
+ def self.flush
22
+ Thread.current[:repo]=nil
23
+ end
24
+ def self.register(url, surrogate=nil)
25
+ repo = Fedora::Repository.new(url, surrogate)
26
+ repo = Thread.current[:repo]
27
+ attributes = repo.describe_repository
28
+ repo.repository_name = attributes["repositoryName"].first
29
+ repo.base_url = attributes["repositoryBaseURL"].first
30
+ repo.fedora_version = attributes["repositoryVersion"].first
31
+ repo.pid_namespace = attributes["repositoryPID"].first["PID-namespaceIdentifier"].first
32
+ repo.pid_delimiter = attributes["repositoryPID"].first["PID-delimiter"].first
33
+ Thread.current[:repo]=repo
34
+ repo
35
+ end
36
+ def self.instance
37
+ raise "did you register a repo?" unless Thread.current[:repo]
38
+ Thread.current[:repo]
39
+ end
40
+ class StringResponse < String
41
+ attr_reader :content_type
42
+
43
+ def initialize(s, content_type)
44
+ super(s)
45
+ @content_type = content_type
46
+ end
47
+ end
48
+
49
+ attr_accessor :fedora_url
50
+
51
+ def initialize(fedora_url, surrogate=nil)
52
+ @fedora_url = fedora_url.is_a?(URI) ? fedora_url : URI.parse(fedora_url)
53
+ @surrogate = surrogate
54
+ @connection = nil
55
+ end
56
+
57
+ # Fetch the raw content of either a fedora object or datastream
58
+ def fetch_content(object_uri)
59
+ response = connection.raw_get("#{url_for(object_uri)}?format=xml")
60
+ StringResponse.new(response.body, response.content_type)
61
+ end
62
+
63
+
64
+
65
+ # Find fedora objects with http://www.fedora.info/wiki/index.php/API-A-Lite_findObjects
66
+ #
67
+ # == Parameters
68
+ # query<String>:: the query string to be sent to Fedora.
69
+ # options<Hash>:: see below
70
+ #
71
+ # == Options<Hash> keys
72
+ # limit<String|Number>:: set the maxResults parameter in fedora
73
+ # select<Symbol|Array>:: the fields to returned. To include all fields, pass :all as the value.
74
+ # The field "pid" is always included.
75
+ #
76
+ # == Examples
77
+ # find_objects("label=Image1"
78
+ # find_objects("pid~demo:*", "label=test")
79
+ # find_objects("label=Image1", :include => :all)
80
+ # find_objects("label=Image1", :include => [:label])
81
+ #-
82
+ def find_objects(*args)
83
+ raise ArgumentError, "Missing query string" unless args.length >= 1
84
+ options = args.last.is_a?(Hash) ? args.pop : {}
85
+
86
+ fields = options[:select]
87
+ fields = (fields.nil? || (fields == :all)) ? ALL_FIELDS : ([:pid] + ([fields].flatten! - [:pid]))
88
+
89
+ query = args.join(' ')
90
+ params = { :format => 'xml', :query => query }
91
+ params[:maxResults] = options[:limit] if options[:limit]
92
+ params[:sessionToken] = options[:sessionToken] if options[:sessionToken]
93
+ includes = fields.inject("") { |s, f| s += "&#{f}=true"; s }
94
+
95
+ convert_xml(connection.get("#{fedora_url.path}/objects?#{params.to_fedora_query}#{includes}"))
96
+ end
97
+ def find_model(pid, klazz)
98
+ obj = self.find_objects("pid=#{pid}").first
99
+ doc = REXML::Document.new(obj.object_xml, :ignore_whitespace_nodes=>:all)
100
+ klazz.deserialize(doc)
101
+ end
102
+
103
+ # Create the given object if it's new (not obtained from a find method). Otherwise update the object.
104
+ #
105
+ # == Return
106
+ # boolean:: whether the operation is successful
107
+ #-
108
+ def save(object)
109
+ object.new_object? ? create(object) : update(object)
110
+ end
111
+
112
+ def nextid
113
+ d = REXML::Document.new(connection.post(fedora_url.path+"/management/getNextPID?xml=true").body)
114
+ d.elements['//pid'].text
115
+ end
116
+
117
+
118
+ def create(object)
119
+ case object
120
+ when Fedora::FedoraObject
121
+ pid = (object.pid ? object : 'new')
122
+ response = connection.post("#{url_for(pid)}?" + object.attributes.to_fedora_query, object.blob)
123
+ if response.code == '201'
124
+ object.pid = extract_pid(response)
125
+ object.new_object = false
126
+ true
127
+ else
128
+ false
129
+ end
130
+ when Fedora::Datastream
131
+ raise ArgumentError, "Missing dsID attribute" if object.dsid.nil?
132
+ extra_headers = {}
133
+ extra_headers['Content-Type'] = object.attributes[:mimeType] if object.attributes[:mimeType]
134
+ response = connection.post("#{url_for(object)}?" + object.attributes.to_fedora_query,
135
+ object.blob, extra_headers)
136
+ if response.code == '201'
137
+ object.new_object = false
138
+ true
139
+ else
140
+ false
141
+ end
142
+ else
143
+ raise ArgumentError, "Unknown object type"
144
+ end
145
+
146
+ end
147
+
148
+ # Update the given object
149
+ # == Return
150
+ # boolean:: whether the operation is successful
151
+ #-
152
+ def update(object)
153
+ raise ArgumentError, "Missing pid attribute" if object.nil? || object.pid.nil?
154
+ case object
155
+ when Fedora::FedoraObject
156
+ response = connection.put("#{url_for(object)}?" + object.attributes.to_fedora_query)
157
+ response.code == '307'
158
+ when Fedora::Datastream
159
+ raise ArgumentError, "Missing dsID attribute" if object.dsid.nil?
160
+ response = connection.put("#{url_for(object)}?" + object.attributes.to_fedora_query, object.blob)
161
+ response.code == '201'
162
+ else
163
+ raise ArgumentError, "Unknown object type"
164
+ end
165
+ end
166
+
167
+ # Delete the given pid
168
+ # == Parameters
169
+ # object<Object|String>:: The object to delete.
170
+ # This can be a uri String ("demo:1", "fedora:info/demo:1") or any object that responds uri method.
171
+ #
172
+ # == Return
173
+ # boolean:: whether the operation is successful
174
+ #-
175
+ def delete(object)
176
+ raise ArgumentError, "Object must not be nil" if object.nil?
177
+ response = connection.delete("#{url_for(object)}")
178
+ response.code == '200' or response.code == '204' # Temporary hack around error in Fedora 3.0 Final's REST API
179
+ end
180
+
181
+ # Fetch the given object using custom method. This is used to fetch other aspects of a fedora object,
182
+ # such as profile, versions, etc...
183
+ # == Parameters
184
+ # object<String|Object>:: a fedora uri, pid, FedoraObject instance
185
+ # method<Symbol>:: the method to fetch such as :export, :history, :versions, etc
186
+ # extra_params<Hash>:: any other extra parameters to pass to fedora
187
+ #
188
+ # == Returns
189
+ # This method returns raw xml response from the server
190
+ #-
191
+ def fetch_custom(object, method, extra_params = { :format => 'xml' })
192
+ path = case method
193
+ when :profile then ""
194
+ else "/#{method}"
195
+ end
196
+
197
+ extra_params.delete(:format) if method == :export
198
+ connection.raw_get("#{url_for(object)}#{path}?#{extra_params.to_fedora_query}").body
199
+ end
200
+
201
+ def describe_repository
202
+ result_body = connection.raw_get("#{fedora_url.path}/describe?xml=true").body
203
+ XmlSimple.xml_in(result_body)
204
+ end
205
+
206
+ private
207
+ def convert_xml(response)
208
+ results = FedoraObjects.new
209
+ return results unless response && response['resultList']
210
+
211
+ results.session_token = response['listSession']['token'] if response['listSession']
212
+ objectFields = response['resultList']['objectFields']
213
+ case objectFields
214
+ when Array
215
+ objectFields.each { |attrs| results << FedoraObject.new(attrs.symbolize_keys!) }
216
+ when Hash
217
+ results << FedoraObject.new(objectFields.symbolize_keys!)
218
+ end
219
+ results.each {|result| result.new_object = false}
220
+ results
221
+ end
222
+
223
+ def url_for(object)
224
+ uri = object.respond_to?(:uri) ? object.uri : object.to_s
225
+ uri = (uri[0..NAMESPACE.length-1] == NAMESPACE ? uri[NAMESPACE.length..-1] : uri) # strip of fedora:info namespace
226
+ "#{fedora_url.path}/objects/#{uri}"
227
+ end
228
+
229
+ # Low level access to the remote fedora server
230
+ # The +refresh+ parameter toggles whether or not the connection is refreshed at every request
231
+ # or not (defaults to +false+).
232
+ def connection(refresh = false)
233
+ if refresh || @connection.nil?
234
+ @connection = Fedora::Connection.new(@fedora_url, Fedora::XmlFormat, @surrogate)
235
+ end
236
+ @connection
237
+ end
238
+
239
+ def extract_pid(response)
240
+ CGI.unescape(response['Location'].split('/').last)
241
+ end
242
+ end
243
+ end
244
+
245
+ class FedoraObjects < Array
246
+ attr_accessor :session_token
247
+ end
248
+
data/lib/ruby-fedora.rb CHANGED
@@ -1,18 +1,8 @@
1
+ require 'rubygems'
2
+ gem 'xml-simple'
1
3
  $LOAD_PATH.unshift File.dirname(__FILE__) unless
2
4
  $LOAD_PATH.include?(File.dirname(__FILE__)) || $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
3
5
 
4
6
  module Fedora #:nodoc:
5
- module VERSION #:nodoc:
6
- unless defined? MAJOR
7
- MAJOR = 0
8
- MINOR = 9
9
- TINY = 0
10
-
11
- STRING = [MAJOR, MINOR, TINY].join('.')
12
- end
13
- end
7
+ VERSION = '1.0.0'
14
8
  end
15
-
16
- module Fedora; end
17
-
18
- require 'fedora/repository'