active-fedora 3.0.7 → 3.1.0.pre1

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.
Files changed (67) hide show
  1. data/.rvmrc +1 -1
  2. data/Gemfile.lock +39 -10
  3. data/History.txt +0 -4
  4. data/active-fedora.gemspec +4 -3
  5. data/lib/active_fedora.rb +9 -9
  6. data/lib/active_fedora/base.rb +92 -163
  7. data/lib/active_fedora/datastream.rb +59 -60
  8. data/lib/active_fedora/datastream_hash.rb +18 -0
  9. data/lib/active_fedora/metadata_datastream.rb +3 -2
  10. data/lib/active_fedora/metadata_datastream_helper.rb +3 -15
  11. data/lib/active_fedora/model.rb +3 -3
  12. data/lib/active_fedora/nokogiri_datastream.rb +305 -302
  13. data/lib/active_fedora/qualified_dublin_core_datastream.rb +24 -19
  14. data/lib/active_fedora/rels_ext_datastream.rb +39 -37
  15. data/lib/active_fedora/rubydora_connection.rb +40 -0
  16. data/lib/active_fedora/semantic_node.rb +1 -1
  17. data/lib/active_fedora/solr_service.rb +1 -1
  18. data/lib/active_fedora/version.rb +1 -1
  19. data/lib/ruby-fedora.rb +0 -8
  20. data/lib/tasks/active_fedora.rake +14 -9
  21. data/lib/tasks/active_fedora_dev.rake +23 -40
  22. data/spec/integration/base_loader_spec.rb +4 -21
  23. data/spec/integration/base_spec.rb +300 -310
  24. data/spec/integration/bug_spec.rb +9 -10
  25. data/spec/integration/datastream_spec.rb +12 -12
  26. data/spec/integration/metadata_datastream_helper_spec.rb +7 -10
  27. data/spec/integration/model_spec.rb +3 -2
  28. data/spec/integration/rels_ext_datastream_spec.rb +9 -15
  29. data/spec/spec_helper.rb +2 -29
  30. data/spec/unit/active_fedora_spec.rb +5 -5
  31. data/spec/unit/base_cma_spec.rb +0 -7
  32. data/spec/unit/base_datastream_management_spec.rb +8 -67
  33. data/spec/unit/base_delegate_spec.rb +26 -9
  34. data/spec/unit/base_extra_spec.rb +5 -3
  35. data/spec/unit/base_file_management_spec.rb +10 -17
  36. data/spec/unit/base_named_datastream_spec.rb +76 -199
  37. data/spec/unit/base_spec.rb +152 -69
  38. data/spec/unit/content_model_spec.rb +1 -1
  39. data/spec/unit/datastream_concurrency_spec.rb +5 -4
  40. data/spec/unit/datastream_spec.rb +28 -48
  41. data/spec/unit/has_many_collection_spec.rb +2 -0
  42. data/spec/unit/inheritance_spec.rb +6 -6
  43. data/spec/unit/metadata_datastream_spec.rb +12 -28
  44. data/spec/unit/model_spec.rb +10 -10
  45. data/spec/unit/nokogiri_datastream_spec.rb +31 -33
  46. data/spec/unit/qualified_dublin_core_datastream_spec.rb +15 -15
  47. data/spec/unit/rels_ext_datastream_spec.rb +35 -29
  48. data/spec/unit/rubydora_connection_spec.rb +26 -0
  49. data/spec/unit/semantic_node_spec.rb +12 -17
  50. data/spec/unit/solr_config_options_spec.rb +13 -14
  51. data/spec/unit/solr_service_spec.rb +14 -17
  52. metadata +59 -55
  53. data/lib/fedora/base.rb +0 -38
  54. data/lib/fedora/connection.rb +0 -218
  55. data/lib/fedora/datastream.rb +0 -67
  56. data/lib/fedora/fedora_object.rb +0 -161
  57. data/lib/fedora/formats.rb +0 -30
  58. data/lib/fedora/generic_search.rb +0 -71
  59. data/lib/fedora/repository.rb +0 -298
  60. data/spec/integration/datastreams_crud_spec.rb +0 -208
  61. data/spec/integration/fedora_object_spec.rb +0 -77
  62. data/spec/integration/repository_spec.rb +0 -301
  63. data/spec/integration/rf_fedora_object_spec.rb +0 -95
  64. data/spec/unit/connection_spec.rb +0 -25
  65. data/spec/unit/fedora_object_spec.rb +0 -74
  66. data/spec/unit/repository_spec.rb +0 -143
  67. data/spec/unit/rf_datastream_spec.rb +0 -63
