Skip to content

Commit

Permalink
Create FileSetDescription to find characterization for FileSets
Browse files Browse the repository at this point in the history
Valkyrie-based FileSet objects don't have direct access to characterization
information. In ActiveFedora, we used a `#characterization_proxy` to provide
that information. Here, we provide a small service that can find the "primary"
file (`FileMetadata`) for a given FileSet, and ask it about its description.
  • Loading branch information
Tom Johnson committed Jan 25, 2020
1 parent b02489e commit 49b4584
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 5 deletions.
17 changes: 16 additions & 1 deletion app/models/hyrax/file_metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

module Hyrax
class FileMetadata < Valkyrie::Resource
GENERIC_MIME_TYPE = 'application/octet-stream'

attribute :file_identifiers, ::Valkyrie::Types::Set # id of the file stored by the storage adapter
attribute :alternate_ids, Valkyrie::Types::Set.of(Valkyrie::Types::ID) # id of the Hydra::PCDM::File which holds metadata and the file in ActiveFedora
attribute :file_set_id, ::Valkyrie::Types::ID # id of parent file set resource

# all remaining attributes are on AF::File metadata_node unless otherwise noted
attribute :label, ::Valkyrie::Types::Set
attribute :original_filename, ::Valkyrie::Types::Set
attribute :mime_type, ::Valkyrie::Types::Set
attribute :mime_type, ::Valkyrie::Types::String.default(GENERIC_MIME_TYPE)
attribute :use, ::Valkyrie::Types::Set # AF::File type
attribute :content, ::Valkyrie::Types::Set

Expand Down Expand Up @@ -79,14 +81,27 @@ def self.for(file:)
use: file.try(:use) || [::Valkyrie::Vocab::PCDMUse.OriginalFile])
end

##
# @param [Symbol] use
# @return [Boolean]
def used_for?(use)
public_send("#{use}?")
end

##
# @return [Boolean]
def original_file?
use.include?(::Valkyrie::Vocab::PCDMUse.OriginalFile)
end

##
# @return [Boolean]
def thumbnail_file?
use.include?(::Valkyrie::Vocab::PCDMUse.ThumbnailImage)
end

##
# @return [Boolean]
def extracted_file?
use.include?(::Valkyrie::Vocab::PCDMUse.ExtractedImage)
end
Expand Down
42 changes: 42 additions & 0 deletions app/services/hyrax/characterization/file_set_description.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

module Hyrax
module Characterization
##
# @api public
class FileSetDescription
include Hydra::Works::MimeTypes

##
# @!attribute [rw] file_set
# @return [Hyrax::FileSet]
attr_accessor :file_set

delegate :mime_type, to: :primary_file

##
# @param [Hyrax::FileSet] file_set
# @param [Symbol] primary_file a symbol mapping to the file_set member
# used for characterization
def initialize(file_set:, primary_file: :original_file)
self.file_set = file_set
@primary_file = primary_file
end

##
# @api public
# @return [Hyrax::FileMetadata] the member file to use for characterization
def primary_file
files.find { |f| f.used_for?(@primary_file) } || Hyrax::FileMetadata.new
end

private

##
# @api private
def files
@__files__ ||= Hyrax.query_service.custom_queries.find_files(file_set: file_set)
end
end
end
end
Empty file.
16 changes: 13 additions & 3 deletions spec/models/hyrax/file_metadata_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,31 @@
let(:resource_klass) { described_class }
end

let(:file) { Rack::Test::UploadedFile.new('spec/fixtures/world.png', 'image/png') }
let(:subject) do
subject(:file_metadata) do
described_class.for(file: file).new(id: 'test_id', format_label: 'test_format_label')
end

let(:file) { Rack::Test::UploadedFile.new('spec/fixtures/world.png', 'image/png') }
let(:pcdm_file_uri) { RDF::URI('http://pcdm.org/models#File') }

it 'sets the proper attributes' do
expect(subject.id.to_s).to eq 'test_id'
expect(subject.label).to contain_exactly('world.png')
expect(subject.original_filename).to contain_exactly('world.png')
expect(subject.mime_type).to contain_exactly('image/png')
expect(subject.mime_type).to eq('image/png')
expect(subject.format_label).to contain_exactly('test_format_label')
expect(subject.use).to contain_exactly(Valkyrie::Vocab::PCDMUse.OriginalFile)
end

describe '#used_for?' do
it 'is true when use matches' do
expect { file_metadata.use = [Valkyrie::Vocab::PCDMUse.ThumbnailImage] }
.to change { file_metadata.used_for?(:original_file) }
.from(true)
.to false
end
end

describe '#original_file?' do
context 'when use says file is the original file' do
before { subject.use = [Valkyrie::Vocab::PCDMUse.OriginalFile, pcdm_file_uri] }
Expand Down
37 changes: 37 additions & 0 deletions spec/services/hyrax/characterization/file_set_description_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

RSpec.describe Hyrax::Characterization::FileSetDescription, valkyrie_adapter: :test_adapter do
subject(:description) { described_class.new(file_set: file_set) }

let(:ctype) { 'image/png' }
let(:file) { Rack::Test::UploadedFile.new('spec/fixtures/world.png', ctype) }
let(:file_set) { FactoryBot.valkyrie_create(:hyrax_file_set, file_ids: file_ids) }
let(:file_ids) { [] }

describe '#mime_type' do
context 'before the file set is saved' do
let(:file_set) { FactoryBot.build(:hyrax_file_set) }

it 'has a generic MIME type' do
expect(description.mime_type).to eq 'application/octet-stream'
end
end

context 'when it has no files' do
it 'has a generic MIME type' do
expect(description.mime_type).to eq 'application/octet-stream'
end
end

context 'when it has an original file' do
let(:file_ids) { [original_file.id] }
let(:original_file) { Hyrax.persister.save(resource: Hyrax::FileMetadata.for(file: file)) }

it { is_expected.to be_image }

it 'has a mime type from a file' do
expect(description.mime_type).to eq ctype
end
end
end
end
Empty file.
2 changes: 1 addition & 1 deletion spec/wings/services/file_metadata_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
expect(built_file_metadata.file_set_id.id).to eq file_set.id.id
expect(built_file_metadata.label).to contain_exactly(original_name)
expect(built_file_metadata.original_filename).to contain_exactly(original_name)
expect(built_file_metadata.mime_type).to contain_exactly(mime_type)
expect(built_file_metadata.mime_type).to eq mime_type
expect(built_file_metadata.use).to contain_exactly(use)
end
end
Expand Down

0 comments on commit 49b4584

Please sign in to comment.