curation_concerns-models 0.1.0 → 0.2.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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/Rakefile +1 -1
  4. data/app/actors/concerns/curation_concerns/manages_embargoes_actor.rb +11 -19
  5. data/app/actors/curation_concerns/base_actor.rb +41 -45
  6. data/app/actors/curation_concerns/embargo_actor.rb +19 -0
  7. data/app/actors/curation_concerns/file_set_actor.rb +200 -0
  8. data/app/actors/curation_concerns/lease_actor.rb +19 -0
  9. data/app/actors/curation_concerns/work_actor_behavior.rb +55 -58
  10. data/app/indexers/curation_concerns/collection_indexer.rb +10 -0
  11. data/app/indexers/curation_concerns/file_set_indexing_service.rb +24 -0
  12. data/app/{services/curation_concerns/generic_work_indexing_service.rb → indexers/curation_concerns/work_indexing_service.rb} +6 -6
  13. data/app/jobs/active_fedora_id_based_job.rb +5 -12
  14. data/app/jobs/audit_job.rb +11 -17
  15. data/app/jobs/characterize_job.rb +8 -7
  16. data/app/jobs/create_derivatives_job.rb +8 -11
  17. data/app/jobs/import_url_job.rb +12 -25
  18. data/app/jobs/ingest_file_job.rb +16 -0
  19. data/app/jobs/ingest_local_file_job.rb +14 -35
  20. data/app/jobs/resolrize_job.rb +3 -5
  21. data/app/jobs/upload_set_update_job.rb +68 -0
  22. data/app/models/checksum_audit_log.rb +2 -3
  23. data/app/models/concerns/curation_concerns/ability.rb +18 -10
  24. data/app/models/concerns/curation_concerns/basic_metadata.rb +1 -3
  25. data/app/models/concerns/curation_concerns/collection_behavior.rb +13 -14
  26. data/app/models/concerns/curation_concerns/file_set/belongs_to_upload_sets.rb +15 -0
  27. data/app/models/concerns/curation_concerns/{generic_file → file_set}/belongs_to_works.rb +8 -14
  28. data/app/models/concerns/curation_concerns/file_set/derivatives.rb +54 -0
  29. data/app/models/concerns/curation_concerns/{generic_file → file_set}/full_text_indexing.rb +1 -2
  30. data/app/models/concerns/curation_concerns/{generic_file → file_set}/indexing.rb +2 -2
  31. data/app/models/concerns/curation_concerns/{generic_file → file_set}/versions.rb +2 -3
  32. data/app/models/concerns/curation_concerns/file_set_behavior.rb +36 -0
  33. data/app/models/concerns/curation_concerns/generic_file.rb +1 -1
  34. data/app/models/concerns/curation_concerns/has_representative.rb +6 -7
  35. data/app/models/concerns/curation_concerns/human_readable_type.rb +5 -7
  36. data/app/models/concerns/curation_concerns/permissions.rb +2 -2
  37. data/app/models/concerns/curation_concerns/permissions/readable.rb +0 -1
  38. data/app/models/concerns/curation_concerns/permissions/writable.rb +10 -51
  39. data/app/models/concerns/curation_concerns/serializers.rb +3 -5
  40. data/app/models/concerns/curation_concerns/solr_document_behavior.rb +37 -40
  41. data/app/models/concerns/curation_concerns/upload_set_behavior.rb +38 -0
  42. data/app/models/concerns/curation_concerns/user.rb +4 -51
  43. data/app/models/concerns/curation_concerns/with_file_sets.rb +28 -0
  44. data/app/models/concerns/curation_concerns/{generic_work_behavior.rb → work_behavior.rb} +12 -6
  45. data/app/models/curation_concerns/classify_concern.rb +7 -7
  46. data/app/models/curation_concerns/quick_classification_query.rb +6 -7
  47. data/app/models/single_use_link.rb +34 -0
  48. data/app/models/upload_set.rb +3 -0
  49. data/app/services/curation_concerns/derivative_path.rb +32 -0
  50. data/app/services/curation_concerns/{generic_file_audit_service.rb → file_set_audit_service.rb} +17 -18
  51. data/app/services/curation_concerns/indexes_thumbnails.rb +14 -0
  52. data/app/services/curation_concerns/local_file_service.rb +10 -0
  53. data/app/services/curation_concerns/lock_manager.rb +40 -0
  54. data/app/services/curation_concerns/noid.rb +1 -1
  55. data/app/services/curation_concerns/persist_derivatives.rb +33 -0
  56. data/app/services/curation_concerns/persist_directly_contained_output_file_service.rb +26 -0
  57. data/app/services/curation_concerns/repository_audit_service.rb +1 -3
  58. data/app/services/curation_concerns/thumbnail_path_service.rb +46 -0
  59. data/app/services/curation_concerns/time_service.rb +7 -0
  60. data/app/services/curation_concerns/versioning_service.rb +11 -12
  61. data/curation_concerns-models.gemspec +6 -6
  62. data/lib/curation_concerns/configuration.rb +154 -0
  63. data/lib/curation_concerns/messages.rb +26 -26
  64. data/lib/curation_concerns/models.rb +5 -14
  65. data/lib/curation_concerns/models/engine.rb +0 -30
  66. data/lib/curation_concerns/models/utils.rb +4 -4
  67. data/lib/curation_concerns/models/version.rb +1 -1
  68. data/lib/generators/curation_concerns/models/abstract_migration_generator.rb +8 -7
  69. data/lib/generators/curation_concerns/models/clamav_generator.rb +3 -3
  70. data/lib/generators/curation_concerns/models/install_generator.rb +13 -20
  71. data/lib/generators/curation_concerns/models/templates/app/models/file_set.rb +4 -0
  72. data/lib/generators/curation_concerns/models/templates/config/clamav.rb +1 -1
  73. data/lib/generators/curation_concerns/models/templates/config/curation_concerns.rb +52 -65
  74. data/lib/generators/curation_concerns/models/templates/config/redis_config.rb +13 -17
  75. data/lib/generators/curation_concerns/models/templates/config/resque_config.rb +2 -1
  76. data/lib/generators/curation_concerns/models/templates/migrations/create_checksum_audit_logs.rb +3 -3
  77. data/lib/generators/curation_concerns/models/templates/migrations/create_single_use_links.rb +12 -0
  78. data/lib/tasks/curation_concerns-models_tasks.rake +4 -62
  79. data/lib/tasks/migrate.rake +1 -1
  80. data/lib/tasks/resque.rake +1 -0
  81. data/lib/tasks/solr_reindex.rake +1 -1
  82. metadata +59 -52
  83. data/app/actors/curation_concerns/generic_file_actor.rb +0 -150
  84. data/app/jobs/active_fedora_pid_based_job.rb +0 -6
  85. data/app/jobs/copy_permissions_job.rb +0 -24
  86. data/app/models/concerns/curation_concerns/generic_file/characterization.rb +0 -89
  87. data/app/models/concerns/curation_concerns/generic_file/content.rb +0 -8
  88. data/app/models/concerns/curation_concerns/generic_file/export.rb +0 -343
  89. data/app/models/concerns/curation_concerns/generic_file_behavior.rb +0 -44
  90. data/app/models/concerns/curation_concerns/with_basic_metadata.rb +0 -98
  91. data/app/models/concerns/curation_concerns/with_generic_files.rb +0 -29
  92. data/app/models/datastreams/fits_datastream.rb +0 -148
  93. data/app/services/curation_concerns/characterization_service.rb +0 -71
  94. data/app/services/curation_concerns/full_text_extraction_service.rb +0 -38
  95. data/app/services/curation_concerns/generic_file_indexing_service.rb +0 -14
  96. data/lib/curation_concerns/models/resque.rb +0 -36
  97. data/lib/generators/curation_concerns/models/fulltext_generator.rb +0 -28
  98. data/lib/generators/curation_concerns/models/templates/app/models/generic_file.rb +0 -4
  99. data/lib/generators/curation_concerns/models/templates/config/resque_admin.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 51998b654c32654d086cbeb388436dff6db4c186
