berkeley_library-av-core 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +391 -0
  3. data/.github/workflows/build.yml +30 -0
  4. data/.gitignore +388 -0
  5. data/.idea/av_core.iml +146 -0
  6. data/.idea/codeStyles/Project.xml +12 -0
  7. data/.idea/codeStyles/codeStyleConfig.xml +5 -0
  8. data/.idea/go.imports.xml +6 -0
  9. data/.idea/inspectionProfiles/Project_Default.xml +37 -0
  10. data/.idea/misc.xml +6 -0
  11. data/.idea/modules.xml +8 -0
  12. data/.idea/vcs.xml +6 -0
  13. data/.rubocop.yml +241 -0
  14. data/.ruby-version +1 -0
  15. data/.simplecov +8 -0
  16. data/CHANGES.md +38 -0
  17. data/Gemfile +3 -0
  18. data/Jenkinsfile +16 -0
  19. data/LICENSE.md +21 -0
  20. data/README.md +20 -0
  21. data/Rakefile +20 -0
  22. data/av_core.gemspec +49 -0
  23. data/lib/berkeley_library/av/config.rb +238 -0
  24. data/lib/berkeley_library/av/constants.rb +30 -0
  25. data/lib/berkeley_library/av/core/module_info.rb +18 -0
  26. data/lib/berkeley_library/av/core.rb +7 -0
  27. data/lib/berkeley_library/av/marc/util.rb +114 -0
  28. data/lib/berkeley_library/av/marc.rb +52 -0
  29. data/lib/berkeley_library/av/metadata/README.md +5 -0
  30. data/lib/berkeley_library/av/metadata/field.rb +110 -0
  31. data/lib/berkeley_library/av/metadata/fields.rb +130 -0
  32. data/lib/berkeley_library/av/metadata/link.rb +28 -0
  33. data/lib/berkeley_library/av/metadata/readers/alma.rb +54 -0
  34. data/lib/berkeley_library/av/metadata/readers/base.rb +53 -0
  35. data/lib/berkeley_library/av/metadata/readers/tind.rb +52 -0
  36. data/lib/berkeley_library/av/metadata/readers.rb +2 -0
  37. data/lib/berkeley_library/av/metadata/source.rb +93 -0
  38. data/lib/berkeley_library/av/metadata/tind_html_metadata_da.json +2076 -0
  39. data/lib/berkeley_library/av/metadata/value.rb +121 -0
  40. data/lib/berkeley_library/av/metadata.rb +103 -0
  41. data/lib/berkeley_library/av/record.rb +86 -0
  42. data/lib/berkeley_library/av/record_id.rb +121 -0
  43. data/lib/berkeley_library/av/record_not_found.rb +7 -0
  44. data/lib/berkeley_library/av/restrictions.rb +36 -0
  45. data/lib/berkeley_library/av/track.rb +132 -0
  46. data/lib/berkeley_library/av/types/duration.rb +67 -0
  47. data/lib/berkeley_library/av/types/file_type.rb +84 -0
  48. data/lib/berkeley_library/av/util.rb +65 -0
  49. data/rakelib/bundle.rake +8 -0
  50. data/rakelib/coverage.rake +11 -0
  51. data/rakelib/gem.rake +54 -0
  52. data/rakelib/rubocop.rake +18 -0
  53. data/rakelib/spec.rake +12 -0
  54. data/spec/.rubocop.yml +116 -0
  55. data/spec/data/10.23.19.JessieLaCavalier.02.mrc +3 -0
  56. data/spec/data/alma/991005939359706532-sru.xml +123 -0
  57. data/spec/data/alma/991034756419706532-sru.xml +162 -0
  58. data/spec/data/alma/991047179369706532-sru.xml +210 -0
  59. data/spec/data/alma/991054360089706532-sru.xml +186 -0
  60. data/spec/data/alma/b11082434-sru.xml +165 -0
  61. data/spec/data/alma/b18538031-sru.xml +123 -0
  62. data/spec/data/alma/b20786580-sru.xml +123 -0
  63. data/spec/data/alma/b22139647-sru.xml +171 -0
  64. data/spec/data/alma/b22139658-sru.xml +282 -0
  65. data/spec/data/alma/b23161018-sru.xml +182 -0
  66. data/spec/data/alma/b23305522-sru.xml +144 -0
  67. data/spec/data/alma/b24071548-sru.xml +136 -0
  68. data/spec/data/alma/b24659129-sru.xml +210 -0
  69. data/spec/data/alma/b25207857-sru.xml +217 -0
  70. data/spec/data/alma/b25716973-sru.xml +186 -0
  71. data/spec/data/alma/b25742488-sru.xml +246 -0
  72. data/spec/data/record-(cityarts)00002.xml +78 -0
  73. data/spec/data/record-(cityarts)00773.xml +94 -0
  74. data/spec/data/record-(clir)00020.xml +153 -0
  75. data/spec/data/record-(miscmat)00615.xml +45 -0
  76. data/spec/data/record-(pacradio)00107.xml +85 -0
  77. data/spec/data/record-(pacradio)01469.xml +82 -0
  78. data/spec/data/record-empty-result.xml +4 -0
  79. data/spec/data/record-multiple-998s-disordered.xml +178 -0
  80. data/spec/data/record-multiple-998s.xml +178 -0
  81. data/spec/data/record-physcolloquia-bk00169017b.xml +78 -0
  82. data/spec/data/record-ragged-998-subfields.xml +122 -0
  83. data/spec/data/record-ragged-998s-multiple-fields.xml +160 -0
  84. data/spec/data/record-redirect-to-login.html +288 -0
  85. data/spec/data/record_id/bibs_with_check_digits.txt +151 -0
  86. data/spec/data/search-1993.xml +158 -0
  87. data/spec/data/search-b23305516.xml +81 -0
  88. data/spec/lib/berkeley_library/av/av_spec.rb +12 -0
  89. data/spec/lib/berkeley_library/av/config_spec.rb +250 -0
  90. data/spec/lib/berkeley_library/av/marc/util_spec.rb +150 -0
  91. data/spec/lib/berkeley_library/av/marc_spec.rb +62 -0
  92. data/spec/lib/berkeley_library/av/metadata/field_spec.rb +81 -0
  93. data/spec/lib/berkeley_library/av/metadata/fields_spec.rb +180 -0
  94. data/spec/lib/berkeley_library/av/metadata/metadata_spec.rb +274 -0
  95. data/spec/lib/berkeley_library/av/metadata/source_spec.rb +261 -0
  96. data/spec/lib/berkeley_library/av/metadata/value_spec.rb +29 -0
  97. data/spec/lib/berkeley_library/av/record_id_spec.rb +72 -0
  98. data/spec/lib/berkeley_library/av/record_spec.rb +284 -0
  99. data/spec/lib/berkeley_library/av/track_spec.rb +335 -0
  100. data/spec/lib/berkeley_library/av/types/duration_spec.rb +91 -0
  101. data/spec/lib/berkeley_library/av/types/file_type_spec.rb +98 -0
  102. data/spec/lib/berkeley_library/av/util_spec.rb +30 -0
  103. data/spec/spec_helper.rb +63 -0
  104. metadata +499 -0
