hydra-works 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -22
  3. data/hydra-works.gemspec +1 -1
  4. data/lib/hydra/works.rb +10 -0
  5. data/lib/hydra/works/characterization.rb +15 -17
  6. data/lib/hydra/works/{models/characterization → characterization}/fits_datastream.rb +3 -5
  7. data/lib/hydra/works/characterization/fits_mapper.rb +0 -0
  8. data/lib/hydra/works/characterization/schema/base_schema.rb +1 -5
  9. data/lib/hydra/works/characterization/schema/image_schema.rb +4 -6
  10. data/lib/hydra/works/models/concerns/file_set/virus_check.rb +4 -41
  11. data/lib/hydra/works/services/add_file_to_file_set.rb +18 -11
  12. data/lib/hydra/works/services/characterization_service.rb +24 -36
  13. data/lib/hydra/works/services/virus_checker_service.rb +73 -0
  14. data/lib/hydra/works/version.rb +1 -1
  15. data/spec/hydra/works/characterization_spec.rb +97 -0
  16. data/spec/hydra/works/models/concerns/file_set/virus_check_spec.rb +6 -64
  17. data/spec/hydra/works/services/characterization_service_spec.rb +88 -103
  18. data/spec/hydra/works/services/virus_checker_service_spec.rb +95 -0
  19. metadata +12 -12
  20. data/lib/hydra/works/models/characterization/already_there_strategy.rb +0 -12
  21. data/lib/hydra/works/models/concerns/file_set/characterization/audio.rb +0 -14
  22. data/lib/hydra/works/models/concerns/file_set/characterization/base.rb +0 -23
  23. data/lib/hydra/works/models/concerns/file_set/characterization/document.rb +0 -11
  24. data/lib/hydra/works/models/concerns/file_set/characterization/image.rb +0 -10
  25. data/lib/hydra/works/models/concerns/file_set/characterization/video.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8e1d3bbe7957645b6170f8bc00a7084fa94e670b
4
- data.tar.gz: 901fcd09d4e40f5a97114e2f070ee36dffd231d6
3
+ metadata.gz: 95116717ae44d85ac45f788033d74e18f8144df6
4
+ data.tar.gz: eef16574d1817c0c984474457676997e34af7b17
5
5
  SHA512:
6
- metadata.gz: d9b4ff1445474ab473dd55a97fa0de5d3e29a5879614ec0fea840929f959c9b8a8e6d424c1d7224b925863b8f157d20d8cebcce4bdf1abc1f3bb38b8f91752f2
7
- data.tar.gz: b2cbefad14f81c691c5129fe0c6e7895a6f1a6b3392bd6a129490e2556b42ff4e796836de751752068d4c5c984b675dfdee7b832c2e272649cf62d5ac7d3c01f
6
+ metadata.gz: f7fa861ac89d69f55d7e70cf19b88feb0b0a4922eaf003dc703d29a5ba3d0bcbcefeee85888414ce19ea81ca74cc8d35442b1f407e69ce64a956657f6215b7fd
7
+ data.tar.gz: 1ec0c85363b2f9eebf497bb22ea26ade58ace1508620f07762b0f6d6e4f67b979a2111ab07a7fa8dbbaa61d302f29085faee89a99a2522c04faac35e4e77f4f2
data/.rubocop.yml CHANGED
@@ -12,30 +12,9 @@ AllCops:
12
12
  Metrics/LineLength:
13
13
  Enabled: false
14
14
 
15
- Metrics/CyclomaticComplexity:
16
- Exclude:
17
- - lib/hydra/works/services/add_file_to_file_set.rb
18
-
19
- Metrics/PerceivedComplexity:
20
- Exclude:
21
- - lib/hydra/works/services/add_file_to_file_set.rb
22
-
23
- Metrics/MethodLength:
24
- Exclude:
25
- - lib/hydra/works/services/add_file_to_file_set.rb
26
- - lib/hydra/works/models/concerns/file_set/virus_check.rb
27
- - lib/hydra/works/models/characterization/fits_datastream.rb
28
-
29
15
  Metrics/ClassLength:
30
16
  Exclude:
31
- - lib/hydra/works/models/characterization/fits_datastream.rb
32
-
33
- Metrics/AbcSize:
34
- Exclude:
35
- - lib/hydra/works/services/add_file_to_file_set.rb
36
- - lib/hydra/works/services/full_text_extraction_service.rb
37
- - lib/hydra/works/models/concerns/file_set/mime_types.rb
38
- - lib/hydra/works/models/concerns/file_set/virus_check.rb
17
+ - lib/hydra/works/characterization/fits_datastream.rb
39
18
 
40
19
  Style/CollectionMethods:
41
20
  PreferredMethods:
data/hydra-works.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency 'hydra-pcdm', '>= 0.6'
21
+ spec.add_dependency 'hydra-pcdm', '>= 0.8'
22
22
  spec.add_dependency 'hydra-derivatives', '~> 3.0'
23
23
  spec.add_dependency 'hydra-file_characterization', '~> 0.3', '>= 0.3.3'
24
24
 
data/lib/hydra/works.rb CHANGED
@@ -38,10 +38,20 @@ module Hydra
38
38
  end
39
39
 
40
40
  autoload_under 'services' do
41
+ autoload :VirusCheckerService
41
42
  autoload :AddFileToFileSet
42
43
  autoload :UploadFileToFileSet
43
44
  autoload :PersistDerivative
44
45
  autoload :CharacterizationService
45
46
  end
47
+
48
+ ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas +=
49
+ [
50
+ Characterization::AudioSchema,
51
+ Characterization::BaseSchema,
52
+ Characterization::DocumentSchema,
53
+ Characterization::ImageSchema,
54
+ Characterization::VideoSchema
55
+ ]
46
56
  end
47
57
  end
@@ -1,10 +1,22 @@
1
1
  module Hydra::Works
2
2
  module Characterization
3
- extend ActiveSupport::Concern
4
3
  extend ActiveSupport::Autoload
5
4
 
6
- autoload :FitsDatastream, 'hydra/works/models/characterization/fits_datastream.rb'
7
- autoload :AlreadyThereStrategy, 'hydra/works/models/characterization/already_there_strategy.rb'
5
+ class << self
6
+ attr_accessor :mapper
7
+ def mapper
8
+ @mapper ||= mapper_defaults
9
+ end
10
+
11
+ def mapper_defaults
12
+ { audio_duration: :duration, audio_sample_rate: :sample_rate, exif_tool_version: :exif_version,
13
+ file_author: :creator, file_language: :language, file_mime_type: :has_mime_type,
14
+ video_audio_sample_rate: :sample_rate, video_duration: :duration, video_height: :height,
15
+ video_sample_rate: :sample_rate, video_width: :width }
16
+ end
17
+ end
18
+
19
+ autoload :FitsDatastream, 'hydra/works/characterization/fits_datastream.rb'
8
20
 
9
21
  autoload_under 'schema' do
10
22
  autoload :AudioSchema
@@ -13,19 +25,5 @@ module Hydra::Works
13
25
  autoload :ImageSchema