4
- data.tar.gz: 59caa819f6745297082809edb2cf38b50ca43c4e
3
+ metadata.gz: 4b866be7465155c67d0157b20159c75f53cc6d2c
4
+ data.tar.gz: def664a51f3bff81f3ca2396787883ae6b3142cc
5
5
  SHA512:
6
- metadata.gz: 3c0af2087c9ec611684b8f6c12bcc62386d7c44837338f08659ca0a2bd6fcbff6538f9e25abc42479f38147553087fd84381deb91aedfaa4637b4a79b6ee7fa0
7
- data.tar.gz: 5079fdbb1d714c8a9b8ef18124da0777e407a0ce877ac748a5bf90fde98617ba88eb6f30480f88435f8b51d2820dc4baef2e8765a6fdc8f34900689ee26b53f7
6
+ metadata.gz: 399bdc3d1ea0bb4722605fa486662e1e33b4c01872f0fe3fe47d7edd36583c0a744a4bfa0198f39e288f4943c69ac00ec712e5ca985cfde379770c510c052516
7
+ data.tar.gz: 1bc3ca8a712bb6d141d4c8411c959db37c66931b86b0c1e3a7a969d42d41402ffb59397ab7d5da1e1c4eec84228a09c50fd9dce5932d37344368193f5a03ea86
data/README.md CHANGED
@@ -4,6 +4,8 @@ Models extracted from worthwhile-models and sufia-models.
4
4
 
