curation_concerns-models 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.md +177 -0
  5. data/README.md +42 -0
  6. data/Rakefile +1 -0
  7. data/app/actors/concerns/curation_concerns/manages_embargoes_actor.rb +99 -0
  8. data/app/actors/curation_concerns/base_actor.rb +90 -0
  9. data/app/actors/curation_concerns/generic_file_actor.rb +150 -0
  10. data/app/actors/curation_concerns/work_actor_behavior.rb +88 -0
  11. data/app/jobs/active_fedora_id_based_job.rb +22 -0
  12. data/app/jobs/active_fedora_pid_based_job.rb +6 -0
  13. data/app/jobs/audit_job.rb +58 -0
  14. data/app/jobs/characterize_job.rb +11 -0
  15. data/app/jobs/copy_permissions_job.rb +24 -0
  16. data/app/jobs/create_derivatives_job.rb +15 -0
  17. data/app/jobs/import_url_job.rb +56 -0
  18. data/app/jobs/ingest_local_file_job.rb +48 -0
  19. data/app/jobs/resolrize_job.rb +9 -0
  20. data/app/models/checksum_audit_log.rb +21 -0
  21. data/app/models/concerns/curation_concerns/ability.rb +34 -0
  22. data/app/models/concerns/curation_concerns/basic_metadata.rb +87 -0
  23. data/app/models/concerns/curation_concerns/collection_behavior.rb +47 -0
  24. data/app/models/concerns/curation_concerns/generic_file/belongs_to_works.rb +53 -0
  25. data/app/models/concerns/curation_concerns/generic_file/characterization.rb +89 -0
  26. data/app/models/concerns/curation_concerns/generic_file/content.rb +8 -0
  27. data/app/models/concerns/curation_concerns/generic_file/export.rb +343 -0
  28. data/app/models/concerns/curation_concerns/generic_file/full_text_indexing.rb +12 -0
  29. data/app/models/concerns/curation_concerns/generic_file/indexing.rb +14 -0
  30. data/app/models/concerns/curation_concerns/generic_file/versions.rb +16 -0
  31. data/app/models/concerns/curation_concerns/generic_file.rb +5 -0
  32. data/app/models/concerns/curation_concerns/generic_file_behavior.rb +44 -0
  33. data/app/models/concerns/curation_concerns/generic_work_behavior.rb +38 -0
  34. data/app/models/concerns/curation_concerns/has_representative.rb +14 -0
  35. data/app/models/concerns/curation_concerns/human_readable_type.rb +23 -0
  36. data/app/models/concerns/curation_concerns/permissions/readable.rb +19 -0
  37. data/app/models/concerns/curation_concerns/permissions/writable.rb +75 -0
  38. data/app/models/concerns/curation_concerns/permissions.rb +7 -0
  39. data/app/models/concerns/curation_concerns/serializers.rb +15 -0
  40. data/app/models/concerns/curation_concerns/solr_document_behavior.rb +135 -0
  41. data/app/models/concerns/curation_concerns/user.rb +65 -0
  42. data/app/models/concerns/curation_concerns/with_basic_metadata.rb +98 -0
  43. data/app/models/concerns/curation_concerns/with_generic_files.rb +29 -0
  44. data/app/models/curation_concerns/classify_concern.rb +47 -0
  45. data/app/models/curation_concerns/quick_classification_query.rb +31 -0
  46. data/app/models/datastreams/fits_datastream.rb +148 -0
  47. data/app/models/version_committer.rb +2 -0
  48. data/app/services/curation_concerns/characterization_service.rb +71 -0
  49. data/app/services/curation_concerns/full_text_extraction_service.rb +38 -0
  50. data/app/services/curation_concerns/generic_file_audit_service.rb +85 -0
  51. data/app/services/curation_concerns/generic_file_indexing_service.rb +14 -0
  52. data/app/services/curation_concerns/generic_work_indexing_service.rb +16 -0
  53. data/app/services/curation_concerns/noid.rb +23 -0
  54. data/app/services/curation_concerns/repository_audit_service.rb +9 -0
  55. data/app/services/curation_concerns/versioning_service.rb +27 -0
  56. data/config/locales/curation_concerns.en.yml +6 -0
  57. data/curation_concerns-models.gemspec +34 -0
  58. data/lib/curation_concerns/messages.rb +66 -0
  59. data/lib/curation_concerns/models/engine.rb +61 -0
  60. data/lib/curation_concerns/models/resque.rb +36 -0
  61. data/lib/curation_concerns/models/utils.rb +22 -0
  62. data/lib/curation_concerns/models/version.rb +5 -0
  63. data/lib/curation_concerns/models.rb +32 -0
  64. data/lib/generators/curation_concerns/models/abstract_migration_generator.rb +30 -0
  65. data/lib/generators/curation_concerns/models/clamav_generator.rb +19 -0
  66. data/lib/generators/curation_concerns/models/fulltext_generator.rb +28 -0
  67. data/lib/generators/curation_concerns/models/install_generator.rb +70 -0
  68. data/lib/generators/curation_concerns/models/templates/app/models/collection.rb +4 -0
  69. data/lib/generators/curation_concerns/models/templates/app/models/generic_file.rb +4 -0
  70. data/lib/generators/curation_concerns/models/templates/config/clamav.rb +1 -0
  71. data/lib/generators/curation_concerns/models/templates/config/curation_concerns.rb +123 -0
  72. data/lib/generators/curation_concerns/models/templates/config/mime_types.rb +6 -0
  73. data/lib/generators/curation_concerns/models/templates/config/redis.yml +9 -0
  74. data/lib/generators/curation_concerns/models/templates/config/redis_config.rb +32 -0
  75. data/lib/generators/curation_concerns/models/templates/config/resque-pool.yml +1 -0
  76. data/lib/generators/curation_concerns/models/templates/config/resque_admin.rb +10 -0
  77. data/lib/generators/curation_concerns/models/templates/config/resque_config.rb +5 -0
  78. data/lib/generators/curation_concerns/models/templates/migrations/create_checksum_audit_logs.rb +19 -0
  79. data/lib/generators/curation_concerns/models/templates/migrations/create_version_committers.rb +15 -0
  80. data/lib/tasks/curation_concerns-models_tasks.rake +75 -0
  81. data/lib/tasks/migrate.rake +13 -0
  82. data/lib/tasks/resque.rake +13 -0
  83. data/lib/tasks/solr_reindex.rake +8 -0
  84. metadata +282 -0