14
26
  autoload :VideoSchema
15
27
  end
16
-
17
- autoload :Base, 'hydra/works/models/concerns/file_set/characterization/base.rb'
18
- autoload :Image, 'hydra/works/models/concerns/file_set/characterization/image.rb'
19
- autoload :Document, 'hydra/works/models/concerns/file_set/characterization/document.rb'
20
- autoload :Video, 'hydra/works/models/concerns/file_set/characterization/video.rb'
21
- autoload :Audio, 'hydra/works/models/concerns/file_set/characterization/audio.rb'
22
-
23
- included do
24
- include Base
25
- include Image
26
- include Audio
27
- include Video
28
- include Document
29
- end
30
28
  end
31
29
  end
@@ -148,11 +148,9 @@ module Hydra::Works::Characterization
148
148
  builder = Nokogiri::XML::Builder.new do |xml|
149
149
  xml.fits(xmlns: 'http://hul.harvard.edu/ois/xml/ns/fits/fits_output',
150
150
  'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
151
- 'xsi:schemaLocation' =>
152
- "http://hul.harvard.edu/ois/xml/ns/fits/fits_output
153
- http://hul.harvard.edu/ois/xml/xsd/fits/fits_output.xsd",
154
- version: '0.6.0',
155
- timestamp: '1/25/12 11:04 AM') do
151
+ 'xsi:schemaLocation' => "http://hul.harvard.edu/ois/xml/ns/fits/fits_output
152
+ http://hul.harvard.edu/ois/xml/xsd/fits/fits_output.xsd",
153
+ version: '0.6.0', timestamp: '1/25/12 11:04 AM') do
156
154
  xml.identification { xml.identity(toolname: 'FITS') }
157
155
  end
158
156
  end
File without changes
@@ -1,17 +1,13 @@
1
1
  module Hydra::Works::Characterization
2
2
  class BaseSchema < ActiveTriples::Schema
3
- property :filename, predicate: RDF::Vocab::EBUCore.filename, multiple: false
4
3
  property :format_label, predicate: RDF::Vocab::PREMIS.hasFormatName
5
4
  property :file_size, predicate: RDF::Vocab::EBUCore.fileSize
6
5
  property :well_formed, predicate: RDF::URI.new("http://projecthydra.org/ns/fits/wellFormed")
7
6
  property :valid, predicate: RDF::URI.new("http://projecthydra.org/ns/fits/valid")
8
7
  property :date_created, predicate: RDF::Vocab::EBUCore.dateCreated
9
- property :last_modified, predicate: RDF::Vocab::EBUCore.dateModified
10
8
  property :fits_version, predicate: RDF::Vocab::PREMIS.hasCreatingApplicationVersion
11
9
  property :exif_version, predicate: RDF::Vocab::EXIF.exifVersion
12
10
  property :original_checksum, predicate: RDF::Vocab::NFO.hashValue
13
- property :mime_type, predicate: RDF::Vocab::EBUCore.hasMimeType, multiple: false do |index|
14
- index.as :stored_searchable
15
- end
11
+ property :mime_type, predicate: RDF::Vocab::EBUCore.hasMimeType
16
12
  end
17
13
  end
@@ -1,15 +1,13 @@
1
1
  module Hydra::Works::Characterization
2
2
  class ImageSchema < ActiveTriples::Schema
3
- property :byte_order, predicate: RDF::URI('http://sweet.jpl.nasa.gov/2.2/reprDataFormat.owl#byteOrder'), multiple: false
4
- property :compression, predicate: RDF::URI('http://projecthydra.org/ns/mix/compressionScheme'), multiple: false
3
+ property :byte_order, predicate: RDF::URI('http://sweet.jpl.nasa.gov/2.2/reprDataFormat.owl#byteOrder')
4
+ property :compression, predicate: RDF::URI('http://projecthydra.org/ns/mix/compressionScheme')
5
5
  property :height, predicate: RDF::Vocab::EBUCore.height
6
6
  property :width, predicate: RDF::Vocab::EBUCore.width
7
- # property :width, predicate: RDF::Vocab::EXIF.imageWidth, multiple: false
8
- # property :height, predicate: RDF::Vocab::EXIF.imageLength, multiple: false
9
- property :color_space, predicate: RDF::Vocab::EXIF.colorSpace, multiple: false
7
+ property :color_space, predicate: RDF::Vocab::EXIF.colorSpace
10
8
  property :profile_name, predicate: RDF::URI('http://projecthydra.org/ns/mix/colorProfileName')
11
9
  property :profile_version, predicate: RDF::URI('http://projecthydra.org/ns/mix/colorProfileVersion')
12
- property :orientation, predicate: RDF::Vocab::EXIF.orientation, multiple: false
10
+ property :orientation, predicate: RDF::Vocab::EXIF.orientation
13
11
  property :color_map, predicate: RDF::URI('http://projecthydra.org/ns/mix/colorMap')
14
12
  property :image_producer, predicate: RDF::Vocab::MARCRelators.pht
15
13
  property :capture_device, predicate: RDF::Vocab::EXIF.model
@@ -4,49 +4,12 @@ module Hydra::Works
4
4
 
5
5
  included do
6
6
  validate :detect_viruses
7
- end
8
-
9
- # Default behavior is to raise a validation error and halt the save if a virus is found
10
- def detect_viruses
11
- return unless original_file && original_file.new_record?
12
-
13
- path = original_file.is_a?(String) ? original_file : local_path_for_file(original_file)
14
- unless defined?(ClamAV)
15
- warning "Virus checking disabled, #{path} not checked"
16
- return
17
- end
18
-
19
- scan_result = ClamAV.instance.scanfile(path)
20
- if scan_result == 0
21
- true
22
- else
23
- virus_message = "A virus was found in #{path}: #{scan_result}"
24
- warning(virus_message)
25
- errors.add(:base, virus_message)
7
+ def detect_viruses
8
+ return true unless original_file && original_file.new_record? # We have a new file to check
9
+ return true unless VirusCheckerService.file_has_virus?(original_file)
10
+ errors.add(:base, "Failed to verify uploaded file is not a virus")
26
11
  false
27
12
  end
28
13
  end
29
-
30
- private
31
-
32
- def warning(msg)
33
- ActiveFedora::Base.logger.warn msg if ActiveFedora::Base.logger
34
- end
35
-
36
- # Returns a path for reading the content of +file+
37
- # @param [File] file object to retrieve a path for
38
- def local_path_for_file(file)
39
- if file.respond_to?(:path)
40
- file.path
41
- else
42
- Tempfile.open('') do |t|
43
- t.binmode
44
- t.write(file.content.read)
45
- file.content.rewind
46
- t.close
47
- t.path
48
- end
49
- end
50
- end
51
14
  end
52
15
  end
@@ -80,18 +80,25 @@ module Hydra::Works
80
80
  # @param [true, false] update_existing when true, try to retrieve existing element before building one
81
81
  def find_or_create_file(type, update_existing)
82
82
  if type.instance_of? Symbol