5
5
  ## Dependencies
6
6
 
7
+ Checkout the readme for [hydra-derivatives](https://github.com/projecthydra/hydra-derivatives#dependencies) for additional dependencies for generating derivatives.
8
+
7
9
  ### FITS 0.6.2
8
10
 
9
11
  To install FITS:
data/Rakefile CHANGED
@@ -1 +1 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
@@ -9,11 +9,11 @@ module CurationConcerns
9
9
  # include Worthwile::ManagesEmbargoesActor
10
10
  #
11
11
  # def create
12
- # interpret_visibility && super && copy_visibility
12
+ # interpret_visibility && super
13
13
  # end
14
14
  #
15
15
  # def update
16
- # interpret_visibility && super && copy_visibility
16
+ # interpret_visibility && super
17
17
  # end
18
18
  # end
19
19
  #
@@ -22,17 +22,17 @@ module CurationConcerns
22
22
 
23
23
  # Interprets embargo & lease visibility if necessary
24
24
  # returns false if there are any errors
25
- def interpret_visibility(attributes=self.attributes)
25
+ def interpret_visibility(attributes = self.attributes)
26
26
  should_continue = interpret_embargo_visibility(attributes) && interpret_lease_visibility(attributes)
27
27
  if attributes[:visibility]
28
28
  curation_concern.visibility = attributes[:visibility]
29
29
  end
30
- return should_continue
30
+ should_continue
31
31
  end
32
32
 
33
33
  # If user has set visibility to embargo, interprets the relevant information and applies it
34
34
  # Returns false if there are any errors and sets an error on the curation_concern
35
- def interpret_embargo_visibility(attributes=self.attributes)
35
+ def interpret_embargo_visibility(attributes = self.attributes)
36
36
  if attributes[:visibility] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_EMBARGO
37
37
  if !attributes[:embargo_release_date]
38
38
  curation_concern.errors.add(:visibility, 'When setting visibility to "embargo" you must also specify embargo release date.')
@@ -42,9 +42,8 @@ module CurationConcerns
42
42
  curation_concern.apply_embargo(attributes[:embargo_release_date], attributes.delete(:visibility_during_embargo),
43
43
  attributes.delete(:visibility_after_embargo))
44
44
  if curation_concern.embargo
45
- curation_concern.embargo.save # See https://github.com/projecthydra/hydra-head/issues/226
45
+ curation_concern.embargo.save # See https://github.com/projecthydra/hydra-head/issues/226
46
46
  end
47
- @needs_to_copy_visibility = true
48
47
  should_continue = true
49
48
  end
50
49
  else
@@ -57,23 +56,22 @@ module CurationConcerns
57
56
  attributes.delete(:visibility_during_embargo)
58
57
  attributes.delete(:visibility_after_embargo)
59
58
 
60
- return should_continue
59
+ should_continue
61
60
  end
62
61
 
63
62
  # If user has set visibility to lease, interprets the relevant information and applies it
64
63
  # Returns false if there are any errors and sets an error on the curation_concern
65
- def interpret_lease_visibility(attributes=self.attributes)
64
+ def interpret_lease_visibility(attributes = self.attributes)
66
65
  if attributes[:visibility] == Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_LEASE
67
66
  if !attributes[:lease_expiration_date]
68
67
  curation_concern.errors.add(:visibility, 'When setting visibility to "lease" you must also specify lease expiration date.')
69
68
  should_continue = false
70
69
  else
71
70
  curation_concern.apply_lease(attributes[:lease_expiration_date], attributes.delete(:visibility_during_lease),
72
- attributes.delete(:visibility_after_lease))
71
+ attributes.delete(:visibility_after_lease))
73
72
  if curation_concern.lease
