sdr-client 2.12.0 → 2.13.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/.rubocop_todo.yml +24 -20
  4. data/Gemfile.lock +11 -8
  5. data/exe/sdr_redesigned +10 -0
  6. data/lib/sdr_client/redesigned_client/authenticator.rb +40 -0
  7. data/lib/sdr_client/redesigned_client/cli/config.rb +32 -0
  8. data/lib/sdr_client/redesigned_client/cli/credentials.rb +35 -0
  9. data/lib/sdr_client/redesigned_client/cli/update.rb +186 -0
  10. data/lib/sdr_client/redesigned_client/cli.rb +198 -0
  11. data/lib/sdr_client/redesigned_client/create_resource.rb +71 -0
  12. data/lib/sdr_client/redesigned_client/deposit.rb +115 -0
  13. data/lib/sdr_client/redesigned_client/direct_upload_request.rb +45 -0
  14. data/lib/sdr_client/redesigned_client/direct_upload_response.rb +9 -0
  15. data/lib/sdr_client/redesigned_client/file.rb +100 -0
  16. data/lib/sdr_client/redesigned_client/file_set.rb +53 -0
  17. data/lib/sdr_client/redesigned_client/file_type_file_set_strategy.rb +13 -0
  18. data/lib/sdr_client/redesigned_client/find.rb +42 -0
  19. data/lib/sdr_client/redesigned_client/image_file_set_strategy.rb +13 -0
  20. data/lib/sdr_client/redesigned_client/job_status.rb +74 -0
  21. data/lib/sdr_client/redesigned_client/matching_file_grouping_strategy.rb +19 -0
  22. data/lib/sdr_client/redesigned_client/metadata.rb +64 -0
  23. data/lib/sdr_client/redesigned_client/operations/md5.rb +16 -0
  24. data/lib/sdr_client/redesigned_client/operations/mime_type.rb +17 -0
  25. data/lib/sdr_client/redesigned_client/operations/sha1.rb +16 -0
  26. data/lib/sdr_client/redesigned_client/request_builder.rb +171 -0
  27. data/lib/sdr_client/redesigned_client/single_file_grouping_strategy.rb +14 -0
  28. data/lib/sdr_client/redesigned_client/structural_grouper.rb +72 -0
  29. data/lib/sdr_client/redesigned_client/structural_metadata_builder.rb +51 -0
  30. data/lib/sdr_client/redesigned_client/unexpected_response.rb +25 -0
  31. data/lib/sdr_client/redesigned_client/update_dro_with_file_identifiers.rb +35 -0
  32. data/lib/sdr_client/redesigned_client/update_resource.rb +61 -0
  33. data/lib/sdr_client/redesigned_client/upload_files.rb +71 -0
  34. data/lib/sdr_client/redesigned_client/upload_files_metadata_builder.rb +40 -0
  35. data/lib/sdr_client/redesigned_client.rb +192 -0
  36. data/lib/sdr_client/version.rb +1 -1
  37. data/lib/sdr_client.rb +3 -1
  38. metadata +35 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe0ad47a766a04fce46a16e1621cd320ef29a17f1fad3db5f6f541e93538555a
4
- data.tar.gz: d8915f97ada0d121b4a2e0c8cb6f125ac3e20486378d53bf7de7a5ab0fe85690
3
+ metadata.gz: 25f723e2fc1c9873d8e6413cb9477f2392e1f29b8042af1fa508e9cda1f80a09
4
+ data.tar.gz: f49cd7219620c202f7f70b1beff293118307bdfe0e3617f2ccb59da6d09f1113
5
5
  SHA512:
