diff --git a/app/controllers/iiif_controller.rb b/app/controllers/iiif_controller.rb index 332acf28..4de395aa 100644 --- a/app/controllers/iiif_controller.rb +++ b/app/controllers/iiif_controller.rb @@ -146,7 +146,7 @@ def transformation end def stacks_identifier - @stacks_identifier ||= StacksIdentifier.new(escaped_identifier.sub(/^degraded_/, '') + '.jp2') + @stacks_identifier ||= StacksIdentifier.new(escaped_identifier.sub(/^degraded_/, ''), file_ext: 'jp2') end def canonical_params diff --git a/app/models/stacks_identifier.rb b/app/models/stacks_identifier.rb index f62d27d5..a06c775a 100644 --- a/app/models/stacks_identifier.rb +++ b/app/models/stacks_identifier.rb @@ -2,19 +2,26 @@ # The identifier of a stacks resource class StacksIdentifier - def initialize(options = {}) - if options.is_a? String - parse_identifer(options) - elsif options[:id] - parse_identifer(options[:id]) - elsif options[:druid] && options[:file_name] - self.druid = options[:druid] - @file_name = options[:file_name] + attr_reader :druid, :file_name, :options + + OPTIONS_DELIMITER = '%2F!attr!%2F' + def initialize(identifier = nil, id: nil, druid: nil, file_name: nil, file_ext: nil, **options) + if identifier + parse_identifer(identifier, file_ext) + elsif id + parse_identifer(id, file_ext) + elsif druid && file_name + self.druid = druid + @file_name = [file_name, file_ext.presence].compact.join('.') end + @options = (@options || {}).merge(options) end def to_s - [@druid, @file_name].join('%2F') + identifier_part = [@druid, @file_name].join('%2F') + options_part = @options.map { |k, v| "#{k}=#{v}" }.join('%2F') + + [identifier_part, options_part.presence].compact.join(OPTIONS_DELIMITER) end def ==(other) @@ -37,8 +44,6 @@ def treeified_path File.join(druid_parts[1..4], file_name) end - attr_reader :druid, :file_name - private attr_reader :druid_parts @@ -49,8 +54,14 @@ def druid=(druid) @druid_parts = match end - def parse_identifer(id) - druid, @file_name = id.split('%2F', 2) + def parse_identifer(id, file_ext) + identifier_and_file_name, attrs = id.split(OPTIONS_DELIMITER, 2) + druid, file_name = identifier_and_file_name.split('%2F', 2) self.druid = druid + @file_name = [file_name, file_ext.presence].compact.join('.') + + if attrs.present? + @options = attrs.split('%2F').map { |x| x.split('=', 2) }.to_h + end end end diff --git a/spec/models/stacks_identifier_spec.rb b/spec/models/stacks_identifier_spec.rb index 9be29edf..d494a92b 100644 --- a/spec/models/stacks_identifier_spec.rb +++ b/spec/models/stacks_identifier_spec.rb @@ -32,4 +32,19 @@ subject { instance.treeified_path } it { is_expected.to eq 'nr/349/ct/7889/nr349ct7889_00_0001.jp2' } end + + context 'with some optional attributes' do + let(:instance) { described_class.new identifier } + let(:identifier) { 'nr349ct7889%2Fnr349ct7889_00_0001%2F!attr!%2Fversion=2'} + + it 'parses out the right data' do + expect(instance.druid).to eq 'nr349ct7889' + expect(instance.file_name_without_ext).to eq 'nr349ct7889_00_0001' + expect(instance.options['version']).to eq '2' + end + + it 'reserializes to the original value' do + expect(instance.to_s).to eq identifier + end + end end