83
- association = file_set.association(type)
84
- fail ArgumentError, "you're attempting to add a file to a file_set using '#{type}' association but the file_set does not have an association called '#{type}''" unless association
85
-
86
- current_file = association.reader if update_existing
87
- current_file || association.build
83
+ find_or_create_file_for_symbol(type, update_existing)
88
84
  else
89
- current_file = file_set.filter_files_by_type(type_to_uri(type)).first if update_existing
90
- unless current_file
91
- file_set.files.build
92
- current_file = file_set.files.last
93
- Hydra::PCDM::AddTypeToFile.call(current_file, type_to_uri(type))
94
- end
85
+ find_or_create_file_for_rdf_uri(type, update_existing)
86
+ end
87
+ end
88
+
89
+ def find_or_create_file_for_symbol(type, update_existing)
90
+ association = file_set.association(type)
91
+ fail ArgumentError, "you're attempting to add a file to a file_set using '#{type}' association but the file_set does not have an association called '#{type}''" unless association
92
+ current_file = association.reader if update_existing
93
+ current_file || association.build
94
+ end
95
+
96
+ def find_or_create_file_for_rdf_uri(type, update_existing)
97
+ current_file = file_set.filter_files_by_type(type_to_uri(type)).first if update_existing
98
+ unless current_file
99
+ file_set.files.build
100
+ current_file = file_set.files.last
101
+ Hydra::PCDM::AddTypeToFile.call(current_file, type_to_uri(type))
95
102
  end
96
103
  end
97
104
 
@@ -2,20 +2,22 @@ require 'hydra-file_characterization'
2
2
 
3
3
  module Hydra::Works
4
4
  class CharacterizationService
5
- # @param [ActiveFedora::Base] object which has properties to recieve characterization values.
6
- # @param [Symbol, String, File] source for characterization to be run on. File object, path on disk, or symbol.
7
- # A symbol should be the name of the method call to get object that responds to content? or is the content.
5
+ # @param [Hydra::PCDM::File] object which has properties to recieve characterization values.
6
+ # @param [String, File] source for characterization to be run on. File object or path on disk.
7
+ # If none is provided, it will assume the binary content already present on the object.
8
8
  # @param [Hash] options to be passed to characterization. parser_mapping:, parser_class:, tools:
9
- def self.run(object, source = :original_file, options = {})
9
+ def self.run(object, source = nil, options = {})
10
10
  new(object, source, options).characterize
11
11
  end
12
12
 
13
13
  attr_accessor :object, :source, :mapping, :parser_class, :tools
14
14
 
15
15
  def initialize(object, source, options)
16
- @object = object
17
- @source = source
18
- @mapping, @parser_class, @tools = extract_options(options)
16
+ @object = object
17
+ @source = source
18
+ @mapping = options.fetch(:parser_mapping, Hydra::Works::Characterization.mapper)
19
+ @parser_class = options.fetch(:parser_class, Hydra::Works::Characterization::FitsDatastream)
20
+ @tools = options.fetch(:ch12n_tool, :fits)
19
21
  end
20
22
 
21
23
  # Get given source into form that can be passed to Hydra::FileCharacterization
@@ -31,41 +33,27 @@ module Hydra::Works
31
33
 
32
34
  protected
33
35
 
34
- # Get value from opts hash, object, or use default
35
- def extract_options(opts)
36
- parser_mapping = fetch_or_respond(opts, :parser_mapping) || {}
37
- parser_class = fetch_or_respond(opts, :parser_class) || FitsDatastream
38
- ch12n_tool = opts.fetch(:ch12n_tool) { :fits }
39
-
40
- [parser_mapping, parser_class, ch12n_tool]
41
- end
42
-
43
- def fetch_or_respond(opts, key)
44
- opts.fetch(key) { object.send(key) if object.respond_to? key }
45
- end
46
-
47
- # @param [String,Symbol,File]
48
- # @return content if source is a symbol, File if source is string
36
+ # @return content of object if source is nil; otherwise, return a File or the source
49
37
  def source_to_content
50
- if source.is_a? String
51
- File.open(source)
52
- elsif source.is_a? Symbol
53
- s = object.send(source)
54
- s.respond_to?(:content) ? s.content : s
55
- else
56
- source
57
- end
38
+ return object.content if source.nil?
39
+ return File.open(source).read if source.is_a? String
40
+ source.read
58
41
  end
59
42
 
60
43
  def extract_metadata(content)
61
- Hydra::FileCharacterization.characterize(content, temp_file_name, tools) do |cfg|
44
+ Hydra::FileCharacterization.characterize(content, file_name, tools) do |cfg|
62
45
  cfg[:fits] = Hydra::Derivatives.fits_path
63
46
  end
64
47
  end
65
48
 
66
- def temp_file_name
67
- m = %r{/([^/]*)$} .match(object.uri)
68
- "#{m[1]}-content.tmp"
49
+ # Determine the filename to send to Hydra::FileCharacterization. If no source is present,
50
+ # use the name of the file from the object; otherwise, use the supplied source.
51
+ def file_name
52
+ if source
53
+ source.is_a?(File) ? File.basename(source.path) : File.basename(source)
54
+ else
55
+ object.original_name.nil? ? "original_file" : object.original_name
56
+ end
69
57
  end
70
58
 
71
59
  # Use OM to parse metadata
@@ -111,8 +99,8 @@ module Hydra::Works
111
99
  end
112
100
 
113
101
  def append_property_value(property, value)
114
- value = object[property] + [value] if object.class.multiple?(property)
115
- object.send("#{property}=", value)
102
+ value = object.send(property) + [value]
103
+ object.send("#{property}=", value.uniq)
116
104
  end
117
105
  end
118
106
  end
@@ -0,0 +1,73 @@
1
+ module Hydra::Works
2
+ # Responsible for checking if the given file is a virus. Coordinates
3
+ # with the underlying system virus scanner.
4
+ class VirusCheckerService
5
+ attr_accessor :original_file, :system_virus_scanner
6
+
7
+ # @api public
8
+ # @param original_file [String, #path]
9
+ # @return true if a virus was detected
10
+ # @return true if anti-virus was not able to run
11
+ # @return false if the file was scanned and no viruses were found
12
+ def self.file_has_virus?(original_file)
13
+ new(original_file).file_has_virus?
14
+ end
15
+
16
+ def initialize(original_file, system_virus_scanner = default_system_virus_scanner)
17
+ self.original_file = original_file
18
+ self.system_virus_scanner = system_virus_scanner
19
+ end
20
+
21
+ # Default behavior is to raise a validation error and halt the save if a virus is found
22
+ def file_has_virus?
23
+ path = original_file.is_a?(String) ? original_file : local_path_for_file(original_file)
24
+ scan_result = system_virus_scanner.call(path)
25
+ handle_virus_scan_results(path, scan_result)
26
+ end
27
+
28
+ private
29
+
30
+ # Stubbing out the behavior of "The Clam" was growing into a rather nasty
31
+ # challenge. So instead I'm injecting a system scanner. This allows me to
32
+ # now test the default system scanner in isolation from the general response
33
+ # to a system scan.
34
+ def default_system_virus_scanner
35
+ if defined?(ClamAV)
36
+ ClamAV.instance.method(:scanfile)
37
+ else
38
+ lambda do |_path|
39
+ :no_anti_virus_was_run
40
+ end
41
+ end
42
+ end
43
+
44
+ def handle_virus_scan_results(path, scan_result)
45
+ case scan_result
46
+ when 0 then return false
47
+ when 1
48
+ warning("A virus was found in #{path}: #{scan_result}")
49
+ true
50
+ else
51
+ warning "Virus checking disabled, #{path} not checked"
52
+ true
53
+ end
54
+ end
55
+
56
+ def warning(msg)
57
+ ActiveFedora::Base.logger.warn msg if ActiveFedora::Base.logger
58
+ end
59
+
60
+ # Returns a path for reading the content of +file+
61
+ # @param [File] file object to retrieve a path for
62
+ def local_path_for_file(file)
63
+ return file.path if file.respond_to?(:path)
64
+ Tempfile.open('') do |t|
65
+ t.binmode
66
+ t.write(file.content.read)
67
+ file.content.rewind
68
+ t.close
69
+ t.path
70
+ end
71
+ end
72
+ end
73
+ end
@@ -1,5 +1,5 @@
1
1
  module Hydra