6
- metadata.gz: 15a80598a92338adec41fc75d53b890a2fe4b95e5c08e16e438d0766ca91a0f75198a282a29dfdaae7bc7ea4d9f2864dca36d07a1cce0fec078b770a776a5b1c
7
- data.tar.gz: 47b5e9bce9ac469b559e68bc1a40ba722f6a921d370aa9af6fe80ea27988016e4c68820a2819e667fc697d050ea2d0c4c7a51ec75d83b52caa2cfded4e14baf7
6
+ metadata.gz: d63b8074bf9490b46bcf3c59e67e2289783311b1283c6440937295b5ddd9e6b698f770549d9aee61190cd47fb72dd67273401688e71cee76b7c45b3d70dd5604
7
+ data.tar.gz: 15b93ebd94830c35e59cd425b6e10b409cfe0acc2b3c06cfb7f763fb5cf80c13af3f38e2ad6a86e8579f9d17ee547e401d384bc8a0256427c5d5d734ce947839
data/.rubocop.yml CHANGED
@@ -22,6 +22,9 @@ Metrics/ClassLength:
22
22
  - 'lib/sdr_client/cli.rb'
23
23
  - 'lib/sdr_client/deposit/request.rb'
24
24
  - 'lib/sdr_client/update.rb'
25
+ - 'lib/sdr_client/redesigned_client.rb'
26
+ - 'lib/sdr_client/redesigned_client/cli.rb'
27
+ - 'lib/sdr_client/redesigned_client/cli/update.rb'
25
28
 
26
29
  Naming/FileName:
