berkeley_library-av-core 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.dockerignore +391 -0
- data/.github/workflows/build.yml +30 -0
- data/.gitignore +388 -0
- data/.idea/av_core.iml +146 -0
- data/.idea/codeStyles/Project.xml +12 -0
- data/.idea/codeStyles/codeStyleConfig.xml +5 -0
- data/.idea/go.imports.xml +6 -0
- data/.idea/inspectionProfiles/Project_Default.xml +37 -0
- data/.idea/misc.xml +6 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.rubocop.yml +241 -0
- data/.ruby-version +1 -0
- data/.simplecov +8 -0
- data/CHANGES.md +38 -0
- data/Gemfile +3 -0
- data/Jenkinsfile +16 -0
- data/LICENSE.md +21 -0
- data/README.md +20 -0
- data/Rakefile +20 -0
- data/av_core.gemspec +49 -0
- data/lib/berkeley_library/av/config.rb +238 -0
- data/lib/berkeley_library/av/constants.rb +30 -0
- data/lib/berkeley_library/av/core/module_info.rb +18 -0
- data/lib/berkeley_library/av/core.rb +7 -0
- data/lib/berkeley_library/av/marc/util.rb +114 -0
- data/lib/berkeley_library/av/marc.rb +52 -0
- data/lib/berkeley_library/av/metadata/README.md +5 -0
- data/lib/berkeley_library/av/metadata/field.rb +110 -0
- data/lib/berkeley_library/av/metadata/fields.rb +130 -0
- data/lib/berkeley_library/av/metadata/link.rb +28 -0
- data/lib/berkeley_library/av/metadata/readers/alma.rb +54 -0
- data/lib/berkeley_library/av/metadata/readers/base.rb +53 -0
- data/lib/berkeley_library/av/metadata/readers/tind.rb +52 -0
- data/lib/berkeley_library/av/metadata/readers.rb +2 -0
- data/lib/berkeley_library/av/metadata/source.rb +93 -0
- data/lib/berkeley_library/av/metadata/tind_html_metadata_da.json +2076 -0
- data/lib/berkeley_library/av/metadata/value.rb +121 -0
- data/lib/berkeley_library/av/metadata.rb +103 -0
- data/lib/berkeley_library/av/record.rb +86 -0
- data/lib/berkeley_library/av/record_id.rb +121 -0
- data/lib/berkeley_library/av/record_not_found.rb +7 -0
- data/lib/berkeley_library/av/restrictions.rb +36 -0
- data/lib/berkeley_library/av/track.rb +132 -0
- data/lib/berkeley_library/av/types/duration.rb +67 -0
- data/lib/berkeley_library/av/types/file_type.rb +84 -0
- data/lib/berkeley_library/av/util.rb +65 -0
- data/rakelib/bundle.rake +8 -0
- data/rakelib/coverage.rake +11 -0
- data/rakelib/gem.rake +54 -0
- data/rakelib/rubocop.rake +18 -0
- data/rakelib/spec.rake +12 -0
- data/spec/.rubocop.yml +116 -0
- data/spec/data/10.23.19.JessieLaCavalier.02.mrc +3 -0
- data/spec/data/alma/991005939359706532-sru.xml +123 -0
- data/spec/data/alma/991034756419706532-sru.xml +162 -0
- data/spec/data/alma/991047179369706532-sru.xml +210 -0
- data/spec/data/alma/991054360089706532-sru.xml +186 -0
- data/spec/data/alma/b11082434-sru.xml +165 -0
- data/spec/data/alma/b18538031-sru.xml +123 -0
- data/spec/data/alma/b20786580-sru.xml +123 -0
- data/spec/data/alma/b22139647-sru.xml +171 -0
- data/spec/data/alma/b22139658-sru.xml +282 -0
- data/spec/data/alma/b23161018-sru.xml +182 -0
- data/spec/data/alma/b23305522-sru.xml +144 -0
- data/spec/data/alma/b24071548-sru.xml +136 -0
- data/spec/data/alma/b24659129-sru.xml +210 -0
- data/spec/data/alma/b25207857-sru.xml +217 -0
- data/spec/data/alma/b25716973-sru.xml +186 -0
- data/spec/data/alma/b25742488-sru.xml +246 -0
- data/spec/data/record-(cityarts)00002.xml +78 -0
- data/spec/data/record-(cityarts)00773.xml +94 -0
- data/spec/data/record-(clir)00020.xml +153 -0
- data/spec/data/record-(miscmat)00615.xml +45 -0
- data/spec/data/record-(pacradio)00107.xml +85 -0
- data/spec/data/record-(pacradio)01469.xml +82 -0
- data/spec/data/record-empty-result.xml +4 -0
- data/spec/data/record-multiple-998s-disordered.xml +178 -0
- data/spec/data/record-multiple-998s.xml +178 -0
- data/spec/data/record-physcolloquia-bk00169017b.xml +78 -0
- data/spec/data/record-ragged-998-subfields.xml +122 -0
- data/spec/data/record-ragged-998s-multiple-fields.xml +160 -0
- data/spec/data/record-redirect-to-login.html +288 -0
- data/spec/data/record_id/bibs_with_check_digits.txt +151 -0
- data/spec/data/search-1993.xml +158 -0
- data/spec/data/search-b23305516.xml +81 -0
- data/spec/lib/berkeley_library/av/av_spec.rb +12 -0
- data/spec/lib/berkeley_library/av/config_spec.rb +250 -0
- data/spec/lib/berkeley_library/av/marc/util_spec.rb +150 -0
- data/spec/lib/berkeley_library/av/marc_spec.rb +62 -0
- data/spec/lib/berkeley_library/av/metadata/field_spec.rb +81 -0
- data/spec/lib/berkeley_library/av/metadata/fields_spec.rb +180 -0
- data/spec/lib/berkeley_library/av/metadata/metadata_spec.rb +274 -0
- data/spec/lib/berkeley_library/av/metadata/source_spec.rb +261 -0
- data/spec/lib/berkeley_library/av/metadata/value_spec.rb +29 -0
- data/spec/lib/berkeley_library/av/record_id_spec.rb +72 -0
- data/spec/lib/berkeley_library/av/record_spec.rb +284 -0
- data/spec/lib/berkeley_library/av/track_spec.rb +335 -0
- data/spec/lib/berkeley_library/av/types/duration_spec.rb +91 -0
- data/spec/lib/berkeley_library/av/types/file_type_spec.rb +98 -0
- data/spec/lib/berkeley_library/av/util_spec.rb +30 -0
- data/spec/spec_helper.rb +63 -0
- 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
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
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
|