iiif_print 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +18 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +16 -0
- data/.github/workflows/build-lint-test-action.yaml +4 -5
- data/.gitignore +5 -4
- data/.rubocop.yml +1 -0
- data/.solargraph.yml +19 -0
- data/Gemfile.lock +1025 -0
- data/README.md +102 -9
- data/Rakefile +6 -0
- data/app/actors/iiif_print/actors/cleanup_file_sets_actor_decorator.rb +24 -0
- data/app/actors/iiif_print/actors/file_set_actor_decorator.rb +30 -28
- data/app/controllers/iiif_print/split_pdfs_controller.rb +38 -0
- data/app/helpers/iiif_print/iiif_helper_decorator.rb +32 -0
- data/app/helpers/iiif_print/iiif_print_helper_behavior.rb +23 -0
- data/app/helpers/iiif_print_helper.rb +0 -20
- data/app/indexers/concerns/iiif_print/child_work_indexer.rb +27 -0
- data/app/indexers/concerns/iiif_print/file_set_indexer.rb +45 -17
- data/{lib → app/jobs}/iiif_print/jobs/application_job.rb +2 -1
- data/app/jobs/iiif_print/jobs/child_works_from_pdf_job.rb +153 -0
- data/app/jobs/iiif_print/jobs/create_relationships_job.rb +117 -0
- data/app/jobs/iiif_print/jobs/request_split_pdf_job.rb +31 -0
- data/app/listeners/iiif_print/listener.rb +31 -0
- data/app/models/concerns/iiif_print/set_child_flag.rb +10 -1
- data/app/models/concerns/iiif_print/solr/document.rb +19 -3
- data/app/models/iiif_print/iiif_search_decorator.rb +35 -0
- data/app/models/iiif_print/iiif_search_response_decorator.rb +25 -2
- data/app/models/iiif_print/pending_relationship.rb +3 -0
- data/app/presenters/iiif_print/file_set_presenter_decorator.rb +11 -0
- data/app/presenters/iiif_print/iiif_manifest_presenter_behavior.rb +120 -0
- data/app/presenters/iiif_print/iiif_manifest_presenter_factory_behavior.rb +1 -1
- data/app/presenters/iiif_print/work_show_presenter_decorator.rb +23 -11
- data/app/search_builders/concerns/iiif_print/allinson_flex_fields.rb +15 -0
- data/app/search_builders/concerns/iiif_print/highlight_search_params.rb +2 -1
- data/app/services/iiif_print/derivative_rodeo_service.rb +382 -0
- data/app/services/iiif_print/manifest_builder_service_behavior.rb +90 -31
- data/app/services/iiif_print/pluggable_derivative_service.rb +8 -10
- data/app/services/iiif_print/simple_schema_loader_decorator.rb +11 -0
- data/app/transactions/hyrax/transactions/iiif_print_container_decorator.rb +34 -0
- data/app/transactions/hyrax/transactions/steps/conditionally_destroy_children_from_split.rb +32 -0
- data/app/transactions/hyrax/transactions/steps/delete_all_file_sets_decorator.rb +35 -0
- data/app/views/catalog/_index_header_list_default.html.erb +13 -0
- data/app/views/hyrax/base/_representative_media.html.erb +4 -3
- data/app/views/hyrax/base/iiif_viewers/_universal_viewer.html.erb +1 -1
- data/app/views/hyrax/file_sets/_show_actions.html.erb +24 -0
- data/config/initializers/simple_schema_loader.rb +1 -0
- data/config/locales/iiif_print.en.yml +4 -0
- data/config/metadata/child_works_from_pdf_splitting.yaml +21 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20181214181358_create_iiif_print_derivative_attachments.rb +8 -6
- data/db/migrate/20190107165909_create_iiif_print_ingest_file_relations.rb +7 -5
- data/db/migrate/20230109000000_create_iiif_print_pending_relationships.rb +8 -6
- data/db/migrate/20231110163052_add_model_details_to_iiif_print_pending_relationships.rb +7 -0
- data/docker-compose.yml +2 -2
- data/iiif_print.gemspec +11 -10
- data/lib/generators/iiif_print/install_generator.rb +21 -1
- data/lib/generators/iiif_print/templates/config/initializers/iiif_print.rb +11 -4
- data/lib/generators/iiif_print/templates/helpers/iiif_print_helper.rb +5 -0
- data/lib/iiif_print/base_derivative_service.rb +14 -2
- data/lib/iiif_print/blacklight_iiif_search/annotation_decorator.rb +58 -6
- data/lib/iiif_print/catalog_search_builder.rb +7 -3
- data/lib/iiif_print/configuration.rb +205 -8
- data/lib/iiif_print/data/fileset_helper.rb +3 -3
- data/lib/iiif_print/data/work_derivatives.rb +4 -4
- data/lib/iiif_print/engine.rb +53 -15
- data/lib/iiif_print/errors.rb +18 -0
- data/lib/iiif_print/homepage_search_builder.rb +17 -0
- data/lib/iiif_print/image_tool.rb +12 -8
- data/lib/iiif_print/jp2_derivative_service.rb +4 -1
- data/lib/iiif_print/lineage_service.rb +47 -13
- data/lib/iiif_print/metadata.rb +67 -48
- data/lib/iiif_print/pdf_derivative_service.rb +3 -1
- data/lib/iiif_print/persistence_layer/active_fedora_adapter.rb +189 -0
- data/lib/iiif_print/persistence_layer/valkyrie_adapter.rb +183 -0
- data/lib/iiif_print/persistence_layer.rb +118 -0
- data/lib/iiif_print/split_pdfs/base_splitter.rb +153 -0
- data/lib/iiif_print/split_pdfs/child_work_creation_from_pdf_service.rb +83 -37
- data/lib/iiif_print/split_pdfs/derivative_rodeo_splitter.rb +166 -0
- data/lib/iiif_print/split_pdfs/destroy_pdf_child_works_service.rb +22 -0
- data/lib/iiif_print/split_pdfs/pages_to_jpgs_splitter.rb +19 -0
- data/lib/iiif_print/split_pdfs/pages_to_pngs_splitter.rb +26 -0
- data/lib/iiif_print/split_pdfs/pages_to_tiffs_splitter.rb +41 -0
- data/lib/iiif_print/split_pdfs/pdf_image_extraction_service.rb +64 -59
- data/lib/iiif_print/text_extraction/hocr_reader.rb +7 -3
- data/lib/iiif_print/text_extraction/page_ocr.rb +5 -4
- data/lib/iiif_print/text_extraction_derivative_service.rb +4 -2
- data/lib/iiif_print/text_formats_from_alto_service.rb +3 -1
- data/lib/iiif_print/tiff_derivative_service.rb +3 -1
- data/lib/iiif_print/version.rb +1 -1
- data/lib/iiif_print.rb +210 -20
- data/lib/samvera/derivatives/configuration.rb +83 -0
- data/lib/samvera/derivatives/hyrax.rb +129 -0
- data/lib/samvera/derivatives.rb +238 -0
- data/tasks/copy_authorities_to_test_app.rake +11 -0
- data/tasks/iiif_print_dev.rake +4 -4
- metadata +111 -196
- data/app/helpers/hyrax/iiif_helper.rb +0 -22
- data/app/indexers/concerns/iiif_print/child_indexer.rb +0 -34
- data/app/views/hyrax/file_sets/_actions.html.erb +0 -45
- data/bin/rails +0 -13
- data/lib/iiif_print/jobs/child_works_from_pdf_job.rb +0 -107
- data/lib/iiif_print/jobs/create_relationships_job.rb +0 -78
- data/lib/iiif_print/split_pdfs/pages_into_images_service.rb +0 -130
- data/spec/.keep.txt +0 -1
- data/spec/factories/ability.rb +0 -6
- data/spec/factories/newspaper_issue.rb +0 -7
- data/spec/factories/newspaper_page.rb +0 -7
- data/spec/factories/newspaper_page_solr_document.rb +0 -12
- data/spec/factories/newspaper_title.rb +0 -8
- data/spec/factories/uploaded_pdf_file.rb +0 -9
- data/spec/factories/uploaded_txt_file.rb +0 -9
- data/spec/factories/user.rb +0 -13
- data/spec/fixtures/files/4.1.07.jp2 +0 -0
- data/spec/fixtures/files/4.1.07.tiff +0 -0
- data/spec/fixtures/files/README.md +0 -7
- data/spec/fixtures/files/alto-2-0.xsd +0 -714
- data/spec/fixtures/files/broken-truncated.pdf +0 -0
- data/spec/fixtures/files/credits.md +0 -16
- data/spec/fixtures/files/lowres-gray-via-ndnp-sample.tiff +0 -0
- data/spec/fixtures/files/minimal-1-page.pdf +0 -0
- data/spec/fixtures/files/minimal-2-page.pdf +0 -0
- data/spec/fixtures/files/minimal-alto.xml +0 -31
- data/spec/fixtures/files/ndnp-alto-sample.xml +0 -24
- data/spec/fixtures/files/ndnp-sample1-json.json +0 -1
- data/spec/fixtures/files/ndnp-sample1-txt.txt +0 -1
- data/spec/fixtures/files/ndnp-sample1.pdf +0 -0
- data/spec/fixtures/files/ocr_alto.xml +0 -202
- data/spec/fixtures/files/ocr_alto_scaled_4pts_per_px.xml +0 -202
- data/spec/fixtures/files/ocr_color.tiff +0 -0
- data/spec/fixtures/files/ocr_gray.jp2 +0 -0
- data/spec/fixtures/files/ocr_gray.tiff +0 -0
- data/spec/fixtures/files/ocr_mono.tiff +0 -0
- data/spec/fixtures/files/ocr_mono_text_hocr.html +0 -78
- data/spec/fixtures/files/page1.tiff +0 -0
- data/spec/fixtures/files/sample-4page-issue.pdf +0 -0
- data/spec/fixtures/files/sample-color-newsletter.pdf +0 -0
- data/spec/fixtures/files/thumbnail.jpg +0 -0
- data/spec/helpers/hyrax/iiif_helper_spec.rb +0 -65
- data/spec/helpers/iiif_print_helper_spec.rb +0 -43
- data/spec/iiif_print/base_derivative_service_spec.rb +0 -11
- data/spec/iiif_print/blacklight_iiif_search/annotation_decorator_spec.rb +0 -51
- data/spec/iiif_print/catalog_search_builder_spec.rb +0 -60
- data/spec/iiif_print/configuration_spec.rb +0 -67
- data/spec/iiif_print/data/work_derivatives_spec.rb +0 -245
- data/spec/iiif_print/data/work_file_spec.rb +0 -99
- data/spec/iiif_print/data/work_files_spec.rb +0 -237
- data/spec/iiif_print/image_tool_spec.rb +0 -109
- data/spec/iiif_print/jobs/child_works_from_pdf_job_spec.rb +0 -30
- data/spec/iiif_print/jobs/create_relationships_job_spec.rb +0 -17
- data/spec/iiif_print/jp2_image_metadata_spec.rb +0 -37
- data/spec/iiif_print/lineage_service_spec.rb +0 -13
- data/spec/iiif_print/metadata_spec.rb +0 -115
- data/spec/iiif_print/split_pdfs/pages_into_images_service_spec.rb +0 -6
- data/spec/iiif_print/text_extraction/alto_reader_spec.rb +0 -49
- data/spec/iiif_print/text_extraction/hocr_reader_spec.rb +0 -45
- data/spec/iiif_print/text_extraction/page_ocr_spec.rb +0 -84
- data/spec/iiif_print/text_extraction/render_alto_spec.rb +0 -54
- data/spec/iiif_print/text_extraction/word_coords_builder_spec.rb +0 -44
- data/spec/iiif_print_spec.rb +0 -51
- data/spec/misc_shared.rb +0 -111
- data/spec/models/iiif_print/derivative_attachment_spec.rb +0 -37
- data/spec/models/iiif_print/ingest_file_relation_spec.rb +0 -56
- data/spec/models/solr_document_spec.rb +0 -14
- data/spec/presenters/iiif_print/iiif_manifest_presenter_behavior_spec.rb +0 -19
- data/spec/presenters/iiif_print/iiif_manifest_presenter_factory_behavior_spec.rb +0 -49
- data/spec/services/iiif_print/jp2_derivative_service_spec.rb +0 -59
- data/spec/services/iiif_print/pdf_derivative_service_spec.rb +0 -66
- data/spec/services/iiif_print/pluggable_derivative_service_spec.rb +0 -178
- data/spec/services/iiif_print/text_extraction_derivative_service_spec.rb +0 -82
- data/spec/services/iiif_print/text_formats_from_alto_service_spec.rb +0 -127
- data/spec/services/iiif_print/tiff_derivative_service_spec.rb +0 -65
- data/spec/spec_helper.rb +0 -181
- data/spec/support/controller_level_helpers.rb +0 -28
- data/spec/support/iiif_print_models.rb +0 -127
- data/spec/test_app_templates/blacklight.yml +0 -9
- data/spec/test_app_templates/fedora.yml +0 -15
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +0 -40
- data/spec/test_app_templates/redis.yml +0 -9
- data/spec/test_app_templates/solr/conf/schema.xml +0 -362
- data/spec/test_app_templates/solr/conf/solrconfig.xml +0 -322
- data/spec/test_app_templates/solr.yml +0 -7
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Samvera
|
4
|
+
module Derivatives
|
5
|
+
# The default behavior of {Hyrax::FileSetDerivativesService} is to create a derivative and then
|
6
|
+
# apply it to the FileSet. This module wraps that behavior such that we can leverage the
|
7
|
+
# {Samvera::Derivatives} module and interfaces to handle cases where some of the derivatives
|
8
|
+
# already exist.
|
9
|
+
module Hyrax
|
10
|
+
# @note This conforms to the {Hyrax::DerivativeService} interface. The intention of this
|
11
|
+
# class is to be the sole registered {Hyrax::DerivativeService.services}
|
12
|
+
class ServiceShim
|
13
|
+
# @param file_set [FileSet]
|
14
|
+
# @param candidate_derivative_types [Array<Symbol>] the possible types of derivatives that
|
15
|
+
# we could create for this file_set.
|
16
|
+
# @param config [#registry_for]
|
17
|
+
#
|
18
|
+
# @todo We will want some kind of lambda to determine the candidate_derivative_types for this
|
19
|
+
# file_set.
|
20
|
+
def initialize(file_set, candidate_derivative_types: [], config: Samvera::Derivatives.config)
|
21
|
+
@file_set = file_set
|
22
|
+
@config = config
|
23
|
+
@derivatives = candidate_derivative_types.map { |type| config.registry_for(type: type) }
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :file_set
|
27
|
+
|
28
|
+
# @return [Array<Samvera::Derivatives::Configuration::RegisteredType>]
|
29
|
+
attr_reader :derivatives
|
30
|
+
attr_reader :config
|
31
|
+
|
32
|
+
def valid?
|
33
|
+
# We have a file set, which also means a parent work. I believe we always want this to be
|
34
|
+
# valid, because we want to leverage the locator/applicator behavior instead of the
|
35
|
+
# implicit work.
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
def cleanup_derivatives; end
|
40
|
+
|
41
|
+
# We have two vectors of consideration for derivative generation:
|
42
|
+
#
|
43
|
+
# - The desired derivatives for a file_set's parent work (e.g. the candidate derivatives)
|
44
|
+
# - The available derivatives for a file_set's mime type
|
45
|
+
def create_derivatives(file_path)
|
46
|
+
derivatives.each do |derivative|
|
47
|
+
Samvera::Derivatives.locate_and_apply_derivative_for(
|
48
|
+
file_set: file_set,
|
49
|
+
file_path: file_path,
|
50
|
+
derivative: derivative
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def derivative_url(_destination_name)
|
56
|
+
""
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class FileApplicatorStrategy < Samvera::Derivatives::FileApplicator::Strategy
|
61
|
+
# With this set to true, we're telling the applicator to use the from_location
|
62
|
+
# (e.g. {Samvera::Derivatives::Hyrax::FileSetDerivativesServiceWrapper}) to apply the
|
63
|
+
# derivatives.
|
64
|
+
self.delegate_apply_to_given_from_location = true
|
65
|
+
end
|
66
|
+
|
67
|
+
class FileLocatorStrategy < Samvera::Derivatives::FileLocator::Strategy
|
68
|
+
# Implements {Samvera::Derivatives::FileLocator::Strategy} interface.
|
69
|
+
#
|
70
|
+
# @see Samvera::Derivatives::FileLocator::Strategy
|
71
|
+
#
|
72
|
+
# @return [Samvera::Derivatives::Hyrax::FileSetDerivativesServiceWrapper]
|
73
|
+
def self.locate(file_set:, file_path:, **)
|
74
|
+
file_set.samvera_derivatives_default_from_location_wrapper(file_path: file_path)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class FileSetDerivativesServiceWrapper
|
79
|
+
class_attribute :wrapped_derivative_service_class, default: ::Hyrax::FileSetDerivativesService
|
80
|
+
|
81
|
+
# @param file_set [FileSet]
|
82
|
+
# @param file_path [String]
|
83
|
+
def initialize(file_set:, file_path:)
|
84
|
+
@file_set = file_set
|
85
|
+
@file_path = file_path
|
86
|
+
@wrapped_derivative_service = wrapped_derivative_service_class.new(file_set)
|
87
|
+
end
|
88
|
+
attr_reader :file_set, :wrapped_derivative_service, :file_path
|
89
|
+
|
90
|
+
# @see Samvera::Derivatives::FileLocator.call
|
91
|
+
def present?
|
92
|
+
true
|
93
|
+
end
|
94
|
+
|
95
|
+
# @see Samvera::Derivatives::FileApplicator::Strategy
|
96
|
+
def apply!(*)
|
97
|
+
# Why the short-circuit? By the nature of the underlying
|
98
|
+
# ::Hyrax::FileSetDerivativesService, we generate multiple derivatives in one pass. But
|
99
|
+
# with the implementation of Samvera::Derivatives, we declare the derivatives and then
|
100
|
+
# iterate on locating and applying them. With this short-circuit, we will only apply the
|
101
|
+
# derivatives once.
|
102
|
+
return true if defined?(@already_applied)
|
103
|
+
|
104
|
+
return false unless wrapped_derivative_service.valid?
|
105
|
+
|
106
|
+
wrapped_derivative_service.create_derivatives(file_path)
|
107
|
+
@already_applied = true
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# The purpose of this module is to preserve the existing Hyrax derivative behavior while also
|
113
|
+
# allowing for the two-step tango of locator and applicator.
|
114
|
+
#
|
115
|
+
# @see Samvera::Derivatives.locate_and_apply_derivative_for
|
116
|
+
module FileSetDecorator
|
117
|
+
# @return [Samvera::Derivatives::Hyrax::FileSetDerivativesServiceWrapper]
|
118
|
+
def samvera_derivatives_default_from_location_wrapper(file_path:)
|
119
|
+
@samvera_derivatives_default_from_location_wrapper ||=
|
120
|
+
Samvera::Derivatives::Hyrax::FileSetDerivativesServiceWrapper.new(file_set: self, file_path: file_path)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# TODO: We are likely going to want that.
|
128
|
+
# Hyrax::DerivativeService.services = [Samvera::Derivatives::Hyrax::ServiceShim]
|
129
|
+
FileSet.prepend(Samvera::Derivatives::Hyrax::FileSetDecorator)
|
@@ -0,0 +1,238 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'samvera/derivatives/configuration'
|
4
|
+
|
5
|
+
##
|
6
|
+
# Why Samvera and not Hyrax? Because there are folks creating non-Hyrax applications that will
|
7
|
+
# almost certainly want to leverage this work. And there might be switches for `defined?(Hyrax)`.
|
8
|
+
#
|
9
|
+
# Further the following four gems have interest in the interfaces of this module:
|
10
|
+
#
|
11
|
+
# - Hyrax
|
12
|
+
# - Hydra::Derivatives
|
13
|
+
# - Bulkrax
|
14
|
+
# - IiifPrint
|
15
|
+
#
|
16
|
+
# As such, it makes some sense to isolate the module and begin defining interfaces.
|
17
|
+
module Samvera
|
18
|
+
##
|
19
|
+
# This module separates the finding/creation of a derivative binary (via {FileLocator}) and
|
20
|
+
# applying that derivative to the FileSet (via {FileApplicator}).
|
21
|
+
#
|
22
|
+
# In working on the interface and objects there is an effort to preserve backwards functionality
|
23
|
+
# while also allowing for a move away from that functionality.
|
24
|
+
#
|
25
|
+
# There are three primary concepts to consider:
|
26
|
+
#
|
27
|
+
# - Locator :: responsible for knowing where the derivative is
|
28
|
+
# - Location :: responsible for encapsulating the location
|
29
|
+
# - Applicator :: responsible for applying the located derivative to the FileSet
|
30
|
+
#
|
31
|
+
# The "trick" in this is in the polymorphism of the Location. Let's say we have the following
|
32
|
+
# desired functionality for the thumbnail derivative:
|
33
|
+
#
|
34
|
+
# ```gherkin
|
35
|
+
# Given a FileSet
|
36
|
+
# When I provide a thumbnail derivative
|
37
|
+
# Then I want to add that as the thumbnail for the FileSet
|
38
|
+
#
|
39
|
+
# Given a FileSet
|
40
|
+
# When I do not provide a thumbnail derivative
|
41
|
+
# Then I want to generate a thumbnail
|
42
|
+
# And add the generated as the thumbnail for the FileSet
|
43
|
+
# ```
|
44
|
+
#
|
45
|
+
# In the above case we would have two Locator strategies:
|
46
|
+
#
|
47
|
+
# - Find Existing One
|
48
|
+
# - Will Generate One (e.g. Hyrax::FileSetDerivativesService with Hydra::Derivative behavior)
|
49
|
+
#
|
50
|
+
# And we would have two Applicator strategies:
|
51
|
+
#
|
52
|
+
# - Apply an Existing One
|
53
|
+
# - Generate One and Apply (e.g. Hyrax::FileSetDerivativesService with Hydra::Derivative behavior)
|
54
|
+
#
|
55
|
+
# The Location from the first successful Locator will dictate how the ApplicatorStrategies do
|
56
|
+
# their work.
|
57
|
+
module Derivatives
|
58
|
+
##
|
59
|
+
# @api public
|
60
|
+
#
|
61
|
+
# Responsible for configuration of derivatives.
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# Samvera::Derivative.config do |config|
|
65
|
+
# config.register(type: :thumbnail, applicators: [CustomApplicator], locators: [CustomLocator]) do |file_set|
|
66
|
+
# file_set.video? || file_set.audio? || file_set.image?
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# @yield [Configuration]
|
71
|
+
#
|
72
|
+
# @return [Configuration]
|
73
|
+
def self.config
|
74
|
+
@config ||= Configuration.new
|
75
|
+
yield(@config) if block_given?
|
76
|
+
@config
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# @api public
|
81
|
+
#
|
82
|
+
# Locate the derivative for the given :file_set and apply it to that :file_set.
|
83
|
+
#
|
84
|
+
# @param file_set [FileSet]
|
85
|
+
# @param derivative [Samvera::Derivatives::Configuration::RegisteredType]
|
86
|
+
# @param file_path [String]
|
87
|
+
#
|
88
|
+
# @note As a concession to existing implementations of creating derivatives, file_path is
|
89
|
+
# included as a parameter.
|
90
|
+
def self.locate_and_apply_derivative_for(file_set:, derivative:, file_path:)
|
91
|
+
return false unless derivative.applicable_for?(file_set: file_set)
|
92
|
+
|
93
|
+
from_location = FileLocator.call(
|
94
|
+
file_set: file_set,
|
95
|
+
file_path: file_path,
|
96
|
+
derivative: derivative
|
97
|
+
)
|
98
|
+
|
99
|
+
FileApplicator.call(
|
100
|
+
from_location: from_location,
|
101
|
+
file_set: file_set,
|
102
|
+
derivative: derivative
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# The purpose of this module is to find the derivative file path for a FileSet and a given
|
108
|
+
# derivative type (e.g. :thumbnail).
|
109
|
+
#
|
110
|
+
# @see https://github.com/samvera-labs/bulkrax/issues/760 Design Document
|
111
|
+
#
|
112
|
+
# @note Ideally, this module would be part of Hyrax or Hydra::Derivatives
|
113
|
+
# @see https://github.com/samvera/hyrax
|
114
|
+
# @see https://github.com/samvera/hydra-derivatives
|
115
|
+
module FileLocator
|
116
|
+
##
|
117
|
+
# @api public
|
118
|
+
#
|
119
|
+
# This method is responsible for finding the correct file names for the given file set and
|
120
|
+
# derivative type.
|
121
|
+
#
|
122
|
+
# @param file_set [FileSet]
|
123
|
+
# @param file_path [String]
|
124
|
+
# @param derivative [Samvera::Derivatives::Configuration::RegisteredType]
|
125
|
+
#
|
126
|
+
# @return [Samvera::Derivatives::FromLocation]
|
127
|
+
#
|
128
|
+
# @note Why {.call}? This allows for a simple lambda interface, which can greatly ease testing
|
129
|
+
# and composition.
|
130
|
+
def self.call(file_set:, file_path:, derivative:)
|
131
|
+
from_location = nil
|
132
|
+
|
133
|
+
derivative.locators.each do |locator|
|
134
|
+
from_location = locator.locate(
|
135
|
+
file_set: file_set,
|
136
|
+
file_path: file_path,
|
137
|
+
derivative_type: derivative.type
|
138
|
+
)
|
139
|
+
break if from_location.present?
|
140
|
+
end
|
141
|
+
|
142
|
+
from_location
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# @abstract
|
147
|
+
#
|
148
|
+
# The purpose of this abstract class is to provide the public interface for strategies.
|
149
|
+
#
|
150
|
+
# @see {.find}
|
151
|
+
class Strategy
|
152
|
+
##
|
153
|
+
# @api public
|
154
|
+
# @param file_set [FileSet]
|
155
|
+
# @param file_path [String]
|
156
|
+
# @param derivative_type [#to_sym]
|
157
|
+
#
|
158
|
+
# @return [Samvera::Derivatives::FromLocation] when this is a valid strategy
|
159
|
+
# @return [NilClass] when this is not a valid strategy
|
160
|
+
def self.locate(file_set:, file_path:, derivative_type:)
|
161
|
+
raise NotImplementedError
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
module FileApplicator
|
167
|
+
##
|
168
|
+
# @api public
|
169
|
+
#
|
170
|
+
# @param file_set [FileSet]
|
171
|
+
# @param from_location [#present?]
|
172
|
+
# @param derivative [Array<#apply!>]
|
173
|
+
def self.call(file_set:, from_location:, derivative:)
|
174
|
+
# rubocop:disable Rails/Blank
|
175
|
+
return false unless from_location.present?
|
176
|
+
# rubocop:enable Rails/Blank
|
177
|
+
|
178
|
+
derivative.applicators.each do |applicator|
|
179
|
+
applicator.apply!(file_set: file_set, derivative_type: derivative.type, from_location: from_location)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
##
|
184
|
+
# @abstract
|
185
|
+
#
|
186
|
+
# The purpose of this abstract class is to provide the public interface for strategies.
|
187
|
+
#
|
188
|
+
# @see {.find}
|
189
|
+
class Strategy
|
190
|
+
# In some cases the FromLocation knows how to write itself; this is the case when we wrap
|
191
|
+
# the Hyrax::FileSetDerivativesService.
|
192
|
+
class_attribute :delegate_apply_to_given_from_location, default: false
|
193
|
+
|
194
|
+
##
|
195
|
+
# @param file_set [FileSet]
|
196
|
+
# @param derivative_type [#to_sym]
|
197
|
+
# @param from_location [Object]
|
198
|
+
def self.apply!(file_set:, derivative_type:, from_location:)
|
199
|
+
new(file_set: file_set, derivative_type: derivative_type, from_location: from_location).apply!
|
200
|
+
end
|
201
|
+
|
202
|
+
def initialize(file_set:, derivative_type:, from_location:)
|
203
|
+
@file_set = file_set
|
204
|
+
@derivative_type = derivative_type
|
205
|
+
@from_location = from_location
|
206
|
+
end
|
207
|
+
attr_reader :file_set, :derivative_type, :from_location
|
208
|
+
|
209
|
+
# @note What's going on with this logic? To continue to leverage
|
210
|
+
# Hyrax::FileSetDerivativesService, we want to let that wrapped service (as a
|
211
|
+
# FromLocation) to do it's original work. However, we might have multiple strategies
|
212
|
+
# in play for application. That case is when we want to first check for an existing
|
213
|
+
# thumbnail and failing that generate the thumbnail. The from_location could either
|
214
|
+
# be the found thumbnail...or it could be the wrapped Hyrax::FileSetDerivativesService
|
215
|
+
# that will create the thumbnail and write it to the location. The two applicator
|
216
|
+
# strategies in that case would be the wrapper and logic that will write the found
|
217
|
+
# file to the correct derivative path.
|
218
|
+
def apply!
|
219
|
+
if delegate_apply_to_given_from_location?
|
220
|
+
return false unless from_location.respond_to?(:apply!)
|
221
|
+
|
222
|
+
from_location.apply!(file_set: file_set, derivative_type: derivative_type)
|
223
|
+
else
|
224
|
+
return false if from_location.respond_to?(:apply!)
|
225
|
+
|
226
|
+
perform_apply!
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
private
|
231
|
+
|
232
|
+
def perform_apply!
|
233
|
+
raise NotImplementedError
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
namespace :engine_cart do
|
2
|
+
desc "Copy custom rights_statement and license questioning authority YAML files into the test app"
|
3
|
+
task copy_authorities: :generate do
|
4
|
+
test_app_path = ENV['ENGINE_CART_DESTINATION'] || File.expand_path(".internal_test_app", File.dirname(__FILE__))
|
5
|
+
src_dir = File.expand_path("../spec/fixtures/authorities", __dir__)
|
6
|
+
dest_dir = File.join(test_app_path, "config/authorities")
|
7
|
+
|
8
|
+
FileUtils.mkdir_p(dest_dir)
|
9
|
+
FileUtils.cp_r("#{src_dir}/.", dest_dir)
|
10
|
+
end
|
11
|
+
end
|
data/tasks/iiif_print_dev.rake
CHANGED
@@ -20,14 +20,14 @@ task :spec_with_app_load do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
if ENV.fetch('IN_DOCKER', false)
|
23
|
-
desc 'Generate the engine_cart and spin up test servers and run specs'
|
24
|
-
task ci: %w[rubocop engine_cart:generate] do
|
23
|
+
desc 'Generate the engine_cart, copy authorities and spin up test servers and run specs'
|
24
|
+
task ci: %w[rubocop engine_cart:generate engine_cart:copy_authorities] do
|
25
25
|
puts 'running continuous integration'
|
26
26
|
Rake::Task['spec'].invoke
|
27
27
|
end
|
28
28
|
else
|
29
|
-
desc 'Generate the engine_cart and spin up test servers and run specs'
|
30
|
-
task ci: %w[rubocop engine_cart:generate] do
|
29
|
+
desc 'Generate the engine_cart, copy authorities and spin up test servers and run specs'
|
30
|
+
task ci: %w[rubocop engine_cart:generate engine_cart:copy_authorities] do
|
31
31
|
puts 'running continuous integration'
|
32
32
|
Rake::Task['spec_with_app_load'].invoke
|
33
33
|
end
|