2
2
  module Works
3
- VERSION = '0.9.0'.freeze
3
+ VERSION = '0.10.0'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hydra::Works::Characterization do
4
+ let(:file) { Hydra::PCDM::File.new }
5
+
6
+ describe "properties" do
7
+ subject { file }
8
+ context "with inhereited terms from ActiveFedora" do
9
+ it { is_expected.to respond_to(:label) }
10
+ it { is_expected.to respond_to(:file_name) }
11
+ it { is_expected.to respond_to(:file_size) }
12
+ it { is_expected.to respond_to(:date_created) }
13
+ it { is_expected.to respond_to(:has_mime_type) }
14
+ it { is_expected.to respond_to(:date_modified) }
15
+ it { is_expected.to respond_to(:byte_order) }
16
+ end
17
+ context "with Base schema" do
18
+ it { is_expected.to respond_to(:format_label) }
19
+ it { is_expected.to respond_to(:file_size) }
20
+ it { is_expected.to respond_to(:well_formed) }
21
+ it { is_expected.to respond_to(:valid) }
22
+ it { is_expected.to respond_to(:date_created) }
23
+ it { is_expected.to respond_to(:fits_version) }
24
+ it { is_expected.to respond_to(:exif_version) }
25
+ it { is_expected.to respond_to(:original_checksum) }
26
+ it { is_expected.to respond_to(:mime_type) }
27
+ end
28
+ context "with Image schema" do
29
+ it { is_expected.to respond_to(:byte_order) }
30
+ it { is_expected.to respond_to(:compression) }
31
+ it { is_expected.to respond_to(:height) }
32
+ it { is_expected.to respond_to(:width) }
33
+ it { is_expected.to respond_to(:color_space) }
34
+ it { is_expected.to respond_to(:profile_name) }
35
+ it { is_expected.to respond_to(:profile_version) }
36
+ it { is_expected.to respond_to(:orientation) }
37
+ it { is_expected.to respond_to(:color_map) }
38
+ it { is_expected.to respond_to(:image_producer) }
39
+ it { is_expected.to respond_to(:capture_device) }
40
+ it { is_expected.to respond_to(:scanning_software) }
41
+ it { is_expected.to respond_to(:gps_timestamp) }
42
+ it { is_expected.to respond_to(:latitude) }
43
+ it { is_expected.to respond_to(:longitude) }
44
+ end
45
+ context "with Document schema" do
46
+ it { is_expected.to respond_to(:file_title) }
47
+ it { is_expected.to respond_to(:creator) }
48
+ it { is_expected.to respond_to(:page_count) }
49
+ it { is_expected.to respond_to(:language) }
50
+ it { is_expected.to respond_to(:word_count) }
51
+ it { is_expected.to respond_to(:character_count) }
52
+ it { is_expected.to respond_to(:line_count) }
53
+ it { is_expected.to respond_to(:character_set) }
54
+ it { is_expected.to respond_to(:markup_basis) }
55
+ it { is_expected.to respond_to(:markup_language) }
56
+ it { is_expected.to respond_to(:paragraph_count) }
57
+ it { is_expected.to respond_to(:table_count) }
58
+ it { is_expected.to respond_to(:graphics_count) }
59
+ end
60
+ context "with Video schema" do
61
+ it { is_expected.to respond_to(:height) }
62
+ it { is_expected.to respond_to(:width) }
63
+ it { is_expected.to respond_to(:frame_rate) }
64
+ it { is_expected.to respond_to(:duration) }
65
+ it { is_expected.to respond_to(:sample_rate) }
66
+ end
67
+ context "with Audio schema" do
68
+ it { is_expected.to respond_to(:bit_depth) }
69
+ it { is_expected.to respond_to(:channels) }
70
+ it { is_expected.to respond_to(:data_format) }
71
+ it { is_expected.to respond_to(:frame_rate) }
72
+ it { is_expected.to respond_to(:duration) }
73
+ it { is_expected.to respond_to(:sample_rate) }
74
+ it { is_expected.to respond_to(:offset) }
75
+ end
76
+ end
77
+
78
+ describe "::mapper" do
79
+ let(:mapper_keys) do
80
+ [
81
+ :audio_duration,
82
+ :audio_sample_rate,
83
+ :exif_tool_version,
84
+ :file_author,
85
+ :file_language,
86
+ :file_mime_type,
87
+ :video_audio_sample_rate,
88
+ :video_duration,
89
+ :video_height,
90
+ :video_sample_rate,
91
+ :video_width
92
+ ]
93
+ end
94
+ subject { described_class.mapper.keys }
95
+ it { is_expected.to eq(mapper_keys) }
96
+ end
97
+ end
@@ -2,37 +2,23 @@ require 'spec_helper'
2
2
 
3
3
  describe Hydra::Works::VirusCheck do
4
4
  context "with ClamAV" do
5
+ subject { FileWithVirusCheck.new }
6
+ let(:file) { Hydra::PCDM::File.new { |f| f.content = File.new(File.join(fixture_path, 'sample-file.pdf')) } }
7
+
5
8
  before do
6
9
  class FileWithVirusCheck < ActiveFedora::Base
7
10
  include Hydra::Works::FileSetBehavior
8
11
  include Hydra::Works::VirusCheck
9
12
  end
10
- class ClamAV
11
- def self.instance
12
- @instance ||= ClamAV.new
13
- end
14
-
15
- def scanfile(path)
16
- puts "scanfile: #{path}"
17
- end
18
- end
13
+ allow(subject).to receive(:original_file) { file }
19
14
  end
20
15
  after do
21
- Object.send(:remove_const, :ClamAV)
22
16
  Object.send(:remove_const, :FileWithVirusCheck)
23
17
  end
24
18
 