@@ -1,38 +0,0 @@
1
- require 'xmlsimple'
2
-
3
- class Hash
4
-
5
- # Produces a valid Fedora query based on the current hash
6
- # @example
7
- # {:q => 'test', :num => 5}.to_fedora_query # => 'q=test&num=5'
8
- def to_fedora_query
9
- self.collect { |key, value| "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}" }.sort * '&'
10
- end
11
-
12
- def self.from_xml(xml)
13
- XmlSimple.xml_in(xml, 'ForceArray' => false)
14
- end
15
- end
16
-
17
- class Fedora::BaseObject
18
- attr_accessor :attributes, :blob, :uri
19
- attr_reader :errors, :uri
20
- attr_writer :new_object
21
-
22
- # @param [Hash] attrs object attributes
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
@@ -1,218 +0,0 @@
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} #{@message.to_s}"
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
- message = "Error from Fedora: #{response.body}"
159
- case response.code.to_i
160
- when 301,302
161
- raise(Redirection.new(response))
162
- when 200...400
163
- response
164
- when 400
165
- raise(BadRequest.new(response, message))
166
- when 401
167
- raise(UnauthorizedAccess.new(response, message))
168
- when 403
169
- raise(ForbiddenAccess.new(response, message))
170
- when 404
171
- raise(ResourceNotFound.new(response, message))
172
- when 405
173
- raise(MethodNotAllowed.new(response, message))
174
- when 409
175
- raise(ResourceConflict.new(response, message))
176
- when 422
177
- raise(ResourceInvalid.new(response, message))
178
- when 423...500
179
- raise(ClientError.new(response, message))
180
- when 500...600
181
- raise(ServerError.new(response, message))
182
- else
183
- raise(ConnectionError.new(response, "Unknown response code: #{response.code}"))
184
- end
185
- end
186
-
187
- # Creates new Net::HTTP instance for communication with
188
- # remote service and resources.
189
- def http
190
- http = Net::HTTP.new(@site.host, @site.port)
191
- if(@site.is_a?(URI::HTTPS))
192
- http.use_ssl = true
193
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
194
-
195
- if (defined?(SSL_CLIENT_CERT_FILE) && !SSL_CLIENT_CERT_FILE.nil? && defined?(SSL_CLIENT_KEY_FILE) && !SSL_CLIENT_KEY_FILE.nil? && defined?(SSL_CLIENT_KEY_PASS) && !SSL_CLIENT_KEY_PASS.nil?)
196
- http.cert = OpenSSL::X509::Certificate.new( File.read(SSL_CLIENT_CERT_FILE) )
197
- http.key = OpenSSL::PKey::RSA.new( File.read(SSL_CLIENT_KEY_FILE), SSL_CLIENT_KEY_PASS )
198
- end
199
- end
200
- http
201
- end
202
-
203
- def default_header
204
- @default_header ||= { 'Content-Type' => format.mime_type }
205
- end
206
-
207
- # Builds headers for request to remote service.
208
- def build_request_headers(headers)
209
- headers.merge!({"From"=>surrogate}) if @surrogate
210
- authorization_header.update(default_header).update(headers)
211
- end
212
-
213
- # Sets authorization header; authentication information is pulled from credentials provided with site URI.
214
- def authorization_header
215
- (@site.user || @site.password ? { 'Authorization' => 'Basic ' + ["#{@site.user}:#{ @site.password}"].pack('m').delete("\r\n") } : {})
216
- end
217
- end
218
- end
@@ -1,67 +0,0 @@
1
- require 'fedora/base'
2
- require 'fedora/repository'
3
-
4
- class Fedora::Datastream < Fedora::BaseObject
5
-
6
-
7
- def initialize(attrs = {})
8
- super
9
- if attrs
10
- if attrs[:mime_type]
11
- self.mime_type = attrs[:mime_type]
12
- elsif attrs[:mimeType]
13
- self.mime_type = attrs[:mimeType]
14
- elsif attrs["mimeType"]
15
- self.mime_type = attrs["mimeType"]
16
- elsif attrs["mime_type"]
17
- self.mime_type = attrs["mime_type"]
18
- end
19
- end
20
- self.control_group='M' if @attributes[:mimeType]
21
- end
22
-
23
- def pid
24
- attributes[:pid]
25
- end
26
-
27
- def control_group
28
- @attributes[:controlGroup]
29
- end
30
- def control_group=(cg)
31
- @attributes[:controlGroup]=cg
32
- end
33
-
34
- def dsid
35
- if attributes.has_key?(:dsid)
36
- attributes[:dsid]
37
- else
38
- attributes[:dsID]
39
- end
40
- end
41
-
42
- def label
43
- @attributes[:dsLabel]
44
- end
45
-
46
- def label=(new_label)
47
- @attributes[:dsLabel] = new_label
48
- end
49
-
50
- def mime_type
51
- @mime_type
52
- end
53
-
54
- def mime_type=(new_mime_type)
55
- @mime_type = new_mime_type
56
- end
57
-
58
- # See http://www.fedora.info/definitions/identifiers/
59
- def uri
60
- "fedora:info/#{pid}/datastreams/#{dsid}"
61
- end
62
-
63
- # @return [String] url of the datastream in Fedora, without the repository userinfo
64
- def url
65
- return "#{Fedora::Repository.instance.base_url}/objects/#{pid}/datastreams/#{dsid}"
66
- end
67
- end
@@ -1,161 +0,0 @@
1
- require 'xmlsimple'
2
- require 'rexml/document'
3
- require 'fedora/base'
4
-
5
- class Fedora::FedoraObject < Fedora::BaseObject
6
- attr_accessor :target_repository
7
-
8
- # = Parameters
9
- # attrs<Hash>:: fedora object attributes (see below)
10
- #
11
- # == Attributes (attrs)
12
- # namespace<Symbol>::
13
- # pid<Symbol>::
14
- # state<Symbol>::
15
- # label<Symbol>::
16
- # contentModel<Symbol>::
17
- # objectXMLFormat<Symbol>::
18
- # ownerID<Symbol>::
19
- #-
20
- def initialize(attrs = nil)
21
- super
22
- # TODO: check for required attributes
23
- end
24
-
25
- ####
26
- # Attribute Accessors
27
- ####
28
-
29
-
30
- def load_attributes_from_fedora
31
- #self.attributes.merge!(profile)
32
- attributes.merge!(profile)
33
- end
34
-
35
- # Reads all object properties from the object's FOXML into a hash. Provides slightly more info than .profile, including the object state.
36
- def properties_from_fedora
37
- #object_rexml = REXML::Document.new(object_xml)
38
- #properties = {
39
- # :pid => object_rexml.root.attributes["PID"],
40
- # :state => object_rexml.root.elements["//foxml:property[@NAME='info:fedora/fedora-system:def/model#state']"].attributes["VALUE"],
41
- # :create_date => object_rexml.root.elements["//foxml:property[@NAME='info:fedora/fedora-system:def/model#createdDate']"].attributes["VALUE"],
42
- # :modified_date => object_rexml.root.elements["//foxml:property[@NAME='info:fedora/fedora-system:def/view#lastModifiedDate']"].attributes["VALUE"],
43
- # :owner_id => object_rexml.root.elements['//foxml:property[@NAME="info:fedora/fedora-system:def/model#ownerId"]'].attributes['VALUE']
44
- #}
45
- #label_element = object_rexml.root.elements["//foxml:property[@NAME='info:fedora/fedora-system:def/model#label']"]
46
- #if profile_hash[:label]
47
- # properties.merge!({:label => label_element.attributes["VALUE"]})
48
- #end
49
- return profile
50
- end
51
-
52
- def create_date
53
- if attributes[:create_date]
54
- return attributes[:create_date]
55
- elsif !new_object?
56
- properties_from_fedora[:create_date]
57
- else
58
- return nil
59
- end
60
- end
61
-
62
- def modified_date
63
- if attributes[:modified_date]
64
- return attributes[:modified_date]
65
- elsif !new_object?
66
- properties_from_fedora[:modified_date]
67
- else
68
- return nil
69
- end
70
- end
71
-
72
-
73
- def pid
74
- self.attributes[:pid]
75
- end
76
-
77
- def pid=(new_pid)
78
- self.attributes.merge!({:pid => new_pid})
79
- end
80
-
81
- def state
82
- if attributes[:state]
83
- return attributes[:state]
84
- elsif !new_object?
85
- properties_from_fedora[:state]
86
- else
87
- return nil
88
- end
89
- end
90
-
91
- def state=(new_state)
92
- if ["I", "A", "D"].include? new_state
93
- self.attributes[:state] = new_state
94
- else
95
- raise 'The object state of "' + new_state + '" is invalid. The allowed values for state are: A (active), D (deleted), and I (inactive).'
96
- end
97
- end
98
-
99
- def label
100
- if attributes[:label]
101
- return attributes[:label]
102
- elsif !new_object?
103
- properties_from_fedora[:label]
104
- else
105
- return nil
106
- end
107
- end
108
-
109
- def label=(new_label)
110
- self.attributes[:label] = new_label
111
- end
112
-
113
- # Get the object and read its @ownerId from the profile
114
- def owner_id
115
- if attributes[:owner_id]
116
- return attributes[:owner_id]
117
- elsif !new_object?
118
- properties_from_fedora[:owner_id]
119
- else
120
- return nil
121
- end
122
- end
123
-
124
- def owner_id=(new_owner_id)
125
- self.attributes.merge!({:ownerId => new_owner_id})
126
- end
127
-
128
- def profile
129
- # Use xmlsimple to slurp the attributes
130
- retrieved_profile = XmlSimple.xml_in(Fedora::Repository.instance.fetch_custom(self.pid, :profile))
131
- label = retrieved_profile["objLabel"].first unless retrieved_profile["objLabel"].first == {}
132
- profile_hash = Hash[:pid => retrieved_profile["pid"],
133
- :owner_id => retrieved_profile["objOwnerId"].first,
134
- :label => label,
135
- :create_date => retrieved_profile["objCreateDate"].first,
136
- :modified_date => retrieved_profile["objLastModDate"].first,
137
- :methods_list_url => retrieved_profile["objDissIndexViewURL"].first,
138
- :datastreams_list_url => retrieved_profile["objItemIndexViewURL"].first,
139
- :state => retrieved_profile["objState"].first
140
- ]
141
- end
142
-
143
- def object_xml
144
- Fedora::Repository.instance.fetch_custom(pid, :objectXML)
145
- end
146
-
147
- def self.object_xml(pid=pid)
148
- Fedora::Repository.instance.fetch_custom(pid, :objectXML)
149
- end
150
-
151
- # See http://www.fedora.info/definitions/identifiers
152
- def uri
153
- "fedora:info/#{pid}"
154
- end
155
-
156
- # @return [String] url of the datastream in Fedora, without the repository userinfo
157
- def url
158
- repo_url = Fedora::Repository.instance.fedora_url
159
- return "#{repo_url.scheme}://#{repo_url.host}:#{repo_url.port}#{repo_url.path}/objects/#{pid}"
160
- end
161
- end