@@ -0,0 +1,22 @@
1
+ class ActiveFedoraIdBasedJob
2
+ def queue_name
3
+ :id_based
4
+ end
5
+
6
+ attr_accessor :id
7
+
8
+ def initialize(id)
9
+ self.id = id
10
+ end
11
+
12
+ def object
13
+ @object ||= ActiveFedora::Base.find(id)
14
+ end
15
+
16
+ alias_method :generic_file, :object
17
+ alias_method :generic_file_id, :id
18
+
19
+ def run
20
+ raise RuntimeError, "Define #run in a subclass"
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ class ActiveFedoraPidBasedJob < ActiveFedoraIdBasedJob
2
+ extend Deprecation
3
+ def self.extended(document)
4
+ Deprecation.warn ActiveFedoraPidBasedJob, "ActiveFedoraPidBasedJob is deprecated; use ActiveFedoraIdBasedJob instead."
5
+ end
6
+ end
@@ -0,0 +1,58 @@
1
+ class AuditJob < ActiveFedoraIdBasedJob
2
+ def queue_name
3
+ :audit
4
+ end
5
+
6
+ attr_accessor :uri, :id, :file_id
7
+
8
+ # URI of the resource to audit.
9
+ # This URI could include the actual resource (e.g. content) and the version to audit:
10
+ # http://localhost:8983/fedora/rest/test/a/b/c/abcxyz/content/fcr:versions/version1
11
+ # but it could also just be:
12
+ # http://localhost:8983/fedora/rest/test/a/b/c/abcxyz/content
13
+ # @param [String] id of the parent object
14
+ # @param [String] file_id used to find the file within its parent object (usually "original_file")
15
+ # @param [String] uri of the specific file/version to be audited
16
+ def initialize(id, file_id, uri)
17
+ super(id)
18
+ self.file_id = file_id
19
+ self.uri = uri
20
+ end
21
+
22
+ def run
23
+ fixity_ok = false
24
+ log = run_audit
25
+ fixity_ok = (log.pass == 1)
26
+ unless fixity_ok
27
+ if CurationConcerns.config.respond_to?(:after_audit_failure)
28
+ login = generic_file.depositor
29
+ user = User.find_by_user_key(login)
30
+ CurationConcerns.config.after_audit_failure.call(generic_file, user, log.created_at)
31
+ end
32
+ end
33
+ fixity_ok
34
+ end
35
+
36
+ protected
37
+
38
+ def run_audit
39
+ begin
40
+ fixity_ok = ActiveFedora::FixityService.new(uri).check
41
+ rescue Ldp::NotFound
42
+ error_msg = "resource not found"
43
+ end
44
+
45
+ if fixity_ok
46
+ passing = 1
47
+ ChecksumAuditLog.prune_history(id, file_id)
48
+ else
49
+ logger.warn "***AUDIT*** Audit failed for #{uri} #{error_msg}"
50
+ passing = 0
51
+ end
52
+ ChecksumAuditLog.create!(pass: passing, generic_file_id: id, version: uri, file_id: file_id)
53
+ end
54
+
55
+ def logger
56
+ ActiveFedora::Base.logger
57
+ end
58
+ end
@@ -0,0 +1,11 @@
1
+ class CharacterizeJob < ActiveFedoraIdBasedJob
2
+ def queue_name
3
+ :characterize
4
+ end
5
+
6
+ def run
7
+ CurationConcerns::CharacterizationService.run(generic_file)
8
+ generic_file.save
9
+ CurationConcerns.queue.push(CreateDerivativesJob.new(generic_file.id))
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ class CopyPermissionsJob
2
+ def queue_name
3
+ :permissions
4
+ end
5
+
6
+ attr_accessor :id
7
+
8
+ def initialize(id)
9
+ self.id = id
10
+ end
11
+
12
+ def run
13
+ # work = ActiveFedora::Base.load_instance_from_solr(id)
14
+ work = ActiveFedora::Base.find(id) # Hydra::Works::GenericWork is not compatible with load_instance_from_solr. Using (slower) ActiveFedora::Base.find instead.
15
+ if work.respond_to?(:generic_files)
16
+ work.generic_files.each do |file|
17
+
18
+ work.permissions.each {|perm| file.permissions << Hydra::AccessControls::Permission.new(perm.to_hash)}
19
+ new_permissions = file.permissions.uniq! { |item| item.to_hash}
20
+ file.permissions = new_permissions unless new_permissions.blank?
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ class CreateDerivativesJob < ActiveFedoraIdBasedJob
2
+ def queue_name
3
+ :derivatives
4
+ end
5
+
6
+ def run
7
+ return unless generic_file.original_file.has_content?
8
+ if generic_file.video?
9
+ return unless CurationConcerns.config.enable_ffmpeg
10
+ end
11
+
12
+ generic_file.create_derivatives
13
+ generic_file.save
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+ require 'tempfile'
4
+
5
+ class ImportUrlJob < ActiveFedoraIdBasedJob
6
+
7
+ def queue_name
8
+ :import_url
9
+ end
10
+
11
+ def run
12
+ user = User.find_by_user_key(generic_file.depositor)
13
+
14
+ Tempfile.open(id.gsub('/', '_')) do |f|
15
+ copy_remote_file(generic_file.import_url, f)
16
+ # attach downloaded file to generic file stubbed out
17
+ if CurationConcerns::GenericFileActor.new(generic_file, user).create_content(f)
18
+
19
+ # send message to user on download success
20
+ if CurationConcerns.config.respond_to?(:after_import_url_success)
21
+ CurationConcerns.config.after_import_url_success.call(generic_file, user)
22
+ end
23
+ else
24
+
25
+ # send message to user on download failure
26
+ if CurationConcerns.config.respond_to?(:after_import_url_failure)
27
+ CurationConcerns.config.after_import_url_failure.call(generic_file, user)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def copy_remote_file(import_url, f)
34
+ f.binmode
35
+ # download file from url
36
+ uri = URI(generic_file.import_url)
37
+ http = Net::HTTP.new(uri.host, uri.port)
38
+ http.use_ssl = uri.scheme == "https" # enable SSL/TLS
39
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
40
+ mime_type = nil
41
+
42
+ http.start do
43
+ http.request_get(uri.request_uri) do |resp|
44
+ mime_type = resp.content_type
45
+ resp.read_body do |segment|
46
+ f.write(segment)
47
+ end
48
+ end
49
+ end
50
+ f.rewind
51
+ end
52
+
53
+ def job_user
54
+ User.batchuser
55
+ end
56
+ end
@@ -0,0 +1,48 @@
1
+ class IngestLocalFileJob
2
+ attr_accessor :directory, :filename, :user_key, :generic_file_id
3
+
4
+ def queue_name
5
+ :ingest
6
+ end
7
+
8
+ def initialize(generic_file_id, directory, filename, user_key)
9
+ self.generic_file_id = generic_file_id
10
+ self.directory = directory
11
+ self.filename = filename
12
+ self.user_key = user_key
13
+ end
14
+
15
+ def run
16
+ user = User.find_by_user_key(user_key)
17
+ raise "Unable to find user for #{user_key}" unless user
18
+ generic_file = GenericFile.find(generic_file_id)
19
+ generic_file.label ||= filename
20
+ path = File.join(directory, filename)
21
+
22
+ actor = CurationConcerns::GenericFileActor.new(generic_file, user)
23
+
24
+ if actor.create_content(File.open(path))
25
+ FileUtils.rm(path)
26
+
27
+ # send message to user on import success
28
+ if CurationConcerns.config.respond_to?(:after_import_local_file_success)
29
+ CurationConcerns.config.after_import_local_file_success.call(generic_file, user, filename)
30
+ end
31
+ else
32
+
33
+ # send message to user on import failure
34
+ if CurationConcerns.config.respond_to?(:after_import_local_file_failure)
35
+ CurationConcerns.config.after_import_local_file_failure.call(generic_file, user, filename)
36
+ end
37
+ end
38
+ end
39
+
40
+ def job_user
41
+ User.batchuser
42
+ end
43
+
44
+ def mime_type(file_name)
45
+ mime_types = MIME::Types.of(file_name)
46
+ mime_types.empty? ? "application/octet-stream" : mime_types.first.content_type
47
+ end
48
+ end
@@ -0,0 +1,9 @@
1
+ class ResolrizeJob
2
+ def queue_name
3
+ :resolrize
4
+ end
5
+
6
+ def run
7
+ ActiveFedora::Base.reindex_everything
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ class ChecksumAuditLog < ActiveRecord::Base
2
+
3
+ def self.get_audit_log(id, path, version_uri)
4
+ ChecksumAuditLog.find_or_create_by(generic_file_id: id, file_id: path, version: version_uri)
5
+ end
6
+
7
+ # Check to see if there are previous passing logs that we can delete
8
+ # we want to keep the first passing event after a failure, the most current passing event,
9
+ # and all failures so that this table doesn't grow too large
10
+ # Simple way (a little naieve): if the last 2 were passing, delete the first one
11
+ def self.prune_history(id, path)
12
+ list = logs_for(id, path).limit(2)
13
+ if list.size > 1 && (list[0].pass == 1) && (list[1].pass == 1)
14
+ list[0].destroy
15
+ end
16
+ end
17
+
18
+ def self.logs_for(id, path)
19
+ ChecksumAuditLog.where(generic_file_id: id, file_id: path).order('created_at desc, id desc')
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ module CurationConcerns
2
+ module Ability
3
+ extend ActiveSupport::Concern
4
+ included do
5
+ self.ability_logic += [:curation_concerns_permissions]
6
+ end
7
+
8
+ def curation_concerns_permissions
9
+
10
+ unless current_user.new_record?
11
+ can :create, CurationConcerns::ClassifyConcern
12
+ # TODO: Shouldn't this be in `everyone_can_create_curation_concerns` ?
13
+ can :create, ::GenericFile
14
+ end
15
+
16
+ if user_groups.include? 'admin'
17
+ can [:create, :discover, :show, :read, :edit, :update, :destroy], :all
18
+ end
19
+
20
+ can :collect, :all
21
+
22
+ end
23
+
24
+ # Add this to your ability_logic if you want all logged in users to be able
25
+ # to submit content
26
+ def everyone_can_create_curation_concerns
27
+ unless current_user.new_record?
28
+ can :create, [ CurationConcerns.configuration.curation_concerns ]
29
+ can :create, ::Collection
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,87 @@
1
+ module CurationConcerns
2
+ module BasicMetadata
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+
7
+ property :label, predicate: ActiveFedora::RDF::Fcrepo::Model.downloadFilename, multiple: false
8
+
9
+ property :depositor, predicate: ::RDF::URI.new("http://id.loc.gov/vocabulary/relators/dpt"), multiple: false do |index|
10
+ index.as :symbol, :stored_searchable
11
+ end
12
+
13
+ property :relative_path, predicate: ::RDF::URI.new('http://scholarsphere.psu.edu/ns#relativePath'), multiple: false
14
+
15
+ property :import_url, predicate: ::RDF::URI.new('http://scholarsphere.psu.edu/ns#importUrl'), multiple: false do |index|
16
+ index.as :symbol
17
+ end
18
+
19
+ property :part_of, predicate: ::RDF::DC.isPartOf
20
+ property :resource_type, predicate: ::RDF::DC.type do |index|
21
+ index.as :stored_searchable, :facetable
22
+ end
23
+ property :title, predicate: ::RDF::DC.title do |index|
24
+ index.as :stored_searchable, :facetable
25
+ end
26
+ property :creator, predicate: ::RDF::DC.creator do |index|
27
+ index.as :stored_searchable, :facetable
28
+ end
29
+ property :contributor, predicate: ::RDF::DC.contributor do |index|
30
+ index.as :stored_searchable, :facetable
31
+ end
32
+ property :description, predicate: ::RDF::DC.description do |index|
33
+ index.type :text
34
+ index.as :stored_searchable
35
+ end
36
+ property :tag, predicate: ::RDF::DC.relation do |index|
37
+ index.as :stored_searchable, :facetable
38
+ end
39
+ property :rights, predicate: ::RDF::DC.rights do |index|
40
+ index.as :stored_searchable
41
+ end
42
+ property :publisher, predicate: ::RDF::DC.publisher do |index|
43
+ index.as :stored_searchable, :facetable
44
+ end
45
+ property :date_created, predicate: ::RDF::DC.created do |index|
46
+ index.as :stored_searchable
47
+ end
48
+
49
+ # We reserve date_uploaded for the original creation date of the record.
50
+ # For example, when migrating data from a fedora3 repo to fedora4,
51
+ # fedora's system created date will reflect the date when the record
52
+ # was created in fedora4, but the date_uploaded will preserve the
53
+ # original creation date from the old repository.
54
+ property :date_uploaded, predicate: ::RDF::DC.dateSubmitted, multiple: false do |index|
55
+ index.type :date
56
+ index.as :stored_sortable
57
+ end
58
+
59
+ property :date_modified, predicate: ::RDF::DC.modified, multiple: false do |index|
60
+ index.type :date
61
+ index.as :stored_sortable
62
+ end
63
+ property :subject, predicate: ::RDF::DC.subject do |index|
64
+ index.as :stored_searchable, :facetable
65
+ end
66
+ property :language, predicate: ::RDF::DC.language do |index|
67
+ index.as :stored_searchable, :facetable
68
+ end
69
+ property :identifier, predicate: ::RDF::DC.identifier do |index|
70
+ index.as :stored_searchable
71
+ end
72
+ property :based_near, predicate: ::RDF::FOAF.based_near do |index|
73
+ index.as :stored_searchable, :facetable
74
+ end
75
+ property :related_url, predicate: ::RDF::RDFS.seeAlso do |index|
76
+ index.as :stored_searchable
77
+ end
78
+ property :bibliographic_citation, predicate: ::RDF::DC.bibliographicCitation do |index|
79
+ index.as :stored_searchable
80
+ end
81
+ property :source, predicate: ::RDF::DC.source do |index|
82
+ index.as :stored_searchable
83
+ end
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,47 @@
1
+ module CurationConcerns
2
+ module CollectionBehavior
3
+ extend ActiveSupport::Concern
4
+
5
+ include Hydra::AccessControls::WithAccessRight
6
+ include Hydra::Collection
7
+ include CurationConcerns::Noid
8
+ include CurationConcerns::HumanReadableType
9
+ include CurationConcerns::HasRepresentative
10
+ include CurationConcerns::Permissions
11
+
12
+ included do
13
+ validates :title, presence: true
14
+ end
15
+
16
+ def add_member(collectible)
17
+ if can_add_to_members?(collectible)
18
+ self.members << collectible
19
+ save
20
+ end
21
+ end
22
+
23
+ def to_s
24
+ title.present? ? title : "No Title"
25
+ end
26
+
27
+ def bytes
28
+ members.reduce(0) { |sum, gf| sum + gf.content.size.to_i }
29
+ end
30
+
31
+ def to_solr(solr_doc={})
32
+ super(solr_doc).tap do |solr_doc|
33
+ Solrizer.set_field(solr_doc, 'generic_type', human_readable_type, :facetable)
34
+ end
35
+ end
36
+
37
+ def can_be_member_of_collection?(collection)
38
+ collection == self ? false : true
39
+ end
40
+
41
+ private
42
+
43
+ def can_add_to_members?(collectible)
44
+ collectible.try(:can_be_member_of_collection?, self)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,53 @@
1
+ module CurationConcerns
2
+ module GenericFile
3
+ module BelongsToWorks
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before_destroy :remove_representative_relationship
8
+ end
9
+
10
+ def generic_works
11
+ self.parent_objects # parent_objects is provided by Hydra::PCDM::ObjectBehavior
12
+ end
13
+
14
+ def generic_work_ids
15
+ generic_works.map { |work| work.id }
16
+ end
17
+
18
+ # Returns the first parent object
19
+ # This is a hack to handle things like GenericFiles inheriting access controls from their parent. (see CurationConcerns::ParentContainer in app/controllers/concerns/curation_concers/parent_container.rb)
20
+ def parent
21
+ self.parent_objects.first
22
+ end
23
+
24
+ # Returns the id of first parent object
25
+ # This is a hack to handle things like GenericFiles inheriting access controls from their parent. (see CurationConcerns::ParentContainer in app/controllers/concerns/curation_concers/parent_container.rb)
26
+ def parent_id
27
+ parent.id
28
+ end
29
+
30
+ # Files with sibling relationships
31
+ # Returns all GenericFiles aggregated by any of the GenericWorks that aggregate the current object
32
+ def related_files
33
+ generic_works = self.generic_works
34
+ return [] if generic_works.empty?
35
+ generic_works.flat_map {|work| work.generic_files.select {|generic_file| generic_file.id != self.id } }
36
+ end
37
+
38
+ # If any parent works are pointing at this object as their representative, remove that pointer.
39
+ def remove_representative_relationship
40
+ generic_works = self.generic_works
41
+ return if generic_works.empty?
42
+ generic_works.each do |work|
43
+ if work.representative == self.id
44
+ work.representative = nil
45
+ work.save
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,89 @@
1
+ module CurationConcerns
2
+ module GenericFile
3
+ module Characterization
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ contains "characterization", class_name: 'FitsDatastream'
7
+ property :mime_type, delegate_to: 'characterization', multiple: false do |index|
8
+ index.as :stored_searchable
9
+ end
10
+ property :format_label, delegate_to: 'characterization'
11
+ property :file_size, delegate_to: 'characterization'
12
+ property :last_modified, delegate_to: 'characterization'
13
+ property :filename, delegate_to: 'characterization'
14
+ property :original_checksum, delegate_to: 'characterization'
15
+ property :rights_basis, delegate_to: 'characterization'
16
+ property :copyright_basis, delegate_to: 'characterization'
17
+ property :copyright_note, delegate_to: 'characterization'
18
+ property :well_formed, delegate_to: 'characterization'
19
+ property :valid, delegate_to: 'characterization'
20
+ property :status_message, delegate_to: 'characterization'
21
+ property :file_title, delegate_to: 'characterization'
22
+ property :file_author, delegate_to: 'characterization'
23
+ property :page_count, delegate_to: 'characterization'
24
+ property :file_language, delegate_to: 'characterization'
25
+ property :word_count, delegate_to: 'characterization'
26
+ property :character_count, delegate_to: 'characterization'
27
+ property :paragraph_count, delegate_to: 'characterization'
28
+ property :line_count, delegate_to: 'characterization'
29
+ property :table_count, delegate_to: 'characterization'
30
+ property :graphics_count, delegate_to: 'characterization'
31
+ property :byte_order, delegate_to: 'characterization'
32
+ property :compression, delegate_to: 'characterization'
33
+ property :color_space, delegate_to: 'characterization'
34
+ property :profile_name, delegate_to: 'characterization'
35
+ property :profile_version, delegate_to: 'characterization'
36
+ property :orientation, delegate_to: 'characterization'
37
+ property :color_map, delegate_to: 'characterization'
38
+ property :image_producer, delegate_to: 'characterization'
39
+ property :capture_device, delegate_to: 'characterization'
40
+ property :scanning_software, delegate_to: 'characterization'
41
+ property :exif_version, delegate_to: 'characterization'
42
+ property :gps_timestamp, delegate_to: 'characterization'
43
+ property :latitude, delegate_to: 'characterization'
44
+ property :longitude, delegate_to: 'characterization'
45
+ property :character_set, delegate_to: 'characterization'
46
+ property :markup_basis, delegate_to: 'characterization'
47
+ property :markup_language, delegate_to: 'characterization'
48
+ property :bit_depth, delegate_to: 'characterization'
49
+ property :channels, delegate_to: 'characterization'
50
+ property :data_format, delegate_to: 'characterization'
51
+ property :offset, delegate_to: 'characterization'
52
+ property :frame_rate, delegate_to: 'characterization'
53
+
54
+ end
55
+
56
+ def width
57
+ characterization.width.blank? ? characterization.video_width : characterization.width
58
+ end
59
+
60
+ def height
61
+ characterization.height.blank? ? characterization.video_height : characterization.height
62
+ end
63
+
64
+ def duration
65
+ characterization.duration.blank? ? characterization.video_duration : characterization.duration
66
+ end
67
+
68
+ def sample_rate
69
+ characterization.sample_rate.blank? ? characterization.video_sample_rate : characterization.sample_rate
70
+ end
71
+
72
+ def characterization_terms
73
+ h = {}
74
+ self.characterization.class.terminology.terms.each_pair do |k, v|
75
+ next unless v.respond_to? :proxied_term
76
+ term = v.proxied_term
77
+ begin
78
+ value = self.send(term.name)
79
+ h[term.name] = value unless value.empty?
80
+ rescue NoMethodError
81
+ next
82
+ end
83
+ end
84
+ h
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,8 @@
1
+ module CurationConcerns
2
+ module GenericFile
3
+ module Content
4
+ extend ActiveSupport::Concern
5
+
6
+ end
7
+ end
8
+ end