74
- curation_concern.lease.save # See https://github.com/projecthydra/hydra-head/issues/226
73
+ curation_concern.lease.save # See https://github.com/projecthydra/hydra-head/issues/226
75
74
  end
76
- @needs_to_copy_visibility = true
77
75
  attributes.delete(:visibility)
78
76
  should_continue = true
79
77
  end
@@ -87,13 +85,7 @@ module CurationConcerns
87
85
  attributes.delete(:visibility_during_lease)
88
86
  attributes.delete(:visibility_after_lease)
89
87
 
90
- return should_continue
91
- end
92
-
93
-
94
- def copy_visibility
95
- CurationConcerns.queue.push(VisibilityCopyWorker.new(curation_concern.id)) if @needs_to_copy_visibility
96
- true
88
+ should_continue
97
89
  end
98
90
  end
99
91
  end
@@ -11,7 +11,7 @@ module CurationConcerns
11
11
  @user = user
12
12
  @attributes = input_attributes.dup.with_indifferent_access
13
13
  @visibility = attributes[:visibility]
14
- @cloud_resources= attributes.delete(:cloud_resources.to_s)
14
+ @cloud_resources = attributes.delete(:cloud_resources.to_s)
15
15
  end
16
16
 
17
17
  attr_reader :visibility
@@ -32,59 +32,55 @@ module CurationConcerns
32
32
  end
33
33
 
34
34
  protected
35
- def apply_creation_data_to_curation_concern
36
- apply_depositor_metadata
37
- apply_deposit_date
38
- end
39
35
 
40
- def apply_update_data_to_curation_concern
41
- true
42
- end
36
+ def apply_creation_data_to_curation_concern
37
+ apply_depositor_metadata
38
+ apply_deposit_date
39
+ end
43
40
 
44
- def apply_depositor_metadata
45
- curation_concern.apply_depositor_metadata(user.user_key)
46
- curation_concern.edit_users += [user.user_key]
47
- end
41
+ def apply_update_data_to_curation_concern
42
+ true
43
+ end
48
44
 
49
- def apply_deposit_date
50
- curation_concern.date_uploaded = Date.today
51
- end
45
+ def apply_depositor_metadata
46
+ curation_concern.apply_depositor_metadata(user.user_key)
47
+ curation_concern.edit_users += [user.user_key]
48
+ end
52
49
 
53
- def save
54
- curation_concern.save
55
- end
50
+ def apply_deposit_date
51
+ curation_concern.date_uploaded = CurationConcerns::TimeService.time_in_utc
52
+ end
56
53
 
57
- def apply_save_data_to_curation_concern
58
- attributes[:rights] = Array(attributes[:rights]) if attributes.key? :rights
59
- remove_blank_attributes!
60
- curation_concern.attributes = attributes.symbolize_keys
61
- curation_concern.date_modified = Date.today
62
- end
54
+ def save
55
+ curation_concern.save
56
+ end
63
57
 
