hydra-works 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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