curation_concerns-models 0.1.0 → 0.2.0

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