25
- subject { FileWithVirusCheck.new }
26
- let(:file) { Hydra::PCDM::File.new { |f| f.content = File.new(File.join(fixture_path, 'sample-file.pdf')) } }
27
-
28
- before do
29
- allow(subject).to receive(:original_file) { file }
30
- allow(subject).to receive(:warn) # suppress virus warning messages
31
- end
32
-
33
19
  context 'with an infected file' do
34
20
  before do
35
- expect(ClamAV.instance).to receive(:scanfile).and_return(1)
21
+ expect(Hydra::Works::VirusCheckerService).to receive(:file_has_virus?).and_return(true)
36
22
  end
37
23
  it 'fails to save' do
38
24
  expect(subject.save).to eq false
@@ -44,56 +30,12 @@ describe Hydra::Works::VirusCheck do
44
30
 
45
31
  context 'with a clean file' do
46
32
  before do
47
- expect(ClamAV.instance).to receive(:scanfile).and_return(0)
48
33
  end
49
34
 
50
35
  it 'does not detect viruses' do
51
- expect(subject.detect_viruses).to eq true
52
- end
53
- end
54
-
55
- context 'with a file that responds to :path' do
56
- before do
57
- allow(file).to receive(:path).and_return('/tmp/file.pdf')
58
- end
59
-
60
- it 'gets the filename from :path' do
61
- expect(subject.send(:local_path_for_file, file)).to eq('/tmp/file.pdf')
62
- end
63
- end
64
-
65
- context 'original file does not respond to path' do
66
- before do
67
- allow(file).to receive(:respond_to?).and_call_original
68
- allow(file).to receive(:respond_to?).with(:path).and_return(false)
69
- end
70
-
71
- it 'reads the content of the original_file' do
72
- expect(file.content).to receive(:read)
36
+ expect(Hydra::Works::VirusCheckerService).to receive(:file_has_virus?).and_return(false)
73
37
  subject.detect_viruses
74
38
  end
75
39
  end
76
40
  end
77
-
78
- context "Without ClamAV" do
79
- before do
80
- class FileWithVirusCheck < ActiveFedora::Base
81
- include Hydra::Works::FileSetBehavior
82
- include Hydra::Works::VirusCheck
83
- end
84
- Object.send(:remove_const, :ClamAV) if defined?(ClamAV)
85
- end
86
-
87
- subject { FileWithVirusCheck.new }
88
- let(:file) { Hydra::PCDM::File.new { |f| f.content = File.new(File.join(fixture_path, 'sample-file.pdf')) } }
89
-
90
- before do
91
- allow(subject).to receive(:original_file) { file }
92
- end
93
-
94
- it 'warns if ClamAV is not defined' do
95
- expect(subject).to receive(:warning) # .with("Virus checking disabled, sample-file.pdf not checked")
96
- expect(subject.detect_viruses).to eq nil
97
- end
98
- end
99
41
  end
@@ -2,37 +2,31 @@ require 'spec_helper'
2
2
  require 'support/file_set_helper'
3
3
 
4
4
  describe Hydra::Works::CharacterizationService do
5
- let(:demo_class) do
6
- Class.new(Hydra::Works::FileSet) do
7
- include Hydra::Works::Characterization
8
- end
9
- end
10
-
11
5
  describe "integration test for characterizing from path on disk." do
12
- let(:filename) { 'sample-file.pdf' }
13
- let(:path_on_disk) { File.join(fixture_path, filename) }
14
- let(:file_set) { demo_class.new(id: 'inte/gr/at/ion') }
6
+ let(:filename) { 'sample-file.pdf' }
7
+ let(:path_on_disk) { File.join(fixture_path, filename) }
8
+ let(:file) { Hydra::PCDM::File.new }
15
9
 
16
10
  before do
17
11
  skip 'external tools not installed for CI environment' if ENV['CI']
18
- described_class.run(file_set, path_on_disk)
12
+ described_class.run(file, path_on_disk)
19
13
  end
20
14
 
21
- it 'successfully sets and persists the property values' do
22
- expect(file_set.file_size).to eq(["7618"])
23
- expect(file_set.file_title).to eq(["sample-file"])
24
- expect(file_set.page_count).to eq(["1"])
15
+ it 'successfully sets the property values' do
16
+ expect(file.file_size).to eq(["7618"])
17
+ expect(file.file_title).to eq(["sample-file"])
18
+ expect(file.page_count).to eq(["1"])
25
19
  # Persist and reload from persistence layer
26
- expect(file_set.save).to be true
27
- expect(file_set.reload).to be file_set
20
+ expect(file.save).to be nil
21
+ expect(file.reload).to be nil
28
22
  # Re-check property values
29
- expect(file_set.file_size).to eq(["7618"])
30
- expect(file_set.file_title).to eq(["sample-file"])
31
- expect(file_set.page_count).to eq(["1"])
23
+ expect(file.file_size).to eq(["7618"])
24
+ expect(file.file_title).to eq(["sample-file"])
25
+ expect(file.page_count).to eq(["1"])
32
26
  end
33
27
  end
34
28
 
35
- describe "handling symbols, strings, and files as sources" do
29
+ describe "handling strings, files, and Hydra::PCDM::File as sources" do
36
30
  # Stub Hydra::FileCharacterization.characterize
37
31
  let(:characterization) { class_double("Hydra::FileCharacterization").as_stubbed_const }
38
32
  let(:fits_filename) { 'fits_0.8.5_pdf.xml' }
@@ -40,131 +34,126 @@ describe Hydra::Works::CharacterizationService do
40
34
  let(:filename) { 'sample-file.pdf' }
41
35
  let(:file_content) { IO.read(File.join(fixture_path, filename)) }
42
36
  let(:file) { Hydra::PCDM::File.new { |f| f.content = file_content } }
43
- let(:file_set) { demo_class.new(id: 'demo/ch/12/on') }
44
37
 
45
38
  before do
46
- mock_add_file_to_file_set(file_set, file)
47
39
  allow(characterization).to receive(:characterize).and_return(fits_response)
48
40
  end
49
41
 
50
- context "using default Symbol as the source." do
51
- it 'calls the corresponding method of the object.' do
52
- expect(file_set).to receive(:original_file)
53
- described_class.run(file_set)
42
+ context "with the object as the source" do
43
+ it 'calls the content method of the object.' do
44
+ expect(file).to receive(:content)
45
+ described_class.run(file)
54
46
  end
55
47
 
56
- it 'passes the content to characterization.' do
57
- expect(Hydra::FileCharacterization).to receive(:characterize).with(file_content, any_args)
58
- described_class.run(file_set)
48
+ context "when original_name is not present" do
49
+ it 'passes the content to characterization.' do
50
+ expect(Hydra::FileCharacterization).to receive(:characterize).with(file_content, "original_file", :fits)
51
+ described_class.run(file)
52
+ end
53
+ end
54
+
55
+ context "when original_name is present" do
56
+ before { allow(file).to receive(:original_name).and_return(filename) }
57
+ it 'passes the content to characterization.' do
58
+ expect(Hydra::FileCharacterization).to receive(:characterize).with(file_content, filename, :fits)
59
+ described_class.run(file)
60
+ end
59
61
  end
60
62
  end
61
63
 
62
64
  context "using a string path as the source." do