64
- def attach_file(generic_file, file_to_attach)
65
- ActiveSupport::Deprecation.warn("removing #{self.class}#attach_file, use CurationConcern.attach_file instead")
66
- CurationConcern.attach_file(generic_file, user, file_to_attach)
67
- end
58
+ def apply_save_data_to_curation_concern
59
+ attributes[:rights] = Array(attributes[:rights]) if attributes.key? :rights
60
+ remove_blank_attributes!
61
+ curation_concern.attributes = attributes.symbolize_keys
62
+ curation_concern.date_modified = CurationConcerns::TimeService.time_in_utc
63
+ end
68
64
 
69
- # If any attributes are blank remove them
70
- # e.g.:
71
- # self.attributes = { 'title' => ['first', 'second', ''] }
72
- # remove_blank_attributes!
73
- # self.attributes
74
- # => { 'title' => ['first', 'second'] }
75
- def remove_blank_attributes!
76
- multivalued_form_attributes.each_with_object(attributes) do |(k, v), h|
77
- if v.instance_of? Array
78
- h[k] = v.select(&:present?)
79
- else
80
- h[k] = v
65
+ # If any attributes are blank remove them
66
+ # e.g.:
67
+ # self.attributes = { 'title' => ['first', 'second', ''] }
68
+ # remove_blank_attributes!
69
+ # self.attributes
70
+ # => { 'title' => ['first', 'second'] }
71
+ def remove_blank_attributes!
72
+ multivalued_form_attributes.each_with_object(attributes) do |(k, v), h|
73
+ if v.instance_of? Array
74
+ h[k] = v.select(&:present?)
75
+ else
76
+ h[k] = v
77
+ end
81
78
  end
82
79
  end
83
- end
84
80
 
85
- # Return the hash of attributes that are multivalued and not uploaded files
86
- def multivalued_form_attributes
87
- attributes.select {|_, v| v.respond_to?(:select) && !v.respond_to?(:read) }
88
- end
81
+ # Return the hash of attributes that are multivalued and not uploaded files
82
+ def multivalued_form_attributes
83
+ attributes.select { |_, v| v.respond_to?(:select) && !v.respond_to?(:read) }
84
+ end
89
85
  end
90
86
  end
