Class: Valkyrie::Storage::Fedora
- Inherits:
-
Object
- Object
- Valkyrie::Storage::Fedora
- Defined in:
- lib/valkyrie/storage/fedora.rb
Overview
Implements the DataMapper Pattern to store binary data in fedora
Constant Summary collapse
- PROTOCOL =
'fedora://'
- SLASH =
'/'
Instance Attribute Summary collapse
-
#base_path ⇒ Object
readonly
Returns the value of attribute base_path.
-
#connection ⇒ Object
readonly
Returns the value of attribute connection.
-
#fedora_version ⇒ Object
readonly
Returns the value of attribute fedora_version.
-
#pairtree_count ⇒ Object
readonly
Returns the value of attribute pairtree_count.
-
#pairtree_length ⇒ Object
readonly
Returns the value of attribute pairtree_length.
-
#uri_transformer ⇒ Object
readonly
Returns the value of attribute uri_transformer.
Instance Method Summary collapse
- #current_version_id(id:) ⇒ Object
-
#delete(id:) ⇒ Object
Delete the file in Fedora associated with the given identifier.
-
#fedora_identifier(id:) ⇒ RDF::URI
Translate the Valkrie ID into a URL for the fedora file.
-
#find_by(id:) ⇒ Valkyrie::StorageAdapter::StreamFile
Return the file associated with the given identifier.
- #find_versions(id:) ⇒ Array<Valkyrie::StorageAdapter::StreamFile>
-
#handles?(id:) ⇒ Boolean
True if this adapter can handle this type of identifer.
-
#initialize(connection:, base_path: "/", fedora_version: Valkyrie::Persistence::Fedora::DEFAULT_FEDORA_VERSION, fedora_pairtree_count: 0, fedora_pairtree_length: 0) ⇒ Fedora
constructor
A new instance of Fedora.
-
#latest_version(identifier) ⇒ Object
Returns a new version identifier to mint.
-
#mint_version(identifier, version_name = "version1") ⇒ Valkyrie::ID
Versions are created AFTER content is uploaded, except for Fedora 6 which auto versions.
- #perform_find(id:, version_id: nil) ⇒ Object
-
#protocol ⇒ String
Identifier prefix.
-
#supports?(feature) ⇒ Boolean
True if the adapter supports the given feature.
- #upload(file:, original_filename:, resource:, content_type: "application/octet-stream", resource_uri_transformer: uri_transformer, **_extra_arguments) ⇒ Valkyrie::StorageAdapter::StreamFile
- #upload_file(fedora_uri:, io:, content_type: "application/octet-stream", original_filename: "default") ⇒ Object
- #upload_version(id:, file:) ⇒ Object
- #valkyrie_identifier(uri:) ⇒ Object
- #version_list(fedora_uri) ⇒ Object
Constructor Details
#initialize(connection:, base_path: "/", fedora_version: Valkyrie::Persistence::Fedora::DEFAULT_FEDORA_VERSION, fedora_pairtree_count: 0, fedora_pairtree_length: 0) ⇒ Fedora
Returns a new instance of Fedora.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/valkyrie/storage/fedora.rb', line 12 def initialize(connection:, base_path: "/", fedora_version: Valkyrie::Persistence::Fedora::DEFAULT_FEDORA_VERSION, fedora_pairtree_count: 0, fedora_pairtree_length: 0) @connection = connection @base_path = base_path @fedora_version = fedora_version @pairtree_count = fedora_pairtree_count @pairtree_length = fedora_pairtree_length @uri_transformer = if fedora_version >= 6.5 && (pairtree_count * pairtree_length).positive? pairtree_resource_uri_transformer else default_resource_uri_transformer end end |
Instance Attribute Details
#base_path ⇒ Object (readonly)
Returns the value of attribute base_path.
5 6 7 |
# File 'lib/valkyrie/storage/fedora.rb', line 5 def base_path @base_path end |
#connection ⇒ Object (readonly)
Returns the value of attribute connection.
5 6 7 |
# File 'lib/valkyrie/storage/fedora.rb', line 5 def connection @connection end |
#fedora_version ⇒ Object (readonly)
Returns the value of attribute fedora_version.
5 6 7 |
# File 'lib/valkyrie/storage/fedora.rb', line 5 def fedora_version @fedora_version end |
#pairtree_count ⇒ Object (readonly)
Returns the value of attribute pairtree_count.
5 6 7 |
# File 'lib/valkyrie/storage/fedora.rb', line 5 def pairtree_count @pairtree_count end |
#pairtree_length ⇒ Object (readonly)
Returns the value of attribute pairtree_length.
5 6 7 |
# File 'lib/valkyrie/storage/fedora.rb', line 5 def pairtree_length @pairtree_length end |
#uri_transformer ⇒ Object (readonly)
Returns the value of attribute uri_transformer.
5 6 7 |
# File 'lib/valkyrie/storage/fedora.rb', line 5 def uri_transformer @uri_transformer end |
Instance Method Details
#current_version_id(id:) ⇒ Object
153 154 155 156 157 |
# File 'lib/valkyrie/storage/fedora.rb', line 153 def current_version_id(id:) version_list = version_list(fedora_identifier(id: id)) return nil if version_list.blank? valkyrie_identifier(uri: version_list.first["@id"]) end |
#delete(id:) ⇒ Object
Delete the file in Fedora associated with the given identifier.
105 106 107 |
# File 'lib/valkyrie/storage/fedora.rb', line 105 def delete(id:) connection.http.delete(fedora_identifier(id: id)) end |
#fedora_identifier(id:) ⇒ RDF::URI
Translate the Valkrie ID into a URL for the fedora file
208 209 210 211 |
# File 'lib/valkyrie/storage/fedora.rb', line 208 def fedora_identifier(id:) identifier = id.to_s.sub(protocol, "#{connection.http.scheme}://") RDF::URI(identifier) end |
#find_by(id:) ⇒ Valkyrie::StorageAdapter::StreamFile
Return the file associated with the given identifier
53 54 55 |
# File 'lib/valkyrie/storage/fedora.rb', line 53 def find_by(id:) perform_find(id: id) end |
#find_versions(id:) ⇒ Array<Valkyrie::StorageAdapter::StreamFile>
92 93 94 95 96 97 98 99 100 101 |
# File 'lib/valkyrie/storage/fedora.rb', line 92 def find_versions(id:) uri = fedora_identifier(id: id) version_list = version_list(uri) version_list.map do |version| id = valkyrie_identifier(uri: version["@id"]) perform_find(id: id, version_id: id) rescue Valkyrie::StorageAdapter::FileNotFound nil end.compact end |
#handles?(id:) ⇒ Boolean
Returns true if this adapter can handle this type of identifer.
29 30 31 |
# File 'lib/valkyrie/storage/fedora.rb', line 29 def handles?(id:) id.to_s.start_with?(protocol) end |
#latest_version(identifier) ⇒ Object
Returns a new version identifier to mint. Defaults to version1, but will increment to version2 etc if one found. Only for Fedora 4.
141 142 143 144 145 146 147 148 149 |
# File 'lib/valkyrie/storage/fedora.rb', line 141 def latest_version(identifier) # Only version 4 needs a version ID, 5/6 both mint using timestamps. return :not_applicable if fedora_version != 4 version_list = version_list(identifier) return "version1" if version_list.blank? last_version = version_list.first["@id"] last_version_number = last_version.split("/").last.gsub("version", "").to_i "version#{last_version_number + 1}" end |
#mint_version(identifier, version_name = "version1") ⇒ Valkyrie::ID
Versions are created AFTER content is uploaded, except for Fedora 6 which
auto versions.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/valkyrie/storage/fedora.rb', line 172 def mint_version(identifier, version_name = "version1") response = connection.http.post do |request| request.url "#{identifier}/fcr:versions" request.headers['Slug'] = version_name if fedora_version == 4 end # If there's a deletion marker, don't return anything. (Fedora 4) return nil if response.status == 410 # This is awful, but versioning is locked to per-second increments, # returns a 409 in Fedora 5 if there's a conflict. if response.status == 409 sleep(0.5) return mint_version(identifier, version_name) end raise "Version unable to be created" unless response.status == 201 valkyrie_identifier(uri: response.headers["location"].gsub("/fcr:metadata", "")) end |
#perform_find(id:, version_id: nil) ⇒ Object
159 160 161 162 163 164 165 166 |
# File 'lib/valkyrie/storage/fedora.rb', line 159 def perform_find(id:, version_id: nil) current_id = Valkyrie::ID.new(id.to_s.split("/fcr:versions").first) version_id ||= id if id != current_id # No version got passed and we're asking for a current_id, gotta get the # version ID return perform_find(id: current_id, version_id: current_version_id(id: id) || :empty) if version_id.nil? Valkyrie::StorageAdapter::StreamFile.new(id: current_id, io: response(id: id), version_id: version_id) end |
#protocol ⇒ String
Returns identifier prefix.
45 46 47 |
# File 'lib/valkyrie/storage/fedora.rb', line 45 def protocol PROTOCOL end |
#supports?(feature) ⇒ Boolean
Returns true if the adapter supports the given feature.
35 36 37 38 39 40 41 42 |
# File 'lib/valkyrie/storage/fedora.rb', line 35 def supports?(feature) return true if feature == :versions # Fedora 6 auto versions and you can't delete versions. return true if feature == :version_deletion && fedora_version < 6 # Fedora 6.5+ lists versions for deleted objects return true if feature == :list_deleted_versions && fedora_version >= 6.5 false end |
#upload(file:, original_filename:, resource:, content_type: "application/octet-stream", resource_uri_transformer: uri_transformer, **_extra_arguments) ⇒ Valkyrie::StorageAdapter::StreamFile
64 65 66 67 68 69 70 71 72 |
# File 'lib/valkyrie/storage/fedora.rb', line 64 def upload(file:, original_filename:, resource:, content_type: "application/octet-stream", # rubocop:disable Metrics/ParameterLists resource_uri_transformer: uri_transformer, **_extra_arguments) identifier = resource_uri_transformer.call(resource, base_url) + '/original' upload_file(fedora_uri: identifier, io: file, content_type: content_type, original_filename: original_filename) # Fedora 6 auto versions, so check to see if there's a version for this # initial upload. If not, then mint one (fedora 4/5) version_id = current_version_id(id: valkyrie_identifier(uri: identifier)) || mint_version(identifier, latest_version(identifier)) perform_find(id: Valkyrie::ID.new(identifier.to_s.sub(/^.+\/\//, protocol)), version_id: version_id) end |
#upload_file(fedora_uri:, io:, content_type: "application/octet-stream", original_filename: "default") ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/valkyrie/storage/fedora.rb', line 124 def upload_file(fedora_uri:, io:, content_type: "application/octet-stream", original_filename: "default") sha1 = fedora_version >= 5 ? "sha" : "sha1" connection.http.put do |request| request.url fedora_uri request.headers['Content-Type'] = content_type io_size = (io.length if io.respond_to?(:length)) || (io.size if io.respond_to?(:size)) request.headers['Content-Length'] = io_size.to_s if io_size request.headers['Content-Disposition'] = "attachment; filename=\"#{original_filename}\"" request.headers['digest'] = "#{sha1}=#{Digest::SHA1.file(io)}" if io.respond_to?(:to_str) request.headers['link'] = "<http://www.w3.org/ns/ldp#NonRDFSource>; rel=\"type\"" io = Faraday::UploadIO.new(io, content_type, original_filename) request.body = io end end |
#upload_version(id:, file:) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/valkyrie/storage/fedora.rb', line 77 def upload_version(id:, file:) uri = fedora_identifier(id: id) # Fedora 6 has auto versioning, so have to sleep if it's too soon after last # upload. if fedora_version >= 6 && current_version_id(id: id).to_s.split("/").last == Time.current.utc.strftime("%Y%m%d%H%M%S") sleep(0.5) return upload_version(id: id, file: file) end upload_file(fedora_uri: uri, io: file) version_id = mint_version(uri, latest_version(uri)) perform_find(id: Valkyrie::ID.new(uri.to_s.sub(/^.+\/\//, protocol)), version_id: version_id) end |
#valkyrie_identifier(uri:) ⇒ Object
213 214 215 216 |
# File 'lib/valkyrie/storage/fedora.rb', line 213 def valkyrie_identifier(uri:) id = uri.to_s.sub("http://", protocol) Valkyrie::ID.new(id) end |
#version_list(fedora_uri) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/valkyrie/storage/fedora.rb', line 109 def version_list(fedora_uri) version_list = connection.http.get do |request| request.url "#{fedora_uri}/fcr:versions" request.headers["Accept"] = "application/ld+json" end return [] unless version_list.success? version_graph = JSON.parse(version_list.body)&.first if fedora_version == 4 version_graph&.fetch("http://fedora.info/definitions/v4/repository#hasVersion", []) else # Fedora 5/6 use Memento. version_graph&.fetch("http://www.w3.org/ns/ldp#contains", [])&.sort_by { |x| x["@id"] }&.reverse end end |