berkeley_library-av-core 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](https://github.com/BerkeleyLibrary/av-core/actions/workflows/build.yml)
|
|
4
|
+
[](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
|