63
65
  it 'passes a file with the string as a path to FileCharacterization.' do
64
66
  path_on_disk = File.join(fixture_path, filename)
65
- expect(Hydra::FileCharacterization).to receive(:characterize).with(kind_of(File), any_args)
66
- described_class.run(file_set, path_on_disk)
67
+ expect(Hydra::FileCharacterization).to receive(:characterize).with(file_content, filename, :fits)
68
+ described_class.run(file, path_on_disk)
67
69
  end
68
70
  end
69
71
 
70
72
  context "using a File instance as the source." do
71
73
  it 'passes the File to FileCharacterization.' do
72
74
  file_inst = File.new(File.join(fixture_path, filename))
73
- expect(Hydra::FileCharacterization).to receive(:characterize).with(file_inst, any_args)
74
- described_class.run(file_set, file_inst)
75
+ expect(Hydra::FileCharacterization).to receive(:characterize).with(file_content, filename, :fits)
76
+ described_class.run(file, file_inst)
75
77
  end
76
78
  end
77
79
  end
78
80
 
79
81
  context "passing an object that does not have matching properties" do
80
- # Stub Hydra::FileCharacterization.characterize
82
+ let!(:current_schemas) { ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas }
83
+
81
84
  let(:characterization) { class_double("Hydra::FileCharacterization").as_stubbed_const }
82
- let(:bland_class) do
83
- Class.new(Hydra::Works::FileSet) { include Hydra::Works::Characterization }
84
- end
85
- let(:fits_filename) { 'fits_0.8.5_pdf.xml' }
86
- let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
87
- let(:file_content) { 'dummy content' }
88
- let(:file) { Hydra::PCDM::File.new { |f| f.content = file_content } }
89
- let(:file_set) { bland_class.new(id: 'base/ch/12/on') }
85
+ let(:fits_filename) { 'fits_0.8.5_pdf.xml' }
86
+ let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
87
+ let(:file_content) { 'dummy content' }
88
+ let(:file) { Hydra::PCDM::File.new { |f| f.content = file_content } }
90
89
 
91
90
  before do
92
- mock_add_file_to_file_set(file_set, file)
91
+ ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas = [ActiveFedora::WithMetadata::DefaultSchema]
93
92
  allow(characterization).to receive(:characterize).and_return(fits_response)
94
93
  end
94
+ after do
95
+ ActiveFedora::WithMetadata::DefaultMetadataClassFactory.file_metadata_schemas = [current_schemas]
96
+ end
95
97
 
96
98
  it 'does not explode with an error' do
97
- expect { described_class.run(file_set) }.not_to raise_error
99
+ expect { described_class.run(file) }.not_to raise_error
98
100
  end
99
101
  end
100
102
 
101
103
  describe 'assigned properties.' do
102
104
  # Stub Hydra::FileCharacterization.characterize
103
105
  let(:characterization) { class_double("Hydra::FileCharacterization").as_stubbed_const }
104
- let(:file) { Hydra::PCDM::File.new }
105
- let(:file_set) { demo_class.new(id: 'prop/er/ti/es') }
106
+ let(:file) { Hydra::PCDM::File.new }
106
107
 
107
108
  before do
108
- mock_add_file_to_file_set(file_set, file)
109
+ allow(file).to receive(:content).and_return("mocked content")
110
+ allow(characterization).to receive(:characterize).and_return(fits_response)
111
+ described_class.run(file)
109
112
  end
110
113
 
111
114
  context 'using document metadata' do
112
- let(:fits_filename) { 'fits_0.8.5_pdf.xml' }
113
- let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
114
-
115
- before do
116
- allow(characterization).to receive(:characterize).and_return(fits_response)
117
- described_class.run(file_set)
118
- end
115
+ let(:fits_filename) { 'fits_0.8.5_pdf.xml' }
116
+ let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
119
117
 
120
118
  it 'assigns expected values to document properties.' do
121
- expect(file_set.file_title).to eq(["sample-file"])
122
- expect(file_set.page_count).to eq(["1"])
119
+ expect(file.file_title).to eq(["sample-file"])
120
+ expect(file.page_count).to eq(["1"])
123
121
  end
124
122
  end
125
123
 
126
124
  context 'using image metadata' do
127
- let(:fits_filename) { 'fits_0.8.5_jp2.xml' }
128
- let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
129
- before do
130
- allow(characterization).to receive(:characterize).and_return(fits_response)
131
- described_class.run(file_set)
132
- end
125
+ let(:fits_filename) { 'fits_0.8.5_jp2.xml' }
126
+ let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
127
+
133
128
  it 'assigns expected values to image properties.' do
134
- expect(file_set.file_size).to eq(["11043"])
135
- expect(file_set.byte_order).to eq("big endian")
136
- expect(file_set.compression).to eq("JPEG 2000")
137
- expect(file_set.width).to eq(["512"])
138
- expect(file_set.height).to eq(["465"])
139
- expect(file_set.color_space).to eq("sRGB")
129
+ expect(file.file_size).to eq(["11043"])
130
+ expect(file.byte_order).to eq(["big endian"])
131
+ expect(file.compression).to eq(["JPEG 2000 Lossless", "JPEG 2000"])
132
+ expect(file.width).to eq(["512"])
133
+ expect(file.height).to eq(["465"])
134
+ expect(file.color_space).to eq(["sRGB"])
140
135
  end
141
136
  end
142
137
  context 'using video metadata' do
143
- let(:fits_filename) { 'fits_0.8.5_avi.xml' }
144
- let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
145
- before do
146
- allow(characterization).to receive(:characterize).and_return(fits_response)
147
- described_class.run(file_set)
148
- end
138
+ let(:fits_filename) { 'fits_0.8.5_avi.xml' }
139
+ let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
140
+
149
141
  it 'assigns expected values to video properties.' do
150
- expect(file_set.height).to eq(["264"])
151
- expect(file_set.width).to eq(["356"])
152
- expect(file_set.duration).to eq(["14.10 s"])
153
- expect(file_set.frame_rate).to eq(["10"])
154
- expect(file_set.sample_rate).to eq(["11025"])
142
+ expect(file.height).to eq(["264"])
143
+ expect(file.width).to eq(["356"])
144
+ expect(file.duration).to eq(["14.10 s"])
145
+ expect(file.frame_rate).to eq(["10"])
146
+ expect(file.sample_rate).to eq(["11025"])
155
147
  end
156
148
  end
157
149
  context 'using audio metadata' do
158
- let(:fits_filename) { 'fits_0.8.5_mp3.xml' }
159
- let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
160
- before do
161
- allow(characterization).to receive(:characterize).and_return(fits_response)
162
- described_class.run(file_set)
163
- end
150
+ let(:fits_filename) { 'fits_0.8.5_mp3.xml' }
151
+ let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
152
+
164
153
  it 'assigns expected values to audio properties.' do
165
- expect(file_set.mime_type).to eq("audio/mpeg")
166
- expect(file_set.duration).to eq(["0:0:15:261"])
167
- expect(file_set.sample_rate).to eq(["44100"])
154
+ expect(file.has_mime_type).to eq(["audio/mpeg"])
155
+ expect(file.duration).to eq(["0:0:15:261"])
156
+ expect(file.sample_rate).to eq(["44100"])
168
157
  end