27
30
  Exclude:
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config --auto-gen-only-exclude`
3
- # on 2023-09-11 17:08:41 UTC using RuboCop version 1.56.3.
3
+ # on 2024-03-26 19:28:56 UTC using RuboCop version 1.62.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -20,26 +20,30 @@ Lint/NoReturnInBeginEndBlocks:
20
20
 
21
21
  # Offense count: 2
22
22
  # This cop supports safe autocorrection (--autocorrect).
23
- # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods.
23
+ # Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods.
24
24
  Lint/UnusedMethodArgument:
25
25
  Exclude:
26
26
  - 'lib/sdr_client/deposit/file_type_file_set_strategy.rb'
27
27
  - 'lib/sdr_client/deposit/image_file_set_strategy.rb'
28
28
 
29
- # Offense count: 4
29
+ # Offense count: 11
30
30
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
31
31
  Metrics/AbcSize:
32
32
  Exclude:
33
33
  - 'lib/sdr_client/cli.rb'
34
+ - 'lib/sdr_client/redesigned_client.rb'
35
+ - 'lib/sdr_client/redesigned_client/cli.rb'
36
+ - 'lib/sdr_client/redesigned_client/cli/update.rb'
34
37
  - 'lib/sdr_client/update.rb'
35
38
 
36
- # Offense count: 1
39
+ # Offense count: 2
37
40
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
38
41
  Metrics/CyclomaticComplexity:
39
42
  Exclude:
43
+ - 'lib/sdr_client/redesigned_client/cli/update.rb'
40
44
  - 'lib/sdr_client/update.rb'
41
45
 
42
- # Offense count: 12
46
+ # Offense count: 15
43
47
  # Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
44
48
  Metrics/MethodLength:
45
49
  Exclude:
@@ -49,14 +53,18 @@ Metrics/MethodLength:
49
53
  - 'lib/sdr_client/deposit/process.rb'
50
54
  - 'lib/sdr_client/deposit/request.rb'
51
55
  - 'lib/sdr_client/login.rb'
56
+ - 'lib/sdr_client/redesigned_client/cli.rb'
57
+ - 'lib/sdr_client/redesigned_client/cli/update.rb'
52
58
  - 'lib/sdr_client/update.rb'
53
59
 
54
- # Offense count: 11
60
+ # Offense count: 15
55
61
  # Configuration parameters: Max, CountAsOne.
56
62
  RSpec/ExampleLength:
57
63
  Exclude:
58
- - 'spec/sdr_client/deposit_spec.rb'
59
64
  - 'spec/sdr_client/deposit_model_spec.rb'
65
+ - 'spec/sdr_client/deposit_spec.rb'
66
+ - 'spec/sdr_client/redesigned_client/deposit_spec.rb'
67
+ - 'spec/sdr_client/redesigned_client/upload_files_metadata_builder_spec.rb'
60
68
  - 'spec/sdr_client/update_spec.rb'
61
69
 
62
70
  # Offense count: 1
@@ -66,16 +74,19 @@ RSpec/MessageSpies:
66
74
  Exclude:
67
75
  - 'spec/sdr_client/deposit_spec.rb'
68
76
 
69
- # Offense count: 13
77
+ # Offense count: 19
70
78
  # Configuration parameters: Max.
71
79
  RSpec/MultipleExpectations:
72
80
  Exclude:
73
81
  - 'spec/sdr_client/connection_spec.rb'
74
82
  - 'spec/sdr_client/deposit/metadata_builder_spec.rb'
83
+ - 'spec/sdr_client/deposit_model_spec.rb'
75
84
  - 'spec/sdr_client/deposit_spec.rb'
76
85
  - 'spec/sdr_client/find_spec.rb'
77
86
  - 'spec/sdr_client/login_spec.rb'
78
- - 'spec/sdr_client/deposit_model_spec.rb'
87
+ - 'spec/sdr_client/redesigned_client/deposit_spec.rb'
88
+ - 'spec/sdr_client/redesigned_client/job_status_spec.rb'
89
+ - 'spec/sdr_client/redesigned_client/upload_files_spec.rb'
79
90
 
80
91
  # Offense count: 24
81
92
  # Configuration parameters: EnforcedStyle, IgnoreSharedExamples.
@@ -89,7 +100,7 @@ RSpec/NamedSubject:
89
100
  - 'spec/sdr_client/deposit/process_spec.rb'
90
101
  - 'spec/sdr_client/login_spec.rb'
91
102
 
92
- # Offense count: 19
103
+ # Offense count: 25
93
104
  # Configuration parameters: Max, AllowedGroups.
94
105
  RSpec/NestedGroups:
95
106
  Exclude:
@@ -97,6 +108,7 @@ RSpec/NestedGroups:
97
108
  - 'spec/sdr_client/deposit/model_process_spec.rb'
98
109
  - 'spec/sdr_client/deposit/process_spec.rb'
99
110
  - 'spec/sdr_client/login_spec.rb'
111
+ - 'spec/sdr_client/redesigned_client/job_status_spec.rb'
100
112
  - 'spec/sdr_client/update_spec.rb'
101
113
 
102
114
  # Offense count: 5
@@ -105,15 +117,6 @@ RSpec/ReceiveMessages:
105
117
  Exclude:
106
118
  - 'spec/sdr_client/update_spec.rb'
107
119
 
108
- # Offense count: 2
109
- # Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata.
110
- # Include: **/*_spec.rb
111
- RSpec/SpecFilePathFormat:
112
- Exclude:
113
- - '**/spec/routing/**/*'
114
- - 'spec/sdr_client/client_spec.rb'
115
- - 'spec/sdr_client/model_deposit_spec.rb'
116
-
117
120
  # Offense count: 21
118
121
  # This cop supports safe autocorrection (--autocorrect).
119
122
  Style/KeywordParametersOrder:
@@ -121,10 +124,11 @@ Style/KeywordParametersOrder:
121
124
  - 'lib/sdr_client/deposit.rb'
122
125
  - 'lib/sdr_client/deposit/request.rb'
123
126
 
124
- # Offense count: 1
127
+ # Offense count: 2
125
128
  # This cop supports safe autocorrection (--autocorrect).
126
129
  Style/MultilineTernaryOperator:
127
130
  Exclude:
131
+ - 'lib/sdr_client/redesigned_client/cli/update.rb'
128
132
  - 'lib/sdr_client/update.rb'
129
133
 
130
134
  # Offense count: 2
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sdr-client (2.12.0)
4
+ sdr-client (2.13.0.beta2)
5
5
  activesupport
6
6
  cocina-models (~> 0.96.0)
7
7
  config
@@ -97,7 +97,7 @@ GEM
97
97
  i18n (1.14.4)
98
98
  concurrent-ruby (~> 1.0)
99
99
  ice_nine (0.11.2)
100
- json (2.7.1)
100
+ json (2.7.2)
101
101
  jsonpath (1.1.5)
102
102
  multi_json
103
103
  language_server-protocol (3.17.0.3)
@@ -109,9 +109,9 @@ GEM
109
109
  mutex_m (0.2.0)
110
110
  net-http (0.4.1)
111
111
  uri
112
- nokogiri (1.16.3-x86_64-darwin)
112
+ nokogiri (1.16.4-x86_64-darwin)
113
113
  racc (~> 1.4)
114
- nokogiri (1.16.3-x86_64-linux)
114
+ nokogiri (1.16.4-x86_64-linux)
115
115
  racc (~> 1.4)
116
116
  openapi3_parser (0.9.2)
117
117
  commonmarker (~> 0.17)
@@ -123,10 +123,10 @@ GEM
123
123
  racc
124
124
  patience_diff (1.2.0)
125
125
  optimist (~> 3.0)
126
- public_suffix (5.0.4)
126
+ public_suffix (5.0.5)
127
127
  racc (1.7.3)
128
128
  rainbow (3.1.1)
129
- rake (13.1.0)
129
+ rake (13.2.1)
130
130
  regexp_parser (2.9.0)
131
131
  rexml (3.2.6)
132
132
  rspec (3.13.0)
@@ -146,7 +146,7 @@ GEM
146
146
  rspec-core (>= 2, < 4, != 2.12.0)
147
147
  rss (0.3.0)
148
148
  rexml
149
- rubocop (1.62.1)
149
+ rubocop (1.63.1)
150
150
  json (~> 2.3)
151
151
  language_server-protocol (>= 3.17.0)
152
152
  parallel (~> 1.10)
@@ -165,10 +165,13 @@ GEM
165
165
  rubocop (~> 1.41)
166
166
  rubocop-rake (0.6.0)
167
167
  rubocop (~> 1.0)
168
- rubocop-rspec (2.27.1)
168
+ rubocop-rspec (2.29.1)
169
169
  rubocop (~> 1.40)
170
170
  rubocop-capybara (~> 2.17)
171
171
  rubocop-factory_bot (~> 2.22)
172
+ rubocop-rspec_rails (~> 2.28)
173
+ rubocop-rspec_rails (2.28.3)
174
+ rubocop (~> 1.40)
172
175
  ruby-progressbar (1.13.0)
173
176
  simplecov (0.22.0)
174
177
  docile (~> 1.1)
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift 'lib'
5
+
6
+ require 'sdr_client'
7
+ require 'sdr_client/redesigned_client'
8
+ require 'sdr_client/redesigned_client/cli'
9
+
10
+ SdrClient::RedesignedClient::CLI.start(ARGV)
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ class RedesignedClient
5
+ # Fetch a token from the SDR API using user credentials
6
+ class Authenticator
7
+ def self.token
8
+ new.token
9
+ end
10
+
11
+ # Request an access_token
12
+ def token
13
+ response = connection.post(path, request_body)
14
+
15
+ UnexpectedResponse.call(response) unless response.success?
16
+
17
+ JSON.parse(response.body)['token']
18
+ end
19
+
20
+ private
21
+
22
+ def request_body
23
+ JSON.generate(
24
+ {
25
+ email: SdrClient::RedesignedClient.config.email,
26
+ password: SdrClient::RedesignedClient.config.password
27
+ }
28
+ )
29
+ end
30
+
31
+ def path
32
+ '/v1/auth/login'
33
+ end
34
+
35
+ def connection
36
+ Faraday.new(url: SdrClient::RedesignedClient.config.url)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'config'
4
+
5
+ Config.setup do |config|
6
+ # Name of the constant exposing loaded settings
7
+ config.const_name = 'Settings'
8
+
9
+ # Load environment variables from the `ENV` object and override any
10
+ # settings defined in files.
11
+ config.use_env = true
12
+
13
+ # Define ENV variable prefix deciding which variables to load into
14
+ # config.
15
+ config.env_prefix = 'SETTINGS'
16
+
17
+ # What string to use as level separator for settings loaded from ENV
18
+ # variables. Default value of '.' works well with Heroku, but you might
19
+ # want to change it for example for '__' to easy override settings from
20
+ # command line, where using dots in variable names might not be allowed
21
+ # (eg. Bash).
22
+ config.env_separator = '__'
23
+
24
+ # Ability to process variables names:
25
+ # * nil - no change
26
+ # * :downcase - convert to lower case
27
+ config.env_converter = :downcase
28
+ end
29
+
30
+ Config.load_and_set_settings(
31
+ File.join(__dir__, '../../../..', 'config/settings.yml')
32
+ )
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ class RedesignedClient
5
+ class CLI < Thor
6
+ # The stored credentials
7
+ class Credentials
8
+ # @param [String] a json string that contains a field 'token'
9
+ def self.write(body)
10
+ token = JSON.parse(body).fetch('token')
11
+ FileUtils.mkdir_p(credentials_path, mode: 0o700)
12
+ File.atomic_write(credentials_file) { |file| file.write(token) }
13
+ File.chmod(0o600, credentials_file)
14
+ end
15
+
16
+ def self.read
17
+ return unless ::File.exist?(credentials_file)
18
+
19
+ creds = File.read(credentials_file, chomp: true)
20
+ return if creds.nil?
21
+
22
+ creds
23
+ end
24
+
25
+ def self.credentials_path
26
+ @credentials_path ||= File.join(Dir.home, '.sdr')
27
+ end
28
+
29
+ def self.credentials_file
30
+ File.join(credentials_path, 'credentials')
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ class RedesignedClient
5
+ class CLI < Thor
6
+ # Update a resource given command-line options
7
+ class Update
8
+ # @return [String] job id for the background job result
9
+ def self.run(druid, **options)
10
+ new(druid, **options).run
11
+ end
12
+
13
+ def initialize(druid, **options)
14
+ @druid = druid
15
+ @options = options
16
+ end
17
+
18
+ # @return [String] job id for the background job result
19
+ def run
20
+ client.update_model(model: updated_cocina_object)
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :druid, :options
26
+
27
+ def client
28
+ SdrClient::RedesignedClient.instance
29
+ end
30
+
31
+ def updated_cocina_object
32
+ @updated_cocina_object ||=
33
+ original_cocina_object.then { |cocina_object| update_cocina(cocina_object) }
34
+ .then { |cocina_object| update_apo(cocina_object) }
35
+ .then { |cocina_object| update_collection(cocina_object) }
36
+ .then { |cocina_object| update_copyright(cocina_object) }
37
+ .then { |cocina_object| update_use_and_reproduction(cocina_object) }
38
+ .then { |cocina_object| update_license(cocina_object) }
39
+ .then { |cocina_object| update_access(cocina_object) }
40
+ end
41
+
42
+ def original_cocina_object
43
+ Cocina::Models.build(
44
+ client.find(object_id: druid)
45
+ )
46
+ end
47
+
48
+ def cocina_hash_from_file
49
+ @cocina_hash_from_file ||= JSON.parse(File.read(options[:cocina_file]), symbolize_names: true)
50
+ end
51
+
52
+ def cocina_hash_from_pipe
53
+ @cocina_hash_from_pipe ||= JSON.parse($stdin.read, symbolize_names: true)
54
+ end
55
+
56
+ # Update the Cocina in full
57
+ def update_cocina(cocina_object)
58
+ if options[:cocina_file]
59
+ update_cocina_from_file(cocina_object)
60
+ elsif options[:cocina_pipe]
61
+ update_cocina_from_pipe(cocina_object)
62
+ else
63
+ cocina_object
64
+ end
65
+ end
66
+
67
+ def update_cocina_from_file(cocina_object)
68
+ if !File.file?(options[:cocina_file]) || !File.readable?(options[:cocina_file])
69
+ raise "File not found: #{options[:cocina_file]}"
70
+ end
71
+
72
+ # NOTE: We may want to add more checks later. For now, make sure the identifiers match.
73
+ if cocina_object.externalIdentifier != cocina_hash_from_file[:externalIdentifier]
74
+ raise "Cocina in #{options[:cocina_file]} has a different external identifier " \
75
+ "than #{cocina_object.externalIdentifier}: #{cocina_hash_from_file[:externalIdentifier]}"
76
+ end
77
+
78
+ cocina_object.new(cocina_hash_from_file)
79
+ end
80
+
81
+ def update_cocina_from_pipe(cocina_object)
82
+ raise 'No pipe provided' unless $stdin.stat.pipe?
83
+
84
+ # NOTE: We may want to add more checks later. For now, make sure the identifiers match.
85
+ if cocina_object.externalIdentifier != cocina_hash_from_pipe[:externalIdentifier]
86
+ raise 'Cocina piped in has a different external identifier than ' \
87
+ "#{cocina_object.externalIdentifier}: #{cocina_hash_from_pipe[:externalIdentifier]}"
88
+ end
89
+
90
+ cocina_object.new(cocina_hash_from_pipe)
91
+ end
92
+
93
+ # Update the APO of a Cocina item if the options specify a new one, else return the original
94
+ def update_apo(cocina_object)
95
+ return cocina_object unless options[:apo]
96
+
97
+ cocina_object.new(
98
+ administrative: cocina_object.administrative.new(
99
+ hasAdminPolicy: options[:apo]
100
+ )
101
+ )
102
+ end
103
+
104
+ # Update the collection of a Cocina item if the options specify a new one, else return the original
105
+ def update_collection(cocina_object)
106
+ return cocina_object unless options[:collection]
107
+
108
+ cocina_object.new(
109
+ structural: cocina_object.structural.new(
110
+ isMemberOf: Array(options[:collection])
111
+ )
112
+ )
113
+ end
114
+
115
+ # Update the copyright of a Cocina item if the options specify a new one, else return the original
116
+ def update_copyright(cocina_object)
117
+ return cocina_object unless options[:copyright]
118
+
119
+ cocina_object.new(
120
+ access: cocina_object.access.new(
121
+ copyright: options[:copyright]
122
+ )
123
+ )
124
+ end
125
+
126
+ # Update the use and reproduction statement of a Cocina item if the
127
+ # options specify a new one, else return the original
128
+ def update_use_and_reproduction(cocina_object)
129
+ return cocina_object unless options[:use_and_reproduction]
130
+
131
+ cocina_object.new(
132
+ access: cocina_object.access.new(
133
+ useAndReproductionStatement: options[:use_and_reproduction]
134
+ )
135
+ )
136
+ end
137
+
138
+ # Update the license of a Cocina item if the options specify a new one, else return the original
139
+ def update_license(cocina_object)
140
+ return cocina_object unless options[:license]
141
+
142
+ cocina_object.new(
143
+ access: cocina_object.access.new(
144
+ license: options[:license]
145
+ )
146
+ )
147
+ end
148
+
149
+ # Update the access of a Cocina item if the options specify a new one, else return the original
150
+ def update_access(cocina_object)
151
+ return cocina_object unless options[:view] || options[:download] || options[:location] || options[:cdl]
152
+
153
+ cocina_object.new(
154
+ access: cocina_object.access.new(
155
+ view: options[:view],
156
+ download: options[:download],
157
+ location: options[:location],
158
+ controlledDigitalLending: !!options[:cdl] # rubocop:disable Style/DoubleNegation
159
+ ),
160
+ structural: cocina_object.structural.new(
161
+ contains: cocina_object.structural.contains.map do |file_set|
162
+ file_set.new(
163
+ structural: file_set.structural.new(
164
+ contains: file_set.structural.contains.map do |file|
165
+ file.new(
166
+ access: file.access.new(
167
+ view: options[:view],
168
+ download: options[:download],
169
+ location: options[:location],
170
+ controlledDigitalLending: !!options[:cdl] # rubocop:disable Style/DoubleNegation
171
+ ),
172
+ administrative: options[:view] == 'dark' ?
173
+ { publish: false, shelve: false, sdrPreserve: file.administrative.sdrPreserve } :
174
+ file.administrative
175
+ )
176
+ end
177
+ )
178
+ )
179
+ end
180
+ )
181
+ )
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end