hydra-derivatives 3.3.2 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +69 -0
  3. data/.rubocop.yml +53 -34
  4. data/.rubocop_todo.yml +42 -9
  5. data/.solr_wrapper +2 -0
  6. data/CODE_OF_CONDUCT.md +36 -0
  7. data/CONTRIBUTING.md +23 -21
  8. data/Gemfile +5 -3
  9. data/README.md +74 -5
  10. data/Rakefile +13 -1
  11. data/SUPPORT.md +5 -0
  12. data/VERSION +1 -1
  13. data/config/fcrepo_wrapper_test.yml +6 -0
  14. data/config/solr_wrapper_test.yml +2 -0
  15. data/hydra-derivatives.gemspec +16 -16
  16. data/lib/hydra/derivatives.rb +2 -2
  17. data/lib/hydra/derivatives/audio_encoder.rb +1 -1
  18. data/lib/hydra/derivatives/config.rb +1 -1
  19. data/lib/hydra/derivatives/io_decorator.rb +13 -6
  20. data/lib/hydra/derivatives/logger.rb +5 -1
  21. data/lib/hydra/derivatives/processors/active_encode.rb +1 -1
  22. data/lib/hydra/derivatives/processors/document.rb +4 -1
  23. data/lib/hydra/derivatives/processors/full_text.rb +20 -6
  24. data/lib/hydra/derivatives/processors/jpeg2k_image.rb +7 -16
  25. data/lib/hydra/derivatives/processors/processor.rb +0 -7
  26. data/lib/hydra/derivatives/processors/shell_based_processor.rb +5 -3
  27. data/lib/hydra/derivatives/runners/full_text_extract.rb +1 -1
  28. data/lib/hydra/derivatives/services/capability_service.rb +1 -1
  29. data/lib/hydra/derivatives/services/persist_basic_contained_output_file_service.rb +5 -1
  30. data/lib/hydra/derivatives/services/persist_output_file_service.rb +5 -3
  31. data/solr/config/schema.xml +0 -2
  32. data/solr/config/xslt/example.xsl +1 -1
  33. data/solr/config/xslt/luke.xsl +1 -1
  34. metadata +187 -138
  35. data/.travis.yml +0 -26
  36. data/spec/fixtures/FlashPix.ppt +0 -0
  37. data/spec/fixtures/adobe1998.tif +0 -0
  38. data/spec/fixtures/countdown.avi +0 -0
  39. data/spec/fixtures/jpeg2k_config.yml +0 -20
  40. data/spec/fixtures/piano_note.wav +0 -0
  41. data/spec/fixtures/sample.rtf +0 -68
  42. data/spec/fixtures/test.dng +0 -0
  43. data/spec/fixtures/test.doc +0 -0
  44. data/spec/fixtures/test.docx +0 -0
  45. data/spec/fixtures/test.pdf +0 -0
  46. data/spec/fixtures/test.pptx +0 -0
  47. data/spec/fixtures/test.tif +0 -0
  48. data/spec/fixtures/test.xls +0 -0
  49. data/spec/fixtures/test.xlsx +0 -0
  50. data/spec/fixtures/world.png +0 -0
  51. data/spec/processors/active_encode_spec.rb +0 -132
  52. data/spec/processors/document_spec.rb +0 -41
  53. data/spec/processors/full_text_spec.rb +0 -70
  54. data/spec/processors/image_spec.rb +0 -122
  55. data/spec/processors/jpeg2k_spec.rb +0 -82
  56. data/spec/processors/processor_spec.rb +0 -35
  57. data/spec/processors/shell_based_processor_spec.rb +0 -19
  58. data/spec/processors/video_spec.rb +0 -40
  59. data/spec/runners/active_encode_derivatives_spec.rb +0 -38
  60. data/spec/services/audio_derivatives_spec.rb +0 -78
  61. data/spec/services/persist_basic_contained_output_file_service_spec.rb +0 -40
  62. data/spec/services/persist_external_file_output_file_service_spec.rb +0 -26
  63. data/spec/services/remote_source_file_spec.rb +0 -33
  64. data/spec/services/retrieve_source_file_service_spec.rb +0 -60
  65. data/spec/services/tempfile_service_spec.rb +0 -30
  66. data/spec/spec_helper.rb +0 -33
  67. data/spec/units/audio_encoder_spec.rb +0 -23
  68. data/spec/units/config_spec.rb +0 -50
  69. data/spec/units/derivatives_spec.rb +0 -62
  70. data/spec/units/io_decorator_spec.rb +0 -33
  71. data/spec/units/logger_spec.rb +0 -22
  72. data/spec/units/transcoding_spec.rb +0 -346