169
158
  end
170
159
  end
@@ -172,27 +161,23 @@ describe Hydra::Works::CharacterizationService do
172
161
  describe 'assigned properties from fits 0.6.2' do
173
162
  # Stub Hydra::FileCharacterization.characterize
174
163
  let(:characterization) { class_double("Hydra::FileCharacterization").as_stubbed_const }
175
- let(:file) { Hydra::PCDM::File.new }
176
- let(:file_set) { demo_class.new(id: 'old/pr/op/es') }
177
-
178
- before do
179
- mock_add_file_to_file_set(file_set, file)
180
- end
164
+ let(:file) { Hydra::PCDM::File.new }
181
165
 
182
166
  context 'using image metadata' do
183
- let(:fits_filename) { 'fits_0.6.2_jpg.xml' }
184
- let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
167
+ let(:fits_filename) { 'fits_0.6.2_jpg.xml' }
168
+ let(:fits_response) { IO.read(File.join(fixture_path, fits_filename)) }
185
169
  before do
170
+ allow(file).to receive(:content).and_return("mocked content")
186
171
  allow(characterization).to receive(:characterize).and_return(fits_response)
187
- described_class.run(file_set)
172
+ described_class.run(file)
188
173
  end
189
174
  it 'assigns expected values to image properties.' do
190
- expect(file_set.file_size).to eq(["57639"])
191
- expect(file_set.byte_order).to eq("big endian")
192
- expect(file_set.compression).to eq("JPEG (old-style)")
193
- expect(file_set.width).to eq(["600"])
194
- expect(file_set.height).to eq(["381"])
195
- expect(file_set.color_space).to eq("YCbCr")
175
+ expect(file.file_size).to eq(["57639"])
176
+ expect(file.byte_order).to eq(["big endian"])
177
+ expect(file.compression).to eq(["JPEG (old-style)"])
178
+ expect(file.width).to eq(["600"])
179
+ expect(file.height).to eq(["381"])
180
+ expect(file.color_space).to eq(["YCbCr"])
196
181
  end
197
182
  end
198
183
  end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hydra::Works::VirusCheckerService do
4
+ let(:system_virus_scanner) { double(call: nil) }
5
+ let(:file) { Hydra::PCDM::File.new { |f| f.content = File.new(File.join(fixture_path, 'sample-file.pdf')) } }
6
+ let(:virus_checker) { described_class.new(file, system_virus_scanner) }
7
+
8
+ context '.file_has_virus?' do
9
+ it 'is a convenience method' do
10
+ mock_object = double(file_has_virus?: true)
11
+ allow(described_class).to receive(:new).and_return(mock_object)
12
+ described_class.file_has_virus?(file)
13
+ expect(mock_object).to have_received(:file_has_virus?)
14
+ end
15
+ end
16
+
17
+ context 'with a system virus scanner that did not run' do
18
+ let(:virus_checker) { described_class.new(file) }
19
+ it 'will return false and set a system warning' do
20
+ expect(defined?(ClamAV)).to eq(nil) # A bit of a sanity test to make sure the default behaves
21
+ allow(file).to receive(:path).and_return('/tmp/file.pdf')
22
+ expect(virus_checker).to receive(:warning).with(kind_of(String))
23
+ expect(virus_checker.file_has_virus?).to eq(true)
24
+ end
25
+ end
26
+
27
+ context 'with an infected file' do
28
+ context 'that responds to :path' do
29
+ it 'will return false' do
30
+ expect(system_virus_scanner).to receive(:call).with('/tmp/file.pdf').and_return(1)
31
+ allow(file).to receive(:path).and_return('/tmp/file.pdf')
32
+ expect(virus_checker.file_has_virus?).to eq(true)
33
+ end
34
+ end
35
+ context 'that does not respond to :path' do
36
+ it 'will return false' do
37
+ expect(system_virus_scanner).to receive(:call).with(kind_of(String)).and_return(1)
38
+ allow(file).to receive(:respond_to?).and_call_original
39
+ allow(file).to receive(:respond_to?).with(:path).and_return(false)
40
+ expect(virus_checker.file_has_virus?).to eq(true)
41
+ end
42
+ end
43
+ end
44
+
45
+ context 'with a clean file' do
46
+ context 'that responds to :path' do
47
+ it 'will return true' do
48
+ expect(system_virus_scanner).to receive(:call).with('/tmp/file.pdf').and_return(0)
49
+ allow(file).to receive(:path).and_return('/tmp/file.pdf')
50
+ expect(virus_checker.file_has_virus?).to eq(false)
51
+ end
52
+ end
53
+ context 'that does not respond to :path' do
54
+ it 'will return true' do
55
+ expect(system_virus_scanner).to receive(:call).with(kind_of(String)).and_return(0)
56
+ allow(file).to receive(:respond_to?).and_call_original
57
+ allow(file).to receive(:respond_to?).with(:path).and_return(false)
58
+ expect(virus_checker.file_has_virus?).to eq(false)
59
+ end
60
+ end
61
+ end
62
+
63
+ context '#default_system_virus_scanner' do
64
+ let(:virus_checker) { described_class.new(file) }
65
+ let(:system_virus_scanner) { virus_checker.send(:default_system_virus_scanner) }
66
+ it 'is callable' do
67
+ expect(system_virus_scanner).to respond_to(:call)
68
+ end
69
+ context 'when called and ClamAV is NOT defined' do
70
+ it 'will warn and return :no_anti_virus_was_run if ClamAV is not defined' do
71
+ expect(system_virus_scanner.call('/tmp/path')).to eq(:no_anti_virus_was_run)
72
+ end
73
+ end
74
+ context 'when called and ClamAV is defined' do
75
+ before do
76
+ class ClamAV
77
+ def self.instance
78
+ @instance ||= ClamAV.new
79
+ end
80
+
81
+ def scanfile(path)
82
+ puts "scanfile: #{path}"
83
+ end
84
+ end
85
+ end
86
+ after do
87
+ Object.send(:remove_const, :ClamAV)
88
+ end
89
+ it "will call the Clam's scanfile" do
90
+ expect(ClamAV.instance).to receive(:scanfile).with('/tmp/path')
91
+ system_virus_scanner.call('/tmp/path')
92
+ end
93
+ end
94
+ end
95
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hydra-works
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-04 00:00:00.000000000 Z
11
+ date: 2016-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hydra-pcdm
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0.6'
19
+ version: '0.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0.6'
26
+ version: '0.8'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: hydra-derivatives
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -191,20 +191,15 @@ files:
191
191
  - hydra-works.gemspec
192
192
  - lib/hydra/works.rb
193
193
  - lib/hydra/works/characterization.rb
194
+ - lib/hydra/works/characterization/fits_datastream.rb
195
+ - lib/hydra/works/characterization/fits_mapper.rb
194
196
  - lib/hydra/works/characterization/schema/audio_schema.rb
