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.
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
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
-
#supports?(feature) ⇒ Boolean
True if the adapter supports the given feature.
- #upload(file:, original_filename:, resource:, content_type: "application/octet-stream", resource_uri_transformer: default_resource_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
Returns a new instance of Fedora.
10 11 12 13 14 |
# File 'lib/valkyrie/storage/fedora.rb', line 10 def initialize(connection:, base_path: "/", fedora_version: Valkyrie::Persistence::Fedora::DEFAULT_FEDORA_VERSION) @connection = connection @base_path = base_path @fedora_version = fedora_version 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 |
Instance Method Details
#current_version_id(id:) ⇒ Object
133 134 135 136 137 |
# File 'lib/valkyrie/storage/fedora.rb', line 133 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.
85 86 87 |
# File 'lib/valkyrie/storage/fedora.rb', line 85 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
188 189 190 191 |
# File 'lib/valkyrie/storage/fedora.rb', line 188 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
35 36 37 |
# File 'lib/valkyrie/storage/fedora.rb', line 35 def find_by(id:) perform_find(id: id) end |
#find_versions(id:) ⇒ Array<Valkyrie::StorageAdapter::StreamFile>
74 75 76 77 78 79 80 81 |
# File 'lib/valkyrie/storage/fedora.rb', line 74 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) end end |
#handles?(id:) ⇒ Boolean
Returns true if this adapter can handle this type of identifer.
18 19 20 |
# File 'lib/valkyrie/storage/fedora.rb', line 18 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.
121 122 123 124 125 126 127 128 129 |
# File 'lib/valkyrie/storage/fedora.rb', line 121 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.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/valkyrie/storage/fedora.rb', line 152 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
139 140 141 142 143 144 145 146 |
# File 'lib/valkyrie/storage/fedora.rb', line 139 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 |
#supports?(feature) ⇒ Boolean
Returns true if the adapter supports the given feature.
24 25 26 27 28 29 |
# File 'lib/valkyrie/storage/fedora.rb', line 24 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 false end |
#upload(file:, original_filename:, resource:, content_type: "application/octet-stream", resource_uri_transformer: default_resource_uri_transformer, **_extra_arguments) ⇒ Valkyrie::StorageAdapter::StreamFile
46 47 48 49 50 51 52 53 54 |
# File 'lib/valkyrie/storage/fedora.rb', line 46 def upload(file:, original_filename:, resource:, content_type: "application/octet-stream", # rubocop:disable Metrics/ParameterLists resource_uri_transformer: default_resource_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
104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/valkyrie/storage/fedora.rb', line 104 def upload_file(fedora_uri:, io:, content_type: "application/octet-stream", original_filename: "default") sha1 = [5, 6].include?(fedora_version) ? "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
59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/valkyrie/storage/fedora.rb', line 59 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
193 194 195 196 |
# File 'lib/valkyrie/storage/fedora.rb', line 193 def valkyrie_identifier(uri:) id = uri.to_s.sub("http://", PROTOCOL) Valkyrie::ID.new(id) end |
#version_list(fedora_uri) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/valkyrie/storage/fedora.rb', line 89 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 |