ruby-fedora 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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'