195
197
  - lib/hydra/works/characterization/schema/base_schema.rb
196
198
  - lib/hydra/works/characterization/schema/document_schema.rb
197
199
  - lib/hydra/works/characterization/schema/image_schema.rb
198
200
  - lib/hydra/works/characterization/schema/video_schema.rb
199
- - lib/hydra/works/models/characterization/already_there_strategy.rb
200
- - lib/hydra/works/models/characterization/fits_datastream.rb
201
201
  - lib/hydra/works/models/collection.rb
202
202
  - lib/hydra/works/models/concerns/collection_behavior.rb
203
- - lib/hydra/works/models/concerns/file_set/characterization/audio.rb
204
- - lib/hydra/works/models/concerns/file_set/characterization/base.rb
205
- - lib/hydra/works/models/concerns/file_set/characterization/document.rb
206
- - lib/hydra/works/models/concerns/file_set/characterization/image.rb
207
- - lib/hydra/works/models/concerns/file_set/characterization/video.rb
208
203
  - lib/hydra/works/models/concerns/file_set/contained_files.rb
209
204
  - lib/hydra/works/models/concerns/file_set/derivatives.rb
210
205
  - lib/hydra/works/models/concerns/file_set/mime_types.rb
@@ -220,6 +215,7 @@ files:
220
215
  - lib/hydra/works/services/characterization_service.rb
221
216
  - lib/hydra/works/services/persist_derivative.rb
222
217
  - lib/hydra/works/services/upload_file_to_file_set.rb
218
+ - lib/hydra/works/services/virus_checker_service.rb
223
219
  - lib/hydra/works/version.rb
224
220
  - lib/hydra/works/vocab/works_terms.rb
225
221
  - solr/config/_rest_managed.json
@@ -259,6 +255,7 @@ files:
259
255
  - spec/fixtures/test5.mp3
260
256
  - spec/fixtures/updated-file.txt
261
257
  - spec/fixtures/world.png
258
+ - spec/hydra/works/characterization_spec.rb
262
259
  - spec/hydra/works/models/characterization/fits_datastream_spec.rb
263
260
  - spec/hydra/works/models/collection_spec.rb
264
261
  - spec/hydra/works/models/concerns/file_set/contained_files_spec.rb
@@ -272,6 +269,7 @@ files:
272
269
  - spec/hydra/works/services/characterization_service_spec.rb
273
270
  - spec/hydra/works/services/persist_derivatives_spec.rb
274
271
  - spec/hydra/works/services/upload_file_spec.rb
272
+ - spec/hydra/works/services/virus_checker_service_spec.rb
275
273
  - spec/hydra/works_spec.rb
276
274
  - spec/spec_helper.rb
277
275
  - spec/support/file_set_helper.rb
@@ -304,7 +302,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
304
302
  version: '0'
305
303
  requirements: []
306
304
  rubyforge_project:
307
- rubygems_version: 2.4.8
305
+ rubygems_version: 2.6.4
308
306
  signing_key:
309
307
  specification_version: 4
310
308
  summary: Fundamental repository data model for hydra
@@ -330,6 +328,7 @@ test_files:
330
328
  - spec/fixtures/test5.mp3
331
329
  - spec/fixtures/updated-file.txt
332
330
  - spec/fixtures/world.png
331
+ - spec/hydra/works/characterization_spec.rb
333
332
  - spec/hydra/works/models/characterization/fits_datastream_spec.rb
334
333
  - spec/hydra/works/models/collection_spec.rb
335
334
  - spec/hydra/works/models/concerns/file_set/contained_files_spec.rb
@@ -343,6 +342,7 @@ test_files:
343
342
  - spec/hydra/works/services/characterization_service_spec.rb
344
343
  - spec/hydra/works/services/persist_derivatives_spec.rb
345
344
  - spec/hydra/works/services/upload_file_spec.rb
345
+ - spec/hydra/works/services/virus_checker_service_spec.rb
346
346
  - spec/hydra/works_spec.rb
347
347
  - spec/spec_helper.rb
348
348
  - spec/support/file_set_helper.rb
@@ -1,12 +0,0 @@
1
- module Hydra::Works::Characterization
2
- class AlreadyThereStrategy < ActiveTriples::ExtensionStrategy
3
- # override apply method to check if property already exists or reciever already has predicate defined.
4
- # Do not add property if the rdf_resource already responds to the property name
5
- # Do not add property if the rdf_resource already has a property with the same predicate.
6
- def self.apply(resource, property)
7
- return if resource.respond_to?(property.name)
8
- return if resource.properties.any? { |p| p[1].predicate == property.predicate }
9
- resource.property property.name, property.to_h
10
- end
11
- end
12
- end
@@ -1,14 +0,0 @@
1
- module Hydra::Works::Characterization
2
- module Audio
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- # Apply the audio schema. This will add properties defined in the schema.
7
- apply_schema AudioSchema, AlreadyThereStrategy
8
-
9
- # Update the configuration to map the parsed terms to the correct property.
10
- parser_mapping.merge!(audio_sample_rate: :sample_rate,
11
- audio_duration: :duration)
12
- end
13
- end
14
- end
@@ -1,23 +0,0 @@
1
- module Hydra::Works::Characterization
2
- module Base
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- # Apply the base schema. This will add properties defined in the schema.
7
- apply_schema BaseSchema, AlreadyThereStrategy
8
-
9
- # Parser config is :term => :property.
10
- # Use this config to override the default behavior of value assignment which is:
11
- # value is assigned to the property with the same name as the characterization term.
12
- # use parser_config.merge! for subsequent modules.
13
- class_attribute :parser_mapping
14
- self.parser_mapping = { exif_tool_version: :exif_version,
15
- file_mime_type: :mime_type }
16
-
17
- # Parser class is an OM terminology.
18
- # It maps the characterization tool's output xml to terms and values.
19
- class_attribute :parser_class
20
- self.parser_class = FitsDatastream
21
- end
22
- end
23
- end
@@ -1,11 +0,0 @@
1
- module Hydra::Works::Characterization
2
- module Document
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- # Apply the document schema. This will add properties defined in the schema.
7
- apply_schema DocumentSchema, AlreadyThereStrategy
8
- parser_mapping.merge!(file_author: :creator, file_language: :language)
9
- end
10
- end
11
- end
@@ -1,10 +0,0 @@
1
- module Hydra::Works::Characterization
2
- module Image
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- # Apply the image schema. This will add properties defined in the schema.
7
- apply_schema ImageSchema, AlreadyThereStrategy
8
- end
9
- end
10
- end
@@ -1,17 +0,0 @@
1
- module Hydra::Works::Characterization
2
- module Video
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- # Apply the module schema. This will add properties defined in the schema.
7
- apply_schema VideoSchema, AlreadyThereStrategy
8
-
9
- # Update the configuration to map the parsed terms to the correct property.
10
- parser_mapping.merge!(video_sample_rate: :sample_rate,
11
- video_audio_sample_rate: :sample_rate,
12
- video_duration: :duration,
13
- video_width: :width,
14
- video_height: :height)
15
- end
16
- end
17
- end