data/.rubocop.yml ADDED
@@ -0,0 +1,241 @@
1
+ inherit_mode:
2
+ merge:
3
+ - Exclude
4
+ - Include
5
+
6
+ AllCops:
7
+ UseCache: false
8
+ # Exclude generated files
9
+ Exclude:
10
+ - 'bin/**/*'
11
+ - 'db/**/*'
12
+ - 'out/**/*'
13
+ # Exclude vendor files in GitHub build
14
+ - 'vendor/**/*'
15
+
16
+ # Allow one line around block body (Layout/EmptyLines will still disallow two or more)
17
+ Layout/EmptyLinesAroundBlockBody:
18
+ Enabled: false
19
+
20
+ # Allow one line around class body (Layout/EmptyLines will still disallow two or more)
21
+ Layout/EmptyLinesAroundClassBody:
22
+ Enabled: false
23
+
24
+ # Allow one line around module body (Layout/EmptyLines will still disallow two or more)
25
+ Layout/EmptyLinesAroundModuleBody:
26
+ Enabled: false
27
+
28
+ # Reasonable line-length check; it's too easy for the cure to be worse than the disease
29
+ Layout/LineLength:
30
+ Max: 150
31
+
32
+ # Make indents consistent regardless of the lengths of variables and method names and whatnot
33
+ Layout/MultilineMethodCallIndentation:
34
+ EnforcedStyle: indented
35
+
36
+ # Produces monsters
37
+ Layout/MultilineOperationIndentation:
38
+ Enabled: false
39
+
40
+ # We meant to do that
41
+ Naming/MemoizedInstanceVariableName:
42
+ Enabled: False
43
+
44
+ # It works in context, trust us
45
+ Naming/MethodParameterName:
46
+ Enabled: False
47
+
48
+ # Confusing and weird
49
+ Naming/VariableNumber:
50
+ Enabled: False
51
+
52
+ # Whether vertical or horizontal is more readable depends on context
53
+ Style/AccessorGrouping:
54
+ Enabled: false
55
+
56
+ # Do what's readable in the context you're in
57
+ Style/AccessModifierDeclarations:
58
+ Enabled: false
59
+
60
+ # 👎 to cultural imperialism
61
+ Style/AsciiComments:
62
+ Enabled: false
63
+
64
+ #
65
+ Style/ClassEqualityComparison:
66
+ Enabled: false
67
+
68
+ # Seriously?
69
+ Style/CommentedKeyword:
70
+ Enabled: False
71
+
72
+ # Disable problematic module documentation check (see https://github.com/bbatsov/rubocop/issues/947)
73
+ Style/Documentation:
74
+ Enabled: false
75
+
76
+ # Adding more line noise to format strings will not improve them
77
+ Style/FormatStringToken:
78
+ Enabled: false
79
+
80
+ # Putting '# frozen_string_literal: true' everywhere does not make the world a better place
81
+ Style/FrozenStringLiteralComment:
82
+ Enabled: false
83
+
84
+ # Requiring the lambda() method just makes wordy calls wordier
85
+ Style/Lambda:
86
+ EnforcedStyle: literal
87
+
88
+ # `foo.positive?` is cute, but it's not actually more readable than `foo > 0`
89
+ Style/NumericPredicate:
90
+ Enabled: false
91
+
92
+ # Don't be unnecessarily redundant
93
+ Style/ReturnNil:
94
+ Enabled: true
95
+ EnforcedStyle: return
96
+
97
+ # Unclear why it's a good idea to give parameters semantically meaningless names
98
+ Style/SingleLineBlockParams:
99
+ Enabled: false
100
+
101
+ # The semantics of `foo&.bar` are a lot less interchangeable with `foo && foo.bar` than RuboCop thinks
102
+ Style/SafeNavigation:
103
+ Enabled: false
104
+
105
+ ############################################################
106
+ # Enable newer cops
107
+
108
+ Style/HashEachMethods: # (new in 0.80)
109
+ Enabled: true
110
+ Style/HashTransformKeys: # (new in 0.80)
111
+ Enabled: true
112
+ Style/HashTransformValues: # (new in 0.80)
113
+ Enabled: true
114
+ Lint/RaiseException: # (new in 0.81)
115
+ Enabled: true
116
+ Lint/StructNewOverride: # (new in 0.81)
117
+ Enabled: true
118
+ Layout/SpaceAroundMethodCallOperator: # (new in 0.82)
119
+ Enabled: true
120
+ Style/ExponentialNotation: # (new in 0.82)
121
+ Enabled: false
122
+ Layout/EmptyLinesAroundAttributeAccessor: # (new in 0.83)
123
+ Enabled: true
124
+ Style/SlicingWithRange: # (new in 0.83)
125
+ Enabled: true
126
+ Lint/DeprecatedOpenSSLConstant: # (new in 0.84)
127
+ Enabled: true
128
+ Lint/MixedRegexpCaptureTypes: # (new in 0.85)
129
+ Enabled: true
130
+ Style/RedundantRegexpCharacterClass: # (new in 0.85)
131
+ Enabled: true
132
+ Style/RedundantRegexpEscape: # (new in 0.85)
133
+ Enabled: true
134
+ Style/RedundantFetchBlock: # (new in 0.86)
135
+ Enabled: true
136
+ Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
137
+ Enabled: true
138
+ Lint/EmptyBlock: # (new in 1.1)
139
+ Enabled: true
140
+ Lint/ToEnumArguments: # (new in 1.1)
141
+ Enabled: true
142
+ Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
143
+ Enabled: true
144
+ Style/ArgumentsForwarding: # (new in 1.1)
145
+ Enabled: true
146
+ Style/DocumentDynamicEvalDefinition: # (new in 1.1)
147
+ Enabled: true
148
+ Style/SwapValues: # (new in 1.1)
149
+ Enabled: true
150
+ Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
151
+ Enabled: true
152
+ Style/CollectionCompact: # (new in 1.2)
153
+ Enabled: true
154
+ Style/NegatedIfElseCondition: # (new in 1.2)
155
+ Enabled: true
156
+ Lint/DuplicateBranch: # (new in 1.3)
157
+ Enabled: true
158
+ Lint/EmptyClass: # (new in 1.3)
159
+ Enabled: true
160
+ Style/NilLambda: # (new in 1.3)
161
+ Enabled: true
162
+ Style/RedundantArgument: # (new in 1.4)
163
+ Enabled: true
164
+ Lint/UnexpectedBlockArity: # (new in 1.5)
165
+ Enabled: true
166
+ Layout/SpaceBeforeBrackets: # (new in 1.7)
167
+ Enabled: true
168
+ Lint/AmbiguousAssignment: # (new in 1.7)
169
+ Enabled: true
170
+ Style/HashExcept: # (new in 1.7)
171
+ Enabled: true
172
+ Lint/DeprecatedConstants: # (new in 1.8)
173
+ Enabled: true
174
+ Lint/LambdaWithoutLiteralBlock: # (new in 1.8)
175
+ Enabled: true
176
+ Lint/RedundantDirGlobSort: # (new in 1.8)
177
+ Enabled: true
178
+ Style/EndlessMethod: # (new in 1.8)
179
+ Enabled: true
180
+ Lint/NumberedParameterAssignment: # (new in 1.9)
181
+ Enabled: true
182
+ Lint/OrAssignmentToConstant: # (new in 1.9)
183
+ Enabled: true
184
+ Lint/SymbolConversion: # (new in 1.9)
185
+ Enabled: true
186
+ Lint/TripleQuotes: # (new in 1.9)
187
+ Enabled: true
188
+ Style/IfWithBooleanLiteralBranches: # (new in 1.9)
189
+ Enabled: true
190
+ Gemspec/DateAssignment: # (new in 1.10)
191
+ Enabled: true
192
+ Style/HashConversion: # (new in 1.10)
193
+ Enabled: true
194
+ Style/StringChars: # (new in 1.12)
195
+ Enabled: true
196
+ Lint/EmptyInPattern: # (new in 1.16)
197
+ Enabled: true
198
+ Style/InPatternThen: # (new in 1.16)
199
+ Enabled: true
200
+ Style/MultilineInPatternThen: # (new in 1.16)
201
+ Enabled: true
202
+ Style/QuotedSymbols: # (new in 1.16)
203
+ Enabled: true
204
+ Layout/LineEndStringConcatenationIndentation: # (new in 1.18)
205
+ Enabled: true
206
+ Naming/InclusiveLanguage: # (new in 1.18)
207
+ Enabled: true
208
+ Lint/AmbiguousRange: # new in 1.19
209
+ Enabled: true
210
+ Style/RedundantSelfAssignmentBranch: # new in 1.19
211
+ Enabled: true
212
+ Lint/AmbiguousOperatorPrecedence: # new in 1.21
213
+ Enabled: true
214
+ Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
215
+ Enabled: true
216
+ Lint/RequireRelativeSelfPath: # new in 1.22
217
+ Enabled: true
218
+ Security/IoMethods: # new in 1.22
219
+ Enabled: true
220
+ Style/NumberedParameters: # new in 1.22
221
+ Enabled: true
222
+ Style/NumberedParametersLimit: # new in 1.22
223
+ Enabled: true
224
+ Style/SelectByRegexp: # new in 1.22
225
+ Enabled: true
226
+ Gemspec/RequireMFA: # new in 1.23
227
+ Enabled: true
228
+ Lint/UselessRuby2Keywords: # new in 1.23
229
+ Enabled: true
230
+ Style/OpenStructUse: # new in 1.23
231
+ Enabled: true
232
+ Naming/BlockForwarding: # new in 1.24
233
+ Enabled: true
234
+ Style/FileRead: # new in 1.24
235
+ Enabled: true
236
+ Style/FileWrite: # new in 1.24
237
+ Enabled: true
238
+ Style/MapToHash: # new in 1.24
239
+ Enabled: true
240
+ Style/NestedFileDirname: # new in 1.26
241
+ Enabled: true
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.1.3
data/.simplecov ADDED
@@ -0,0 +1,8 @@
1
+ require 'simplecov-rcov'
2
+
3
+ SimpleCov.start 'rails' do
4
+ add_filter 'module_info.rb'
5
+ coverage_dir 'artifacts'
6
+ formatter SimpleCov::Formatter::RcovFormatter
7
+ minimum_coverage 100
8
+ end
data/CHANGES.md ADDED
@@ -0,0 +1,38 @@
1
+ # 0.3.0 (2022-02-01)
2
+
3
+ - Rename `Record#ucb_access?` and `Metadata#ucb_access?` to `calnet_or_ip?` for clarity.
4
+ - Remove the following methods:
5
+ - `Record#player_link_text`
6
+ - `Metadata#player_link_text`
7
+ - `Metadata#player_url`
8
+ - Remove the following constants:
9
+ - `AV::Constants::RESTRICTIONS_CALNET`
10
+ - `AV::Constants::RESTRICTIONS_UCB_IP`
11
+ - `AV::Constants::RESTRICTIONS`
12
+ - `AV::Constants::RESTRICTIONS_NONE`
13
+
14
+ # 0.2.3 (2022-01-05)
15
+
16
+ - `Record#bib_number` and `Metadata#bib_number` now return nil instead of raising an
17
+ exception when the MARC field expected to contain a Millennium bib number contains
18
+ something else.
19
+
20
+ # 0.2.2 (2022-01-03)
21
+
22
+ - Add `Record#calnet_only?` in addition to `Record#ucb_access?`
23
+
24
+ # 0.2.1 (2021-11-08)
25
+
26
+ - Add `Metadata#calnet_only?` in addition to `Metadata#ucb_access?`
27
+ - Support declaring restrictions in 998$r as well as 95640$z (Alma) or 85642$y (TIND)
28
+
29
+ # 0.2.0 (2021-10-21)
30
+
31
+ - Add Alma support
32
+ - Remove Millennium support
33
+ - Switch to [`BerkeleyLibrary/logging`](https://github.com/BerkeleyLibrary/logging)
34
+
35
+ # 0.1.0 (2021-08-05)
36
+
37
+ - Initial prerelease
38
+ - Send a custom `User-Agent` header to deal with new TIND firewall rules.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Jenkinsfile ADDED
@@ -0,0 +1,16 @@
1
+ dockerComposePipeline(
2
+ commands: [
3
+ 'bundle exec rake coverage',
4
+ 'bundle exec rake rubocop',
5
+ 'bundle exec rake bundle:audit',
6
+ 'bundle exec rake gem'
7
+ ],
8
+ artifacts: [
9
+ junit: 'artifacts/rspec/**/*.xml',
10
+ html : [
11
+ 'Code Coverage': 'artifacts/rcov',
12
+ 'RuboCop' : 'artifacts/rubocop'
13
+ ],
14
+ raw : ['artifacts/**/*.gem']
15
+ ]
16
+ )
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ # The MIT License (MIT)
2
+
3
+ Copyright © 2023 The Regents of the University of California
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a
6
+ copy of this software and associated documentation files (the “Software”),
7
+ to deal in the Software without restriction, including without limitation
8
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
+ and/or sell copies of the Software, and to permit persons to whom the
10
+ Software is furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # BerkeleyLibrary::AV::Core
2
+
3
+ [![Build Status](https://github.com/BerkeleyLibrary/av-core/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/BerkeleyLibrary/av-core/actions/workflows/build.yml)
4
+ [![Gem Version](https://img.shields.io/gem/v/berkeley_library-av-core.svg)](https://rubygems.org/gems/berkeley_library-av-core)
5
+
6
+ Gem for UC Berkeley Library shared audio/video code.
7
+
8
+ ## Installation
9
+
10
+ In your Gemfile:
11
+
12
+ ```ruby
13
+ gem 'berkeley_library-av-core'
14
+ ```
15
+
16
+ In your code:
17
+
18
+ ```ruby
19
+ require 'berkeley_library/av/core'
20
+ ```
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile', __dir__)
2
+ require 'bundler/setup' # Set up gems listed in the Gemfile.
3
+
4
+ # ------------------------------------------------------------
5
+ # Application code
6
+
7
+ File.expand_path('lib', __dir__).tap do |lib|
8
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
9
+ end
10
+
11
+ # ------------------------------------------------------------
12
+ # CI
13
+
14
+ ENV['RAILS_ENV'] = 'test' if ENV['CI']
15
+
16
+ # ------------------------------------------------------------
17
+ # Custom tasks
18
+
19
+ desc 'Run tests, check test coverage, check code style, check for vulnerabilities, build gem'
20
+ task default: %i[coverage rubocop bundle:audit gem]
data/av_core.gemspec ADDED
@@ -0,0 +1,49 @@
1
+ File.expand_path('lib', __dir__).tap do |lib|
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ end
4
+
5
+ ruby_version_file = File.expand_path('.ruby-version', __dir__)
6
+ ruby_version_exact = File.read(ruby_version_file).strip
7
+ ruby_minor_version = ruby_version_exact.gsub(/^(\d+\.\d+).*/, '\1')
8
+
9
+ require 'berkeley_library/av/core/module_info'
10
+
11
+ Gem::Specification.new do |spec|
12
+ spec.name = BerkeleyLibrary::AV::Core::ModuleInfo::NAME
13
+ spec.author = BerkeleyLibrary::AV::Core::ModuleInfo::AUTHOR
14
+ spec.email = BerkeleyLibrary::AV::Core::ModuleInfo::AUTHOR_EMAIL
15
+ spec.summary = BerkeleyLibrary::AV::Core::ModuleInfo::SUMMARY
16
+ spec.description = BerkeleyLibrary::AV::Core::ModuleInfo::DESCRIPTION
17
+ spec.license = BerkeleyLibrary::AV::Core::ModuleInfo::LICENSE
18
+ spec.version = BerkeleyLibrary::AV::Core::ModuleInfo::VERSION
19
+ spec.homepage = BerkeleyLibrary::AV::Core::ModuleInfo::HOMEPAGE
20
+
21
+ spec.files = `git ls-files -z -- ':!:Dockerfile' ':!:docker-compose.yml'`.split("\x0")
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.required_ruby_version = ">= #{ruby_minor_version}"
26
+
27
+ spec.add_dependency 'berkeley_library-logging', '~> 0.2'
28
+ spec.add_dependency 'berkeley_library-marc', '~> 0.2', '>= 0.2.1'
29
+ spec.add_dependency 'berkeley_library-util', '~> 0.1', '>= 0.1.1'
30
+ spec.add_dependency 'ruby-marc-spec', '~> 0.1', '>= 0.1.3'
31
+ spec.add_dependency 'typesafe_enum', '~> 0.3'
32
+
33
+ spec.add_development_dependency 'brakeman', '~> 4.9'
34
+ spec.add_development_dependency 'bundle-audit', '~> 0.1'
35
+ spec.add_development_dependency 'ci_reporter_rspec', '~> 1.0'
36
+ spec.add_development_dependency 'colorize', '~> 0.8'
37
+ spec.add_development_dependency 'dotenv', '~> 2.7'
38
+ spec.add_development_dependency 'irb', '~> 1.2' # workaroundfor https://github.com/bundler/bundler/issues/6929
39
+ spec.add_development_dependency 'listen', '>= 3.0.5', '< 3.2'
40
+ spec.add_development_dependency 'rake', '~> 13.0'
41
+ spec.add_development_dependency 'rspec-support', '~> 3.9'
42
+ spec.add_development_dependency 'rubocop', '1.26.0'
43
+ spec.add_development_dependency 'rubocop-rake', '~> 0.6.0'
44
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.4.0'
45
+ spec.add_development_dependency 'simplecov', '~> 0.21'
46
+ spec.add_development_dependency 'simplecov-rcov', '~> 0.2'
47
+ spec.add_development_dependency 'webmock', '~> 3.8'
48
+ spec.metadata['rubygems_mfa_required'] = 'true'
49
+ end
@@ -0,0 +1,238 @@
1
+ require 'berkeley_library/util/uris'
2
+
3
+ module BerkeleyLibrary
4
+ module AV
5
+ # rubocop:disable Metrics/ClassLength
6
+ class Config
7
+ REQUIRED_SETTINGS = %i[
8
+ avplayer_base_uri
9
+ alma_sru_host
10
+ alma_primo_host
11
+ alma_institution_code
12
+ alma_permalink_key
13
+ tind_base_uri
14
+ wowza_base_uri
15
+ ].freeze
16
+
17
+ class << self
18
+ include BerkeleyLibrary::Util
19
+
20
+ # Alma SRU hostname, e.g. UC Berkeley = berkeley.alma.exlibrisgroup.com
21
+ def alma_sru_host
22
+ @alma_sru_host ||= value_from_rails_config(:alma_sru_host)
23
+ end
24
+
25
+ # Alma institution code, e.g. UC Berkeley = 01UCS_BER
26
+ def alma_institution_code
27
+ @alma_institution_code ||= value_from_rails_config(:alma_institution_code)
28
+ end
29
+
30
+ # Alma Primo host, e.g. UC Berkeley = search.library.berkeley.edu
31
+ def alma_primo_host
32
+ @alma_primo_host ||= value_from_rails_config(:alma_primo_host)
33
+ end
34
+
35
+ # View state key to use when generating Alma permalinks, e.g. `iqob43`; see
36
+ # https://knowledge.exlibrisgroup.com/Primo/Knowledge_Articles/What_is_the_key_in_short_permalinks%3F
37
+ def alma_permalink_key
38
+ @alma_permalink_key ||= value_from_rails_config(:alma_permalink_key)
39
+ end
40
+
41
+ def alma_sru_base_uri
42
+ ensure_configured(:alma_sru_host, :alma_institution_code)
43
+
44
+ sru_base_uri_for(alma_sru_host, alma_institution_code)
45
+ end
46
+
47
+ def alma_permalink_base_uri
48
+ ensure_configured(:alma_primo_host, :alma_institution_code, :alma_permalink_key)
49
+
50
+ primo_permalink_base_uri_for(alma_primo_host, alma_institution_code, alma_permalink_key)
51
+ end
52
+
53
+ def avplayer_base_uri
54
+ @avplayer_base_uri ||= uri_from_rails_config(:avplayer_base_uri)
55
+ end
56
+
57
+ def tind_base_uri
58
+ @tind_base_uri ||= uri_from_rails_config(:tind_base_uri)
59
+ end
60
+
61
+ def wowza_base_uri
62
+ @wowza_base_uri ||= uri_from_rails_config(:wowza_base_uri)
63
+ end
64
+
65
+ # Sets the AV Player base URI
66
+ #
67
+ # @param [URI, String] uri the base URI
68
+ # @return [URI] the URI
69
+ # @raise URI::InvalidURIError if the URI cannot be parsed, or is not HTTP/HTTPS
70
+ def avplayer_base_uri=(uri)
71
+ @avplayer_base_uri = clean_uri(uri)
72
+ end
73
+
74
+ # Sets the Alma SRU hostname
75
+ #
76
+ # @param [String] hostname the hostname
77
+ # @return [String] the hostname
78
+ # @raise ArgumentError if the hostname is nil or empty
79
+ # @raise URI::InvalidURIError if the resulting SRU URI cannot be parsed
80
+ def alma_sru_host=(hostname)
81
+ raise ArgumentError, "Invalid hostname: #{hostname.inspect}" if hostname.nil? || hostname.empty?
82
+
83
+ sru_uri = sru_base_uri_for(hostname, '') # Catch bad URIs early
84
+ @alma_sru_host = sru_uri.host
85
+ end
86
+
87
+ # Sets the Alma Primo hostname
88
+ #
89
+ # @param [String] hostname the hostname
90
+ # @return [String] the hostname
91
+ # @raise ArgumentError if the hostname is nil or empty
92
+ # @raise URI::InvalidURIError if the resulting Primo permalink URI cannot be parsed
93
+ def alma_primo_host=(hostname)
94
+ raise ArgumentError, "Invalid hostname: #{hostname.inspect}" if hostname.nil? || hostname.empty?
95
+
96
+ primo_uri = primo_permalink_base_uri_for(hostname, 'XXX', 'abc123') # Catch bad URIs early
97
+ @alma_primo_host = primo_uri.host
98
+ end
99
+
100
+ # Sets the Alma SRU institution code
101
+ #
102
+ # @param [String] inst_code the institution code
103
+ # @return [String] the institution code
104
+ # @raise ArgumentError if the institution code is nil or empty
105
+ # @raise URI::InvalidURIError if the resulting SRU URI cannot be parsed
106
+ def alma_institution_code=(inst_code)
107
+ raise ArgumentError, "Invalid institution code: #{inst_code.inspect}" if inst_code.nil? || inst_code.empty?
108
+
109
+ sru_uri = sru_base_uri_for('example.org', inst_code) # Catch bad URIs early
110
+ @alma_institution_code = sru_uri.path.split('/').last
111
+ end
112
+
113
+ # Sets the Alma permalink key
114
+ #
115
+ # @param [String] permalink_key the permalink key
116
+ # @return [String] the permalink key
117
+ # @raise ArgumentError if the permalink key is nil or empty
118
+ # @raise URI::InvalidURIError if the resulting Primo permalink URI cannot be parsed
119
+ def alma_permalink_key=(permalink_key)
120
+ raise ArgumentError, "Invalid permalink key: #{permalink_key.inspect}" if permalink_key.nil? || permalink_key.empty?
121
+
122
+ sru_uri = primo_permalink_base_uri_for('example.org', 'XXX', permalink_key) # Catch bad URIs early
123
+ @alma_permalink_key = sru_uri.path.split('/').last
124
+ end
125
+
126
+ # Sets the TIND base URI
127
+ #
128
+ # @param [URI, String] uri the base URI
129
+ # @return [URI] the URI
130
+ # @raise URI::InvalidURIError if the URI cannot be parsed, or is not HTTP/HTTPS
131
+ def tind_base_uri=(uri)
132
+ @tind_base_uri = clean_uri(uri)
133
+ end
134
+
135
+ # Sets the Wowza base URI
136
+ #
137
+ # @param [URI, String] uri the base URI
138
+ # @return [URI] the URI
139
+ # @raise URI::InvalidURIError if the URI cannot be parsed, or is not HTTP/HTTPS
140
+ def wowza_base_uri=(uri)
141
+ @wowza_base_uri = clean_uri(uri)
142
+ end
143
+
144
+ # Returns the list of missing required settings.
145
+ # @return [Array<Symbol>] the missing settings.
146
+ def missing(*settings)
147
+ settings = REQUIRED_SETTINGS if settings.empty?
148
+ [].tap do |unset|
149
+ settings.each do |setting|
150
+ unset << setting unless set?(setting)
151
+ end
152
+ end
153
+ end
154
+
155
+ def ensure_configured(*settings)
156
+ return if (missing_settings = missing(*settings)).empty?
157
+
158
+ raise ArgumentError, "Missing AV configuration settings: #{missing_settings.join(', ')}"
159
+ end
160
+
161
+ private
162
+
163
+ def sru_base_uri_for(domain, inst_code)
164
+ URIs.append("https://#{domain}/view/sru/", inst_code)
165
+ end
166
+
167
+ def primo_permalink_base_uri_for(alma_primo_host, inst_code, key)
168
+ URIs.append("https://#{alma_primo_host}/", 'permalink', inst_code, key)
169
+ end
170
+
171
+ # Returns a URI
172
+ # @param [URI, String] url the base URL
173
+ # @return [URI] the URI
174
+ # @raise URI::InvalidURIError if the URI cannot be parsed, or is not HTTP/HTTPS
175
+ def clean_uri(url)
176
+ BerkeleyLibrary::Util::URIs.uri_or_nil(url).tap do |uri|
177
+ raise URI::InvalidURIError, 'url cannot be nil' unless uri
178
+ raise URI::InvalidURIError, 'URL must have a scheme' unless (scheme = uri.scheme)
179
+ raise URI::InvalidURIError, 'URL must be HTTP or HTTPS' unless scheme.start_with?('http')
180
+ end
181
+ end
182
+
183
+ def uri_from_rails_config(sym)
184
+ return unless (config = rails_config)
185
+
186
+ result = config.send(sym)
187
+ clean_uri(result)
188
+ end
189
+
190
+ # Gets the specified value from the Rails configuraiton
191
+ # @return [Object, nil] the value, or nil if there is no Rails configuration or the value is not set
192
+ def value_from_rails_config(sym)
193
+ return unless (config = rails_config)
194
+
195
+ config.send(sym)
196
+ end
197
+
198
+ def rails_config
199
+ return unless defined?(Rails)
200
+ return unless (application = Rails.application)
201
+
202
+ application.config
203
+ end
204
+
205
+ def set?(setting)
206
+ !Config.send(setting).nil?
207
+ end
208
+
209
+ def clear!
210
+ REQUIRED_SETTINGS.each do |attr|
211
+ ivar_name = "@#{attr}"
212
+ next unless instance_variable_defined?(ivar_name)
213
+
214
+ send(:remove_instance_variable, ivar_name)
215
+ end
216
+ end
217
+ end
218
+
219
+ private_class_method :new
220
+
221
+ end
222
+ # rubocop:enable Metrics/ClassLength
223
+
224
+ class << self
225
+ def config
226
+ AV::Config
227
+ end
228
+
229
+ def configure(&)
230
+ class_eval(&)
231
+ end
232
+
233
+ def configured?
234
+ Config.missing.empty?
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,30 @@
1
+ module BerkeleyLibrary
2
+ module AV
3
+ module Constants
4
+ TAG_TITLE_FIELD = '245'.freeze
5
+ TAG_LINK_FIELD = '856'.freeze
6
+ TAG_TRACK_FIELD = '998'.freeze
7
+ TAG_TIND_ID = '001'.freeze
8
+
9
+ # TODO: use marc/spec
10
+ TAG_TIND_CATALOG_ID = '901'.freeze
11
+ SUBFIELD_CODE_TIND_BIB_NUMBER = 'm'.freeze
12
+
13
+ # TODO: use marc/spec
14
+ TAG_ALMA_MIGRATION_INFO = '996'.freeze
15
+ SUBFIELD_CODE_ALMA_BIB_NUMBER = 'a'.freeze
16
+
17
+ SUBFIELD_CODE_DURATION = :a
18
+ SUBFIELD_CODE_TITLE = :t
19
+ SUBFIELD_CODE_PATH = :g
20
+ SUBFIELD_CODES_TRACKS = [SUBFIELD_CODE_DURATION, SUBFIELD_CODE_TITLE, SUBFIELD_CODE_PATH].freeze
21
+
22
+ UNKNOWN_TITLE = 'Unknown title'.freeze
23
+
24
+ # '99' is the Alma prefix for a Metadata Management System ID
25
+ ALMA_RECORD_RE = /^(?<type>99)[0-9]{9,12}(?<institution>[0-9]{4})$/
26
+ MILLENNIUM_RECORD_RE = /^b(?<digits>[0-9]{8})(?<check>[0-9ax])?$/
27
+ OCLC_RECORD_RE = /^o[0-9]+$/
28
+ end
29
+ end
30
+ end