@@ -0,0 +1,19 @@
1
+ module CurationConcerns
2
+ class EmbargoActor
3
+ attr_reader :work
4
+
5
+ # @param [Hydra::Works::Work] work
6
+ def initialize(work)
7
+ @work = work
8
+ end
9
+
10
+ # Update the visibility of the work to match the correct state of the embargo, then clear the embargo date, etc.
11
+ # Saves the embargo and the work
12
+ def destroy
13
+ work.embargo_visibility! # If the embargo has lapsed, update the current visibility.
14
+ work.deactivate_embargo!
15
+ work.embargo.save!
16
+ work.save!
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,200 @@
1
+ module CurationConcerns
2
+ # Actions are decoupled from controller logic so that they may be called from a controller or a background job.
3
+ class FileSetActor
4
+ include CurationConcerns::ManagesEmbargoesActor
5
+
6
+ attr_reader :file_set, :user, :attributes, :curation_concern
7
+
8
+ def initialize(file_set, user)
9
+ # we're setting attributes and curation_concern to bridge the difference
10
+ # between CurationConcerns::FileSetActor and ManagesEmbargoesActor
11
+ @curation_concern = file_set
12
+ @file_set = file_set
13
+ @user = user
14
+ end
15
+
16
+ # Adds the appropriate metadata, visibility and relationships to file_set
17
+ #
18
+ # *Note*: In past versions of Sufia this method did not perform a save because it is mainly used in conjunction with
19
+ # create_content, which also performs a save. However, due to the relationship between Hydra::PCDM objects,
20
+ # we have to save both the parent work and the file_set in order to record the "metadata" relationship
21
+ # between them.
22
+ # @param [String] upload_set_id id of the batch of files that the file was uploaded with
23
+ # @param [ActiveFedora::Base] work the parent work that will contain the file_set.
24
+ # @param [Hash] file_set specifying the visibility, lease and/or embargo of the file set. If you don't provide at least one of visibility, embargo_release_date or lease_expiration_date, visibility will be copied from the parent.
25
+
26
+ def create_metadata(upload_set_id, work, file_set_params = {})
27
+ file_set.apply_depositor_metadata(user)
28
+ now = CurationConcerns::TimeService.time_in_utc
29
+ file_set.date_uploaded = now
30
+ file_set.date_modified = now
31
+ file_set.creator = [user.user_key]
32
+
33
+ if upload_set_id && file_set.respond_to?(:upload_set_id=)
34
+ UploadSet.create(id: upload_set_id) unless UploadSet.exists?(upload_set_id)
35
+ file_set.upload_set_id = upload_set_id
36
+ else
37
+ ActiveFedora::Base.logger.warn 'unable to find UploadSet to attach to'
38
+ end
39
+
40
+ if assign_visibility?(file_set_params)
41
+ interpret_visibility file_set_params
42
+ end
43
+ # TODO: Why do we need to check if work is nil? Shoudn't that raise an error?
44
+ attach_file_to_work(work, file_set, file_set_params) if work
45
+ yield(file_set) if block_given?
46
+ end
47
+
48
+ # Puts the uploaded content into a staging directory. Then kicks off a
49
+ # job to characterize and create derivatives with this on disk variant.
50
+ # Simultaneously moving a preservation copy to the repostiory.
51
+ # TODO: create a job to monitor this directory and prune old files that
52
+ # have made it to the repo
53
+ # @param [ActionDigest::HTTP::UploadedFile, Tempfile] file the file uploaded by the user.
54
+ def create_content(file)
55
+ file_set.label ||= file.original_filename
56
+ file_set.title = [file_set.label] if file_set.title.blank?
57
+ return false unless file_set.save
58
+
59
+ working_file = copy_file_to_working_directory(file, file_set.id)
60
+ IngestFileJob.perform_later(file_set.id, working_file, file.content_type, user.user_key)
61
+ make_derivative(file_set.id, working_file)
62
+ true
63
+ end
64
+
65
+ def revert_content(revision_id)
66
+ file_set.original_file.restore_version(revision_id)
67
+
68
+ return false unless file_set.save
69
+
70
+ CurationConcerns::VersioningService.create(file_set.original_file, user)
71
+
72
+ # Retrieve a copy of the orginal file from the repository
73
+ working_file = copy_repository_resource_to_working_directory(file_set)
74
+ make_derivative(file_set.id, working_file)
75
+
76
+ CurationConcerns.config.callback.run(:after_revert_content, file_set, user, revision_id)
77
+ true
78
+ end
79
+
80
+ def update_content(file)
81
+ working_file = copy_file_to_working_directory(file, file_set.id)
82
+ IngestFileJob.perform_later(file_set.id, working_file, file.content_type, user.user_key)
83
+ make_derivative(file_set.id, working_file)
84
+ CurationConcerns.config.callback.run(:after_update_content, file_set, user)
85
+ true
86
+ end
87
+
88
+ def update_metadata(attributes)
89
+ update_visibility(attributes)
90
+ # attributes.delete(:visibility) # Applying this attribute is handled by update_visibility
91
+ file_set.attributes = attributes
92
+ file_set.date_modified = CurationConcerns::TimeService.time_in_utc
93
+ save do
94
+ CurationConcerns.config.callback.run(:after_update_metadata, file_set, user)
95
+ end
96
+ end
97
+
98
+ def destroy
99
+ file_set.destroy
100
+ # TODO: need to mend the linked list of proxies (possibly wrap with a lock)
101
+ CurationConcerns.config.callback.run(:after_destroy, file_set.id, user)
102
+ end
103
+
104
+ private
105
+
106
+ def make_derivative(file_set_id, working_file)
107
+ CharacterizeJob.perform_later(file_set_id, working_file)
108
+ end
109
+
110
+ # @param [ActionDispatch::Http::UploadedFile] file
111
+ # @param [String] id the identifer
112
+ # @return [String] path of the working file
113
+ def copy_file_to_working_directory(file, id)
114
+ copy_stream_to_working_directory(id, file.original_filename, file)
115
+ end
116
+
117
+ # @param [FileSet] file_set the resource
118
+ # @return [String] path of the working file
119
+ def copy_repository_resource_to_working_directory(file_set)
120
+ file = file_set.original_file
121
+ copy_stream_to_working_directory(file_set.id, file.original_name, StringIO.new(file.content))
122
+ end
123
+
124
+ # @param [String] id the identifer
125
+ # @param [String] name the file name
126
+ # @param [#read] stream the stream to copy to the working directory
127
+ # @return [String] path of the working file
128
+ def copy_stream_to_working_directory(id, name, stream)
129
+ working_path = full_filename(id, name)
130
+ FileUtils.mkdir_p(File.dirname(working_path))
131
+ IO.copy_stream(stream, working_path)
132
+ working_path
133
+ end
134
+
135
+ def full_filename(id, original_name)
136
+ pair = id.scan(/..?/).first(4)
137
+ File.join(CurationConcerns.config.working_path, *pair, original_name)
138
+ end
139
+
140
+ # Takes an optional block and executes the block if the save was successful.
141
+ # returns false if the save was unsuccessful
142
+ def save
143
+ save_tries = 0
144
+ begin
145
+ return false unless file_set.save
146
+ rescue RSolr::Error::Http => error
147
+ ActiveFedora::Base.logger.warn "CurationConcerns::FileSetActor#save Caught RSOLR error #{error.inspect}"
148
+ save_tries += 1
149
+ # fail for good if the tries is greater than 3
150
+ raise error if save_tries >= 3
151
+ sleep 0.01
152
+ retry
153
+ end
154
+ yield if block_given?
155
+ true
156
+ end
157
+
158
+ # Adds a FileSet to the work using ore:Aggregations.
159
+ # Locks to ensure that only one process is operating on
160
+ # the list at a time.
161
+ def attach_file_to_work(work, file_set, file_set_params)
162
+ acquire_lock_for(work.id) do
163
+ # Ensure we have an up-to-date copy of the members association, so
164
+ # that we append to the end of the list.
165
+ work.reload unless work.new_record?
166
+ unless assign_visibility?(file_set_params)
167
+ copy_visibility(work, file_set)
168
+ end
169
+ work.ordered_members << file_set
170
+ # Save the work so the association between the work and the file_set is persisted (head_id)
171
+ work.save
172
+ end
173
+ end
174
+
175
+ def acquire_lock_for(lock_key, &block)
176
+ lock_manager.lock(lock_key, &block)
177
+ end
178
+
179
+ def lock_manager
180
+ @lock_manager ||= CurationConcerns::LockManager.new(
181
+ CurationConcerns.config.lock_time_to_live,
182
+ CurationConcerns.config.lock_retry_count,
183
+ CurationConcerns.config.lock_retry_delay)
184
+ end
185
+
186
+ def assign_visibility?(file_set_params = {})
187
+ !((file_set_params || {}).keys & %w(visibility embargo_release_date lease_expiration_date)).empty?
188
+ end
189
+
190
+ # This method can be overridden in case there is a custom approach for visibility (e.g. embargo)
191
+ def update_visibility(attributes)
192
+ interpret_visibility(attributes) # relies on CurationConcerns::ManagesEmbargoesActor to interpret and apply visibility
193
+ end
194
+
195
+ # copy visibility from source_concern to destination_concern
196
+ def copy_visibility(source_concern, destination_concern)
197
+ destination_concern.visibility = source_concern.visibility
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,19 @@
1
+ module CurationConcerns
2
+ class LeaseActor
3
+ attr_reader :work
4
+
5
+ # @param [Hydra::Works::Work] work
6
+ def initialize(work)
7
+ @work = work
8
+ end
9
+
10
+ # Update the visibility of the work to match the correct state of the lease, then clear the lease date, etc.
11
+ # Saves the lease and the work
12
+ def destroy
13
+ work.lease_visibility! # If the lease has lapsed, update the current visibility.
14
+ work.deactivate_lease!
15
+ work.lease.save!
16
+ work.save!
17
+ end
18
+ end
19
+ end