diff --git a/Gemfile b/Gemfile index 5f0fce66a..2bb0bfb9b 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ gem 'uglifier' # compressor for JavaScript assets # Stanford gems gem 'assembly-image', '~> 1.7' -gem 'assembly-objectfile', '~> 1.10' +gem 'assembly-objectfile', '~> 1.10', '>= 1.10.2' # webarchive-seed and reading order is supported in 1.10.2 and better gem 'dor-services-client', '~> 6.27' gem 'dor-workflow-client' gem 'druid-tools' diff --git a/Gemfile.lock b/Gemfile.lock index 115ea782e..74a0e223c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -67,7 +67,7 @@ GEM assembly-image (1.7.7) assembly-objectfile (>= 1.6.4) mini_exiftool (>= 1.6, < 3) - assembly-objectfile (1.10.0) + assembly-objectfile (1.10.2) activesupport (>= 5.2.0) deprecation dry-struct (~> 1.0) @@ -115,17 +115,7 @@ GEM rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - cocina-models (0.55.0) - activesupport - dry-struct (~> 1.0) - dry-types (~> 1.1) - openapi3_parser - openapi_parser - thor - zeitwerk (~> 2.1) coderay (1.1.3) - commonmarker (0.21.2) - ruby-enum (~> 0.5) concurrent-ruby (1.1.8) config (3.0.0) deep_merge (~> 1.2, >= 1.2.1) @@ -155,13 +145,6 @@ GEM capistrano-one_time_key capistrano-shared_configs docile (1.3.5) - dor-services-client (6.27.0) - activesupport (>= 4.2, < 7) - cocina-models (~> 0.55.0) - deprecation - faraday (>= 0.15, < 2) - moab-versioning (~> 4.0) - zeitwerk (~> 2.1) dor-workflow-client (3.23.1) activesupport (>= 3.2.1, < 7) deprecation (>= 0.99.0) @@ -271,11 +254,6 @@ GEM mini_mime (1.0.2) mini_portile2 (2.5.0) minitest (5.14.4) - moab-versioning (4.4.1) - druid-tools (>= 1.0.0) - json - nokogiri - nokogiri-happymapper mono_logger (1.1.0) multi_json (1.15.0) multipart-post (2.1.1) @@ -290,13 +268,7 @@ GEM racc (~> 1.4) nokogiri (1.11.2-x86_64-linux) racc (~> 1.4) - nokogiri-happymapper (0.8.1) - nokogiri (~> 1.5) okcomputer (1.18.4) - openapi3_parser (0.9.0) - commonmarker (~> 0.17) - psych (~> 3.1) - openapi_parser (0.12.1) orm_adapter (0.5.0) parallel (1.20.1) parser (3.0.0.0) @@ -311,7 +283,6 @@ GEM pry (~> 0.13.0) pry-rails (0.3.9) pry (>= 0.10.4) - psych (3.3.1) public_suffix (4.0.6) racc (1.5.2) rack (2.2.3) @@ -398,8 +369,6 @@ GEM unicode-display_width (>= 1.4.0, < 1.7) rubocop-rspec (1.41.0) rubocop (>= 0.68.1) - ruby-enum (0.9.0) - i18n ruby-progressbar (1.11.0) ruby2_keywords (0.0.4) sassc (2.0.1) @@ -469,7 +438,7 @@ PLATFORMS DEPENDENCIES assembly-image (~> 1.7) - assembly-objectfile (~> 1.10) + assembly-objectfile (~> 1.10, >= 1.10.2) bootstrap (~> 4.3, >= 4.3.1) capistrano-bundler capistrano-passenger @@ -480,7 +449,6 @@ DEPENDENCIES devise devise-remote-user dlss-capistrano (~> 3.10) - dor-services-client (~> 6.27) dor-workflow-client druid-tools equivalent-xml diff --git a/app/lib/pre_assembly/content_metadata_creator.rb b/app/lib/pre_assembly/content_metadata_creator.rb index da79dd36a..c965115f2 100644 --- a/app/lib/pre_assembly/content_metadata_creator.rb +++ b/app/lib/pre_assembly/content_metadata_creator.rb @@ -4,12 +4,13 @@ module PreAssembly class ContentMetadataCreator # rubocop:disable Metrics/ParameterLists def initialize(druid_id:, content_md_creation:, object_files:, - content_md_creation_style:, media_manifest:, add_file_attributes:) + content_md_creation_style:, media_manifest:, reading_order:, add_file_attributes:) @druid_id = druid_id @content_md_creation = content_md_creation @object_files = object_files @content_md_creation_style = content_md_creation_style @media_manifest = media_manifest + @reading_order = reading_order @add_file_attributes = add_file_attributes end # rubocop:enable Metrics/ParameterLists @@ -24,13 +25,14 @@ def create add_exif: false, bundle: content_md_creation.to_sym, style: content_md_creation_style, + reading_order: reading_order, add_file_attributes: add_file_attributes) end private attr_reader :druid_id, :content_md_creation, :object_files, - :content_md_creation_style, :media_manifest, :add_file_attributes + :content_md_creation_style, :media_manifest, :reading_order, :add_file_attributes # Object files that should be included in content metadata. def content_object_files diff --git a/app/lib/pre_assembly/digital_object.rb b/app/lib/pre_assembly/digital_object.rb index de1997e58..15aa005d6 100644 --- a/app/lib/pre_assembly/digital_object.rb +++ b/app/lib/pre_assembly/digital_object.rb @@ -47,8 +47,10 @@ def content_md_creation_style Cocina::Models::Vocab.object => :file, Cocina::Models::Vocab.book => :simple_book, Cocina::Models::Vocab.manuscript => :simple_book, + Cocina::Models::Vocab.document => :document, Cocina::Models::Vocab.map => :map, - Cocina::Models::Vocab.three_dimensional => :'3d' + Cocina::Models::Vocab.three_dimensional => :'3d', + Cocina::Models::Vocab.webarchive_seed => :'webarchive-seed' }.fetch(object_type, content_structure.to_sym) end @@ -118,11 +120,21 @@ def generate_content_metadata(file_attributes_supplied) # Invoke the contentMetadata creation method used by the project # @param [Boolean] file_attributes_supplied - true if publish/preserve/shelve attribs are supplied def create_content_metadata(file_attributes_supplied) + # Special case: if the content_structure set by the user is a rtl simple book, + # be sure we set this as the style, else use the default and style from the object + if content_structure == 'simple_book_rtl' + reading_order = 'rtl' + content_style = :simple_book + else + reading_order = 'ltr' + content_style = content_md_creation_style + end ContentMetadataCreator.new(druid_id: druid.id, content_md_creation: content_md_creation, object_files: object_files, - content_md_creation_style: content_md_creation_style, + content_md_creation_style: content_style, media_manifest: media_manifest, + reading_order: reading_order, add_file_attributes: file_attributes_supplied).create end diff --git a/app/models/batch_context.rb b/app/models/batch_context.rb index 47c80cfe8..2dc778bae 100644 --- a/app/models/batch_context.rb +++ b/app/models/batch_context.rb @@ -23,7 +23,10 @@ class BatchContext < ApplicationRecord 'file' => 3, 'media' => 4, '3d' => 5, - 'document' => 6 + 'document' => 6, + 'maps' => 7, + 'webarchive_seed' => 8, + 'simple_book_rtl' => 9 } enum content_metadata_creation: { diff --git a/app/views/batch_contexts/_new_bc_form.erb b/app/views/batch_contexts/_new_bc_form.erb index c3acb0000..ade4e369e 100644 --- a/app/views/batch_contexts/_new_bc_form.erb +++ b/app/views/batch_contexts/_new_bc_form.erb @@ -14,12 +14,15 @@ <%= form.input :content_structure, collection: [ - ['Simple Image', 'simple_image'], - ['Simple Book', 'simple_book'], + ['Image', 'simple_image'], + ['Book (ltr)', 'simple_book'], + ['Book (rtl)', 'simple_book_rtl'], ['Document', 'document'], ['File', 'file'], ['Media', 'media'], ['3D', '3d'], + ['Map', 'maps'], + ['Webarchive seed', 'webarchive_seed'] ] %> diff --git a/spec/features/dark_file_object_spec.rb b/spec/features/dark_file_object_spec.rb index 7d6f56afb..1ffd54543 100644 --- a/spec/features/dark_file_object_spec.rb +++ b/spec/features/dark_file_object_spec.rb @@ -10,7 +10,7 @@ let(:bare_druid) { 'tx666tx9999' } let(:object_staging_dir) { Rails.root.join(Settings.assembly_staging_dir, 'tx', '666', 'tx', '9999', bare_druid) } let(:cocina_model_dark_access) { instance_double(Cocina::Models::Access, access: 'dark') } - let(:item) { instance_double(Cocina::Models::DRO, type: Cocina::Models::Vocab.media, access: cocina_model_dark_access) } + let(:item) { instance_double(Cocina::Models::DRO, type: Cocina::Models::Vocab.object, access: cocina_model_dark_access) } let(:dsc_object_version) { instance_double(Dor::Services::Client::ObjectVersion, openable?: true) } let(:dsc_object) { instance_double(Dor::Services::Client::Object, version: dsc_object_version, find: item) } let(:exp_content_md) do diff --git a/spec/features/document_spec.rb b/spec/features/document_spec.rb index 82e1e5c15..52ff640bd 100644 --- a/spec/features/document_spec.rb +++ b/spec/features/document_spec.rb @@ -8,7 +8,7 @@ let(:bare_druid) { 'pr666rr9999' } let(:object_staging_dir) { Rails.root.join(Settings.assembly_staging_dir, 'pr', '666', 'rr', '9999', bare_druid) } let(:cocina_model_world_access) { instance_double(Cocina::Models::Access, access: 'world') } - let(:item) { instance_double(Cocina::Models::DRO, type: Cocina::Models::Vocab.media, access: cocina_model_world_access) } + let(:item) { instance_double(Cocina::Models::DRO, type: Cocina::Models::Vocab.document, access: cocina_model_world_access) } let(:dsc_object_version) { instance_double(Dor::Services::Client::ObjectVersion, openable?: true) } let(:dsc_object) { instance_double(Dor::Services::Client::Object, version: dsc_object_version, find: item) } let(:exp_content_md) do diff --git a/spec/features/image_spec.rb b/spec/features/image_spec.rb index 6298ce518..7e02a53d1 100644 --- a/spec/features/image_spec.rb +++ b/spec/features/image_spec.rb @@ -8,7 +8,7 @@ let(:bare_druid) { 'pr666rr9999' } let(:object_staging_dir) { Rails.root.join(Settings.assembly_staging_dir, 'pr', '666', 'rr', '9999', bare_druid) } let(:cocina_model_world_access) { instance_double(Cocina::Models::Access, access: 'world') } - let(:item) { instance_double(Cocina::Models::DRO, type: Cocina::Models::Vocab.media, access: cocina_model_world_access) } + let(:item) { instance_double(Cocina::Models::DRO, type: Cocina::Models::Vocab.image, access: cocina_model_world_access) } let(:dsc_object_version) { instance_double(Dor::Services::Client::ObjectVersion, openable?: true) } let(:dsc_object) { instance_double(Dor::Services::Client::Object, version: dsc_object_version, find: item) } let(:exp_content_md) do @@ -47,7 +47,7 @@ fill_in 'Project name', with: project_name select 'Pre Assembly Run', from: 'Job type' - select 'Simple Image', from: 'Content structure' + select 'Image', from: 'Content structure' fill_in 'Bundle dir', with: bundle_dir click_button 'Submit' diff --git a/spec/features/public_tif_spec.rb b/spec/features/public_tif_spec.rb index 1df9a6448..0080d1b9e 100644 --- a/spec/features/public_tif_spec.rb +++ b/spec/features/public_tif_spec.rb @@ -10,7 +10,7 @@ let(:bare_druid) { 'tf111tf2222' } let(:object_staging_dir) { Rails.root.join(Settings.assembly_staging_dir, 'tf', '111', 'tf', '2222', bare_druid) } let(:cocina_model_world_access) { instance_double(Cocina::Models::Access, access: 'world') } - let(:item) { instance_double(Cocina::Models::DRO, type: Cocina::Models::Vocab.media, access: cocina_model_world_access) } + let(:item) { instance_double(Cocina::Models::DRO, type: Cocina::Models::Vocab.image, access: cocina_model_world_access) } let(:dsc_object_version) { instance_double(Dor::Services::Client::ObjectVersion, openable?: true) } let(:dsc_object) { instance_double(Dor::Services::Client::Object, version: dsc_object_version, find: item) } let(:exp_content_md) do @@ -49,7 +49,7 @@ fill_in 'Project name', with: project_name select 'Pre Assembly Run', from: 'Job type' - select 'Simple Image', from: 'Content structure' + select 'Image', from: 'Content structure' fill_in 'Bundle dir', with: bundle_dir choose 'Preserve=Yes, Shelve=Yes, Publish=Yes' diff --git a/spec/lib/pre_assembly/content_metadata_creator_spec.rb b/spec/lib/pre_assembly/content_metadata_creator_spec.rb index 4f3e91666..e813a4d75 100644 --- a/spec/lib/pre_assembly/content_metadata_creator_spec.rb +++ b/spec/lib/pre_assembly/content_metadata_creator_spec.rb @@ -7,6 +7,7 @@ object_files: object_files, content_md_creation_style: content_md_creation_style, media_manifest: media_manifest, + reading_order: reading_order, add_file_attributes: add_file_attributes) end @@ -14,6 +15,7 @@ let(:content_md_creation) { 'bar' } let(:content_md_creation_style) { 'baz' } let(:add_file_attributes) { false } + let(:reading_order) { 'ltr' } let(:media_manifest) { 'quix' } describe '#content_object_files' do @@ -55,7 +57,7 @@ creator.create expect(Assembly::ContentMetadata).to have_received(:create_content_metadata) .with(druid: druid_id, objects: object_files, add_exif: false, - bundle: :bar, style: content_md_creation_style, add_file_attributes: false) + bundle: :bar, style: content_md_creation_style, reading_order: reading_order, add_file_attributes: false) end end @@ -66,7 +68,7 @@ creator.create expect(Assembly::ContentMetadata).to have_received(:create_content_metadata) .with(druid: druid_id, objects: object_files, add_exif: false, - bundle: :bar, style: content_md_creation_style, add_file_attributes: true) + bundle: :bar, style: content_md_creation_style, reading_order: reading_order, add_file_attributes: true) end end end diff --git a/spec/lib/pre_assembly/digital_object_spec.rb b/spec/lib/pre_assembly/digital_object_spec.rb index ec628fee2..63d9a4b44 100644 --- a/spec/lib/pre_assembly/digital_object_spec.rb +++ b/spec/lib/pre_assembly/digital_object_spec.rb @@ -110,7 +110,7 @@ def add_object_files(extension = 'tif', all_files_public: false) end describe '#create_content_metadata' do - describe 'default content metadata' do + describe 'default content metadata (image)' do let(:exp_xml) do noko_doc <<-XML @@ -175,10 +175,221 @@ def add_object_files(extension = 'tif', all_files_public: false) end end + describe 'map content metadata' do + let(:exp_xml) do + noko_doc <<-XML + + + + + 1111 + + + + + + 2222 + + + + XML + end + + let(:assembly_directory) { PreAssembly::AssemblyDirectory.new(druid_id: druid.id) } + + before do + allow(object).to receive(:druid).and_return(druid) + allow(object).to receive(:object_type).and_return('') + allow(bc).to receive(:content_structure).and_return('map') + add_object_files('jp2') + allow(object).to receive(:assembly_directory).and_return(assembly_directory) + end + + around do |example| + RSpec::Mocks.with_temporary_scope do + Dir.mktmpdir(*tmp_dir_args) do |tmp_area| + allow(assembly_directory).to receive(:druid_tree_dir).and_return(tmp_area) + example.run + end + end + end + + it 'generates the expected xml text' do + expect(noko_doc(object.send(:create_content_metadata, false))).to be_equivalent_to exp_xml + end + + it 'is able to write the content_metadata XML to a file' do + assembly_directory.create_object_directories + file_name = object.send(:assembly_directory).content_metadata_file + expect(File.exist?(file_name)).to eq(false) + object.send(:generate_content_metadata, false) + expect(noko_doc(File.read(file_name))).to be_equivalent_to exp_xml + end + end + + describe 'book (ltr) content metadata' do + let(:exp_xml) do + noko_doc <<-XML + + + + + + 1111 + + + + + + 2222 + + + + XML + end + + let(:assembly_directory) { PreAssembly::AssemblyDirectory.new(druid_id: druid.id) } + + before do + allow(object).to receive(:druid).and_return(druid) + allow(object).to receive(:object_type).and_return('') + allow(bc).to receive(:content_structure).and_return('simple_book') + add_object_files('jp2') + allow(object).to receive(:assembly_directory).and_return(assembly_directory) + end + + around do |example| + RSpec::Mocks.with_temporary_scope do + Dir.mktmpdir(*tmp_dir_args) do |tmp_area| + allow(assembly_directory).to receive(:druid_tree_dir).and_return(tmp_area) + example.run + end + end + end + + it 'generates the expected xml text' do + expect(noko_doc(object.send(:create_content_metadata, false))).to be_equivalent_to exp_xml + end + + it 'is able to write the content_metadata XML to a file' do + assembly_directory.create_object_directories + file_name = object.send(:assembly_directory).content_metadata_file + expect(File.exist?(file_name)).to eq(false) + object.send(:generate_content_metadata, false) + expect(noko_doc(File.read(file_name))).to be_equivalent_to exp_xml + end + end + + describe 'book (rtl) content metadata' do + let(:exp_xml) do + noko_doc <<-XML + + + + + + 1111 + + + + + + 2222 + + + + XML + end + + let(:assembly_directory) { PreAssembly::AssemblyDirectory.new(druid_id: druid.id) } + + before do + allow(object).to receive(:druid).and_return(druid) + allow(object).to receive(:object_type).and_return('') + allow(bc).to receive(:content_structure).and_return('simple_book_rtl') + add_object_files('jp2') + allow(object).to receive(:assembly_directory).and_return(assembly_directory) + end + + around do |example| + RSpec::Mocks.with_temporary_scope do + Dir.mktmpdir(*tmp_dir_args) do |tmp_area| + allow(assembly_directory).to receive(:druid_tree_dir).and_return(tmp_area) + example.run + end + end + end + + it 'generates the expected xml text' do + expect(noko_doc(object.send(:create_content_metadata, false))).to be_equivalent_to exp_xml + end + + it 'is able to write the content_metadata XML to a file' do + assembly_directory.create_object_directories + file_name = object.send(:assembly_directory).content_metadata_file + expect(File.exist?(file_name)).to eq(false) + object.send(:generate_content_metadata, false) + expect(noko_doc(File.read(file_name))).to be_equivalent_to exp_xml + end + end + + describe 'webarchive-seed content metadata' do + let(:exp_xml) do + noko_doc <<-XML + + + + + 1111 + + + + + + 2222 + + + + XML + end + + let(:assembly_directory) { PreAssembly::AssemblyDirectory.new(druid_id: druid.id) } + + before do + allow(object).to receive(:druid).and_return(druid) + allow(object).to receive(:object_type).and_return('') + allow(bc).to receive(:content_structure).and_return('webarchive-seed') + add_object_files('jp2') + allow(object).to receive(:assembly_directory).and_return(assembly_directory) + end + + around do |example| + RSpec::Mocks.with_temporary_scope do + Dir.mktmpdir(*tmp_dir_args) do |tmp_area| + allow(assembly_directory).to receive(:druid_tree_dir).and_return(tmp_area) + example.run + end + end + end + + it 'generates the expected xml text' do + expect(noko_doc(object.send(:create_content_metadata, false))).to be_equivalent_to exp_xml + end + + it 'is able to write the content_metadata XML to a file' do + assembly_directory.create_object_directories + file_name = object.send(:assembly_directory).content_metadata_file + expect(File.exist?(file_name)).to eq(false) + object.send(:generate_content_metadata, false) + expect(noko_doc(File.read(file_name))).to be_equivalent_to exp_xml + end + end + describe 'grouped by filename, simple book content metadata without file attributes' do let(:exp_xml) do noko_doc <<-XML + @@ -219,6 +430,7 @@ def add_object_files(extension = 'tif', all_files_public: false) let(:exp_xml) do noko_doc <<-XML + diff --git a/spec/models/batch_context_spec.rb b/spec/models/batch_context_spec.rb index fe5865e30..6e6e7fe43 100644 --- a/spec/models/batch_context_spec.rb +++ b/spec/models/batch_context_spec.rb @@ -63,7 +63,10 @@ 'file' => 3, 'media' => 4, '3d' => 5, - 'document' => 6 + 'document' => 6, + 'maps' => 7, + 'webarchive_seed' => 8, + 'simple_book_rtl' => 9 ) end