@@ -1,82 +0,0 @@
1
- require 'spec_helper'
2
- require 'yaml'
3
-
4
- describe Hydra::Derivatives::Processors::Jpeg2kImage do
5
- let(:object) { ActiveFedora::Base.new }
6
- let(:filename) { File.expand_path('../../fixtures/test.tif', __FILE__) }
7
- let(:image) { MiniMagick::Image.open(filename) }
8
-
9
- describe "#calculate_recipe" do
10
- it "calculates the number of levels from a size" do
11
- dim = 7200
12
- expect(described_class.level_count_for_size(dim)).to eq(6)
13
- end
14
-
15
- it "calculates the compression rates for each quality layer" do
16
- compression_num = 10
17
- layers = 8
18
- calc = described_class.layer_rates(layers, compression_num)
19
- expect(calc).to eq("2.4,1.48331273,0.91675694,0.56659885,0.3501847,0.21643059,0.13376427,0.0826726")
20
- end
21
- end
22
-
23
- describe ".srgb_profile_path" do
24
- it "exists" do
25
- expect(File.exist?(described_class.srgb_profile_path)).to eq true
26
- end
27
- end
28
-
29
- describe "#kdu_compress_recipe" do
30
- before(:all) do
31
- @sample_cfg = YAML.load_file(File.expand_path('../../fixtures/jpeg2k_config.yml', __FILE__))['test']
32
- Hydra::Derivatives.kdu_compress_recipes = @sample_cfg['jp2_recipes']
33
- end
34
- after(:all) do
35
- Hydra::Derivatives.reset_config!
36
- end
37
-
38
- it "can get the recipe from a config file" do
39
- args = { recipe: :myrecipe }
40
- r = described_class.kdu_compress_recipe(args, 'grey', 7200)
41
- expect(r).to eq(@sample_cfg['jp2_recipes'][:myrecipe_grey])
42
- end
43
-
44
- it "can take a recipe as a string" do
45
- args = { recipe: '-my -excellent -recipe' }
46
- r = described_class.kdu_compress_recipe(args, 'grey', 7200)
47
- expect(r).to eq(args[:recipe])
48
- end
49
-
50
- it "will fall back to a #calculate_recipe if a symbol is passed but no recipe is found" do
51
- args = { recipe: :x }
52
- r = described_class.kdu_compress_recipe(args, 'grey', 7200)
53
- expect(r).to eq(described_class.calculate_recipe(args, 'grey', 7200))
54
- end
55
-
56
- it "will fall back to a #calculate_recipe if there is no attempt to provide one" do
57
- args = {}
58
- r = described_class.kdu_compress_recipe(args, 'grey', 7200)
59
- expect(r).to eq(described_class.calculate_recipe(args, 'grey', 7200))
60
- end
61
- end
62
-
63
- describe "#encode" do
64
- it "executes the external utility" do
65
- expect(described_class).to receive(:execute) { 0 }
66
- described_class.encode('infile', 'recipe', 'outfile')
67
- end
68
- end
69
-
70
- describe "#tmp_file" do
71
- it "returns a temp file with the correct extension" do
72
- f = described_class.tmp_file('.test')
73
- expect(f).to end_with('.test')
74
- end
75
- end
76
-
77
- describe "long_dim" do
78
- it "returns the image's largest dimension" do
79
- expect(described_class.long_dim(image)).to eq(386)
80
- end
81
- end
82
- end
@@ -1,35 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hydra::Derivatives::Processors::Processor do
4
- let(:object) { "Fake Object" }
5
- let(:source_name) { 'content' }
6
- let(:directives) { { thumb: "100x100>" } }
7
- let(:file_path) { double }
8
-
9
- subject { described_class.new(file_path, directives) }
10
-
11
- describe "output_file_service" do
12
- let(:custom_output_file_service) { "fake service" }
13
- let(:another_custom_output_file_service) { "another fake service" }
14
-
15
- context "as a global configuration setting" do
16
- before do
17
- allow(Hydra::Derivatives).to receive(:output_file_service).and_return(custom_output_file_service)
18
- end
19
- it "utilizes the default output file service" do
20
- expect(subject.output_file_service).to eq(custom_output_file_service)
21
- end
22
- end
23
-
24
- context "as an instance level configuration setting" do
25
- subject do
26
- described_class.new('/opt/derivatives/foo.mp4', directives,
27
- output_file_service: another_custom_output_file_service)
28
- end
29
-
30
- it "accepts a custom output file service as an option" do
31
- expect(subject.output_file_service).to eq(another_custom_output_file_service)
32
- end
33
- end
34
- end
35
- end
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hydra::Derivatives::Processors::ShellBasedProcessor do
4
- before do
5
- class TestProcessor
6
- include Hydra::Derivatives::Processors::ShellBasedProcessor
7
- end
8
- end
9
-
10
- after { Object.send(:remove_const, :TestProcessor) }
11
-
12
- let(:processor) { TestProcessor.new }
13
-
14
- describe "options_for" do
15
- it "returns a hash" do
16
- expect(processor.options_for("a")).to be_a Hash
17
- end
18
- end
19
- end
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hydra::Derivatives::Processors::Video::Processor do
4
- let(:file_name) { 'foo/bar.mov' }
5
- subject { described_class.new(file_name, directives) }
6
-
7
- describe ".config" do
8
- before do
9
- @original_config = described_class.config.dup
10
- described_class.config.mpeg4.codec = "-vcodec mpeg4 -acodec aac -strict -2"
11
- end
12
-
13
- after { described_class.config = @original_config }
14
- let(:directives) { { label: :thumb, format: "mp4", url: 'http://localhost:8983/fedora/rest/dev/1234/thumbnail' } }
15
-
16
- it "is configurable" do
17
- expect(subject).to receive(:encode_file).with("mp4", Hydra::Derivatives::Processors::Ffmpeg::OUTPUT_OPTIONS => "-s 320x240 -vcodec mpeg4 -acodec aac -strict -2 -g 30 -b:v 345k -ac 2 -ab 96k -ar 44100", Hydra::Derivatives::Processors::Ffmpeg::INPUT_OPTIONS => "")
18
- subject.process
19
- end
20
- end
21
-
22
- context "when arguments are passed as a hash" do
23
- context "and a video format is requested" do
24
- let(:directives) { { label: :thumb, format: 'webm', url: 'http://localhost:8983/fedora/rest/dev/1234/thumbnail' } }
25
-
26
- it "creates a fedora resource and infers the name" do
27
- expect(subject).to receive(:encode_file).with("webm", Hydra::Derivatives::Processors::Ffmpeg::OUTPUT_OPTIONS => "-s 320x240 -vcodec libvpx -acodec libvorbis -g 30 -b:v 345k -ac 2 -ab 96k -ar 44100", Hydra::Derivatives::Processors::Ffmpeg::INPUT_OPTIONS => "")
28
- subject.process
29
- end
30
- end
31
-
32
- context "and jpg is requested" do
33
- let(:directives) { { label: :thumb, format: 'jpg', url: 'http://localhost:8983/fedora/rest/dev/1234/thumbnail' } }
34
- it "creates a fedora resource and infers the name" do
35
- expect(subject).to receive(:encode_file).with("jpg", output_options: "-s 320x240 -vcodec mjpeg -vframes 1 -an -f rawvideo", input_options: " -itsoffset -2")
36
- subject.process
37
- end
38
- end
39
- end
40
- end
@@ -1,38 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hydra::Derivatives::ActiveEncodeDerivatives do
4
- context '.create' do
5
- before do
6
- class TestVideo < ActiveFedora::Base
7
- attr_accessor :remote_file_name
8
- end
9
- end
10
-
11
- after { Object.send(:remove_const, :TestVideo) }
12
-
13
- let(:file_path) { 'some/path/to/my_video.mp4' }
14
- let(:video_record) { TestVideo.new(remote_file_name: file_path) }
15
- let(:options) { { source: :remote_file_name, outputs: [low_res_video] } }
16
- let(:low_res_video) { { some_key: 'some options to pass to my encoder service' } }
17
- let(:processor) { double('processor') }
18
-
19
- it 'calls the processor with the right arguments' do
20
- expect(Hydra::Derivatives::Processors::ActiveEncode).to receive(:new).with(file_path, low_res_video, output_file_service: Hydra::Derivatives::PersistExternalFileOutputFileService).and_return(processor)
21
- expect(processor).to receive(:process)
22
- described_class.create(video_record, options)
23
- end
24
-
25
- context 'with a custom encode class' do
26
- before { class TestEncode < ::ActiveEncode::Base; end }
27
- after { Object.send(:remove_const, :TestEncode) }
28
-
29
- let(:options) { { encode_class: TestEncode, source: :remote_file_name, outputs: [low_res_video] } }
30
-
31
- it 'calls the processor with the right arguments' do
32
- expect(Hydra::Derivatives::Processors::ActiveEncode).to receive(:new).with(file_path, low_res_video, output_file_service: Hydra::Derivatives::PersistExternalFileOutputFileService, encode_class: TestEncode).and_return(processor)
33
- expect(processor).to receive(:process)
34
- described_class.create(video_record, options)
35
- end
36
- end
37
- end
38
- end
@@ -1,78 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hydra::Derivatives::AudioDerivatives do
4
- describe ".create" do
5
- let(:filename) { 'spec/fixtures/piano_note.wav' }
6
- let(:af_path) { ActiveFedora.fedora.host + ActiveFedora.fedora.base_path }
7
-
8
- context "with a filename", requires_ffmpeg: true do
9
- before do
10
- class LocalFileService
11
- def self.call(file_name, _options, &_block)
12
- yield File.open(file_name)
13
- end
14
- end
15
- described_class.source_file_service = LocalFileService
16
- end
17
-
18
- after do
19
- # restore the default
20
- described_class.source_file_service = Hydra::Derivatives::RetrieveSourceFileService
21
- Object.send(:remove_const, :LocalFileService)
22
- end
23
-
24
- it "creates derivatives" do
25
- described_class.create(filename,
26
- outputs: [{ label: 'mp3', format: 'mp3', url: "#{af_path}/1234/mp3" },
27
- { label: 'ogg', format: 'ogg', url: "#{af_path}/1234/ogg" }])
28
- end
29
- end
30
-
31
- context "with an object" do
32
- let(:object) { "Fake Object" }
33
- let(:source_name) { :content }
34
- let(:file) { double("the file") }
35
-
36
- before do
37
- allow(object).to receive(:original_file).and_return(file)
38
- allow(Hydra::Derivatives::TempfileService).to receive(:create).with(file)
39
- end
40
-
41
- it "creates derivatives" do
42
- described_class.create(object,
43
- source: :original_file,
44
- outputs: [{ label: 'mp3', format: 'mp3' },
45
- { label: 'ogg', format: 'ogg' }])
46
- end
47
- end
48
- end
49
-
50
- describe "source_file" do
51
- subject { described_class }
52
-
53
- it "relies on the source_file_service" do
54
- expect(subject.source_file_service).to receive(:call).with('foo/bar.aiff', baz: true)
55
- subject.source_file('foo/bar.aiff', baz: true)
56
- end
57
- end
58
-
59
- describe "output_file_service" do
60
- before do
61
- class FakeOutputService
62
- end
63
- Hydra::Derivatives.output_file_service = FakeOutputService
64
- end
65
-
66
- after do
67
- # restore the default
68
- Hydra::Derivatives.output_file_service = Hydra::Derivatives::PersistBasicContainedOutputFileService
69
- Object.send(:remove_const, :FakeOutputService)
70
- end
71
-
72
- subject { described_class.output_file_service }
73
-
74
- it "defaults to the value set on Hydra::Derivatives" do
75
- expect(subject).to eq FakeOutputService
76
- end
77
- end
78
- end
@@ -1,40 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hydra::Derivatives::PersistBasicContainedOutputFileService do
4
- before(:all) do
5
- class BasicContainerObject < ActiveFedora::Base
6
- has_subresource "the_derivative_name"
7
- end
8
- end
9
-
10
- let(:object) { BasicContainerObject.new }
11
- let(:file_path) { File.join(fixture_path, 'test.tif') }
12
- let(:file) { File.new(file_path) }
13
- let(:destination_name) { 'the_derivative_name' }
14
-
15
- # alas, we have to support this as the default because all legacy code (and fedora 3 systems) created basic contained files
16
- # The new signature does not have a destination_name option. There is a default string that will get applied, but his might
17
- # not be sufficient.
18
- context "when file is basic contained (default assumption)" do
19
- let(:object) { BasicContainerObject.create }
20
- let(:content) { StringIO.new("fake file content") }
21
- let(:resource) { object.public_send(destination_name.to_sym) }
22
- context "and the content is a stream" do
23
- it "persists the file to the specified destination on the given object" do
24
- described_class.call(content, format: 'jpg', url: "#{object.uri}/the_derivative_name")
25
- expect(resource.content).to start_with("fake file content")
26
- expect(resource.content_changed?).to eq false
27
- expect(resource.mime_type).to eq 'image/jpeg'
28
- end
29
- end
30
-
31
- context "and content is a string" do
32
- let(:content) { "fake file content - ÅÄÖ" }
33
- it "persists the file to the specified destination on the given object" do
34
- described_class.call(content, format: 'txt', url: "#{object.uri}/the_derivative_name")
35
- expect(resource.content).to eq("fake file content - ÅÄÖ")
36
- expect(resource.mime_type).to eq 'text/plain;charset=UTF-8'
37
- end
38
- end
39
- end
40
- end
@@ -1,26 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hydra::Derivatives::PersistExternalFileOutputFileService do
4
- before do
5
- class ExternalDerivativeContainerObject < ActiveFedora::Base
6
- has_subresource "external_derivative"
7
- end
8
- end
9
- after do
10
- Object.send(:remove_const, :ExternalDerivativeContainerObject)
11
- end
12
-
13
- let(:object) { ExternalDerivativeContainerObject.create }
14
- let(:directives) { { url: "#{object.uri}/external_derivative" } }
15
- let(:external_url) { 'http://www.example.com/external/content' }
16
- let(:output) { { url: external_url } }
17
- let(:destination_name) { 'external_derivative' }
18
-
19
- describe '.call' do
20
- it "persists the external file to the specified destination on the given object" do
21
- described_class.call(output, directives)
22
- expect(object.send(destination_name.to_sym).mime_type).to eq "message/external-body;access-type=URL;url=\"http://www.example.com/external/content\""
23
- expect(object.send(destination_name.to_sym).content).to eq ''
24
- end
25
- end
26
- end
@@ -1,33 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class TestObject < ActiveFedora::Base
4
- attr_accessor :source_file_name
5
- end
6
-
7
- describe Hydra::Derivatives::RemoteSourceFile do
8
- describe '.call' do
9
- let(:file_name) { 'my_source_file.mp4' }
10
-
11
- context 'when you pass in a String file name' do
12
- let(:input_obj) { file_name }
13
- let(:options) { Hash.new }
14
-
15
- it 'it yields the file name' do
16
- expect do |blk|
17
- described_class.call(input_obj, options, &blk)
18
- end.to yield_with_args(file_name)
19
- end
20
- end
21
-
22
- context 'when you pass in an ActiveFedora::Base object ' do
23
- let(:input_obj) { TestObject.new(source_file_name: file_name) }
24
- let(:options) { { source: :source_file_name } }
25
-
26
- it 'it yields the file name' do
27
- expect do |blk|
28
- described_class.call(input_obj, options, &blk)
29
- end.to yield_with_args(file_name)
30
- end
31
- end
32
- end
33
- end
@@ -1,60 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Hydra::Derivatives::RetrieveSourceFileService do
4
- before(:all) do
5
- # Need a class that:
6
- # 1) Allows you to set .uri= (to work with directly_contains)
7
- # 2) has a metadata_node (to work with directly_contains_one)
8
- class FileWithMetadata < ActiveFedora::File
9
- include ActiveFedora::WithMetadata
10
- end
11
-
12
- class ObjectWithBasicContainer < ActiveFedora::Base
13
- has_subresource "contained_file"
14
- end
15
-
16
- class DirectContainerObject < ActiveFedora::Base
17
- directly_contains :files, has_member_relation: ::RDF::URI("http://pcdm.org/use#hasFile"),
18
- class_name: "FileWithMetadata"
19
- directly_contains_one :directly_contained_file, through: :files, type: ::RDF::URI("http://pcdm.org/use#OriginalFile")
20
- end
21
- end
22
-
23
- context "when file is in basic container (default assumption)" do # alas, we have to support this as the default because all legacy code (and fedora 3 systems) created indirectly contained files
24
- let(:object) { ObjectWithBasicContainer.new }
25
- let(:content) { "fake file content (basic container)" }
26
- let(:source_name) { 'contained_file' }
27
-
28
- before do
29
- allow(object).to receive(:uri).and_return('http://foo/bar')
30
- allow(object.contained_file).to receive(:new_record?).and_return(false)
31
- allow(object.contained_file).to receive(:has_content?).and_return(true)
32
- allow(object.contained_file).to receive(:mime_type).and_return('text/html')
33
- # attaches the file as an indirectly contained object
34
- object.contained_file.content = content
35
- end
36
-
37
- it "persists the file to the specified destination on the given object" do
38
- described_class.call(object, source: source_name) do |f|
39
- expect(f.read).to eq(object.contained_file.content)
40
- end
41
- end
42
- end
43
-
44
- context "when file is directly contained" do # direct containers are more efficient, but most legacy code will have indirect containers
45
- let(:object) { DirectContainerObject.new }
46
- let(:content) { "fake file content (direct container)" }
47
- let(:source_name) { 'directly_contained_file' }
48
-
49
- before do
50
- object.save # can't build directly contained objects without saving the parent first
51
- object.build_directly_contained_file
52
- object.directly_contained_file.content = content
53
- end
54
- it "retrieves the file from the specified location on the given object" do
55
- described_class.call(object, source: source_name) do |f|
56
- expect(f.read).to eq(object.directly_contained_file.content)
57
- end
58
- end
59
- end
60
- end