cocina-models 0.122.0 → 0.123.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 +4 -4
- data/.circleci/config.yml +1 -1
- data/Gemfile.lock +22 -6
- data/README.md +1 -1
- data/cocina-models.gemspec +1 -0
- data/description_types.yml +0 -2
- data/docs/description_types.md +0 -2
- data/identifier_source_codes.yml +210 -0
- data/lib/cocina/models/validators/composite_description_validator.rb +7 -1
- data/lib/cocina/models/validators/description_date_time_visitor_validator.rb +18 -9
- data/lib/cocina/models/validators/description_event_date_visitor_validator.rb +38 -0
- data/lib/cocina/models/validators/description_form_resource_type_visitor_validator.rb +46 -0
- data/lib/cocina/models/validators/description_identifier_source_code_visitor_validator.rb +41 -0
- data/lib/cocina/models/validators/description_location_source_code_visitor_validator.rb +43 -0
- data/lib/cocina/models/validators/description_role_source_code_visitor_validator.rb +44 -0
- data/lib/cocina/models/validators/description_subject_temporal_encoding_visitor_validator.rb +43 -0
- data/lib/cocina/models/validators/marc_relator_role_validator.rb +83 -0
- data/lib/cocina/models/validators/validator.rb +2 -1
- data/lib/cocina/models/version.rb +1 -1
- data/location_source_codes.yml +483 -0
- data/resource_type_values.yml +30 -0
- data/schema.json +78 -6
- data/temporal_subject_encoding_codes.yml +8 -0
- metadata +26 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 00e220a27c041178441f3a9372469f6f4aeacd6b9cf73bec45b36d0dfc8e8f1a
|
|
4
|
+
data.tar.gz: e6b6e939d33c2bbc9e88c99bdfef996b23d40df59667cf9f7c1b63b3b2a2b6ba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8fa102a60d4d216b439f514051d34afd07e57105afefd751d1c1b8f07411b876c5475237a0a577fb1240ac6eb564918ebf9a372d3596107f2787d041de8c9f77
|
|
7
|
+
data.tar.gz: 7eb1f0771c848747c833437e3aeb4fb616de5716bae81a8f1ba83a048ba8364953eb47332bae622b91b830807eb39395d0a186a8347605bed662ebc4ecec4807
|
data/.circleci/config.yml
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
cocina-models (0.
|
|
4
|
+
cocina-models (0.123.0)
|
|
5
5
|
activesupport
|
|
6
|
+
cocina_display
|
|
6
7
|
deprecation
|
|
7
8
|
dry-struct (~> 1.0)
|
|
8
9
|
dry-types (~> 1.1)
|
|
@@ -36,6 +37,14 @@ GEM
|
|
|
36
37
|
base64 (0.3.0)
|
|
37
38
|
bigdecimal (4.1.2)
|
|
38
39
|
builder (3.3.0)
|
|
40
|
+
cocina_display (2.6.0)
|
|
41
|
+
activesupport (>= 7)
|
|
42
|
+
edtf (~> 3.2)
|
|
43
|
+
geo_coord (~> 0.2)
|
|
44
|
+
i18n
|
|
45
|
+
iso8601 (~> 0.13.0)
|
|
46
|
+
janeway-jsonpath (>= 0.6, < 2)
|
|
47
|
+
zeitwerk (~> 2.7)
|
|
39
48
|
concurrent-ruby (1.3.6)
|
|
40
49
|
connection_pool (3.0.2)
|
|
41
50
|
csv (3.3.5)
|
|
@@ -81,6 +90,7 @@ GEM
|
|
|
81
90
|
logger
|
|
82
91
|
faraday-net_http (3.4.4)
|
|
83
92
|
net-http (~> 0.5)
|
|
93
|
+
geo_coord (0.2.0)
|
|
84
94
|
i18n (1.14.8)
|
|
85
95
|
concurrent-ruby (~> 1.0)
|
|
86
96
|
ice_nine (0.11.2)
|
|
@@ -90,7 +100,9 @@ GEM
|
|
|
90
100
|
prism (>= 1.3.0)
|
|
91
101
|
rdoc (>= 4.0.0)
|
|
92
102
|
reline (>= 0.4.2)
|
|
93
|
-
|
|
103
|
+
iso8601 (0.13.0)
|
|
104
|
+
janeway-jsonpath (1.0.0)
|
|
105
|
+
json (2.19.9)
|
|
94
106
|
jsonschema_rs (0.46.5-arm64-darwin)
|
|
95
107
|
bigdecimal (>= 3.1, < 5)
|
|
96
108
|
jsonschema_rs (0.46.5-x86_64-linux)
|
|
@@ -219,8 +231,9 @@ CHECKSUMS
|
|
|
219
231
|
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
|
|
220
232
|
bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
|
|
221
233
|
builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
|
|
222
|
-
bundler (4.0.
|
|
223
|
-
cocina-models (0.
|
|
234
|
+
bundler (4.0.14) sha256=d09a0a965cf772266a7e49e83610be7c2f4e49e61134c42a56804bb383cc24b8
|
|
235
|
+
cocina-models (0.123.0)
|
|
236
|
+
cocina_display (2.6.0) sha256=a30e4bd638023371985ab641164e4dbbb12fe9a669a168c1b8e2eac2e37739f4
|
|
224
237
|
concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
|
|
225
238
|
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
|
|
226
239
|
csv (3.3.5) sha256=6e5134ac3383ef728b7f02725d9872934f523cb40b961479f69cf3afa6c8e73f
|
|
@@ -240,11 +253,14 @@ CHECKSUMS
|
|
|
240
253
|
erb (6.0.4) sha256=38e3803694be357fe2bfe312487c74beaf9fb4e5beb3e22498952fe1645b95d9
|
|
241
254
|
faraday (2.14.2) sha256=73ccb9994a9e8648f010e32eca2ae82e41c57860aa10932cda29418b9e0223ad
|
|
242
255
|
faraday-net_http (3.4.4) sha256=0e78af151747ed1b00f33e25973b4bc220d7f16c00c39676817c8b12331eb588
|
|
256
|
+
geo_coord (0.2.0) sha256=ae4e2dc5799deafa4db9138f3d7e85cf5e7dbd00b3b8395f1e1dbd34e007d7e8
|
|
243
257
|
i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5
|
|
244
258
|
ice_nine (0.11.2) sha256=5d506a7d2723d5592dc121b9928e4931742730131f22a1a37649df1c1e2e63db
|
|
245
259
|
io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
|
|
246
260
|
irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3
|
|
247
|
-
|
|
261
|
+
iso8601 (0.13.0) sha256=298c2b15b7be5fa95a1372813d36a2257656cd8e906dfbc1f5cb409851425aa2
|
|
262
|
+
janeway-jsonpath (1.0.0) sha256=c8293f009f2aea9487ddee3067ca735a1f758eb1c8834ff4fab3ffd06c56d0a3
|
|
263
|
+
json (2.19.9) sha256=9b9025b7cdddafa38d316eca0b2358488e42d417045c1b90d216a9fefe46b79a
|
|
248
264
|
jsonschema_rs (0.46.5-arm64-darwin) sha256=e80414ed67f0956d3e06474a2fa076fc4a7b722f00e5d7142b70289c016ac6f1
|
|
249
265
|
jsonschema_rs (0.46.5-x86_64-linux) sha256=345c65ec7a5abf8879b9c9356752f0fdf4c9926f6480458fc32803a871b5cbb3
|
|
250
266
|
language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
|
|
@@ -295,4 +311,4 @@ CHECKSUMS
|
|
|
295
311
|
zeitwerk (2.8.2) sha256=7212a61311083c604184b1ea2574b9aa05cd14f855a0841c06985cabe9181d12
|
|
296
312
|
|
|
297
313
|
BUNDLED WITH
|
|
298
|
-
4.0.
|
|
314
|
+
4.0.14
|
data/README.md
CHANGED
|
@@ -62,7 +62,7 @@ Beyond what is necessary to test the generator, the Cocina model classes are not
|
|
|
62
62
|
|
|
63
63
|
## Testing validation changes
|
|
64
64
|
|
|
65
|
-
If there is a possibility that a model, mapping, or validation change will conflict with some existing objects then `bin/validate-data` should be used for testing. This operates on
|
|
65
|
+
If there is a possibility that a model, mapping, or validation change will conflict with some existing objects then `bin/validate-data` should be used for testing. This operates on an export of objects from the repository and reports any validation errors. You may get the file by running the script [bin/export-cocina-head-versions](https://github.com/sul-dlss/dor-services-app#export-cocina-json-data) and downloading the data file to your computer. See the [DSA README](https://github.com/sul-dlss/dor-services-app#scheduled-cocina-json-data-exports) for more info about the files and locations. Running a full validation takes about 2 hours.
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
Alternatively, you can use [validate-cocina](https://github.com/sul-dlss/dor-services-app/blob/main/bin/validate-cocina) for testing. This must be run on the `sdr-infra` VM since it requires deploying a branch of cocina-models. It is slower than using `bin/validate-data`, but all of the data is completely up to date.
|
data/cocina-models.gemspec
CHANGED
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
|
25
25
|
spec.required_ruby_version = '>= 3.4'
|
|
26
26
|
|
|
27
27
|
spec.add_dependency 'activesupport'
|
|
28
|
+
spec.add_dependency 'cocina_display'
|
|
28
29
|
spec.add_dependency 'deprecation'
|
|
29
30
|
spec.add_dependency 'dry-struct', '~> 1.0'
|
|
30
31
|
spec.add_dependency 'dry-types', '~> 1.1'
|
data/description_types.yml
CHANGED
|
@@ -46,8 +46,6 @@ contributor:
|
|
|
46
46
|
description: An institution or other corporate or collective body.
|
|
47
47
|
- value: person
|
|
48
48
|
description: An individual identity.
|
|
49
|
-
- value: unspecified others
|
|
50
|
-
description: Designator for one or more additional contributors not named individually.
|
|
51
49
|
contributor.identifier:
|
|
52
50
|
- value: ORCID
|
|
53
51
|
description: Identifier from orcid.org.
|
data/docs/description_types.md
CHANGED
|
@@ -49,8 +49,6 @@ _Path: contributor.type_
|
|
|
49
49
|
* An institution or other corporate or collective body.
|
|
50
50
|
* person
|
|
51
51
|
* An individual identity.
|
|
52
|
-
* unspecified others
|
|
53
|
-
* Designator for one or more additional contributors not named individually.
|
|
54
52
|
## Contributor identifier types
|
|
55
53
|
_Path: contributor.identifier.type_
|
|
56
54
|
* ORCID
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# LC Standard Identifier Source Codes
|
|
2
|
+
# Source: https://www.loc.gov/standards/sourcelist/standard-identifier.html
|
|
3
|
+
# Additional codes: swets, apis
|
|
4
|
+
- agorha
|
|
5
|
+
- agrovoc
|
|
6
|
+
- allmovie
|
|
7
|
+
- allmusic
|
|
8
|
+
- allocine
|
|
9
|
+
- amnbo
|
|
10
|
+
- ansi
|
|
11
|
+
- apis
|
|
12
|
+
- archinl
|
|
13
|
+
- archinpe
|
|
14
|
+
- archinpr
|
|
15
|
+
- archna
|
|
16
|
+
- archns
|
|
17
|
+
- ark
|
|
18
|
+
- artsy
|
|
19
|
+
- artukart
|
|
20
|
+
- artukaw
|
|
21
|
+
- atg
|
|
22
|
+
- balat
|
|
23
|
+
- bbcth
|
|
24
|
+
- bdrc
|
|
25
|
+
- bdusc
|
|
26
|
+
- belvku
|
|
27
|
+
- belvwrk
|
|
28
|
+
- benezit
|
|
29
|
+
- bew
|
|
30
|
+
- bfi
|
|
31
|
+
- bibbi
|
|
32
|
+
- bigenc
|
|
33
|
+
- bnfcg
|
|
34
|
+
- bpn
|
|
35
|
+
- bsi
|
|
36
|
+
- cabt
|
|
37
|
+
- cana
|
|
38
|
+
- cantic
|
|
39
|
+
- cbwpid
|
|
40
|
+
- cerl
|
|
41
|
+
- cgndb
|
|
42
|
+
- clara
|
|
43
|
+
- cnbksy
|
|
44
|
+
- csfdcz
|
|
45
|
+
- danacode
|
|
46
|
+
- darome
|
|
47
|
+
- datoses
|
|
48
|
+
- discogs
|
|
49
|
+
- dkfilm
|
|
50
|
+
- dma
|
|
51
|
+
- doi
|
|
52
|
+
- dpb
|
|
53
|
+
- ean
|
|
54
|
+
- ecli
|
|
55
|
+
- eidr
|
|
56
|
+
- emlo
|
|
57
|
+
- fast
|
|
58
|
+
- fidecp
|
|
59
|
+
- filmaff
|
|
60
|
+
- filmport
|
|
61
|
+
- findagr
|
|
62
|
+
- fisa
|
|
63
|
+
- freebase
|
|
64
|
+
- fuoc
|
|
65
|
+
- gacsch
|
|
66
|
+
- gec
|
|
67
|
+
- geogndb
|
|
68
|
+
- geonames
|
|
69
|
+
- geprishisp
|
|
70
|
+
- gettyaat
|
|
71
|
+
- gettyart
|
|
72
|
+
- gettyobj
|
|
73
|
+
- gettytgn
|
|
74
|
+
- gettyulan
|
|
75
|
+
- gnd
|
|
76
|
+
- gnis
|
|
77
|
+
- goodra
|
|
78
|
+
- gtaa
|
|
79
|
+
- gtin-14
|
|
80
|
+
- hdl
|
|
81
|
+
- iaafa
|
|
82
|
+
- ibdb
|
|
83
|
+
- iconauth
|
|
84
|
+
- idref
|
|
85
|
+
- imdb
|
|
86
|
+
- isan
|
|
87
|
+
- isbn
|
|
88
|
+
- isbn-a
|
|
89
|
+
- isbnre
|
|
90
|
+
- isbnsbn
|
|
91
|
+
- isfdbau
|
|
92
|
+
- isfdbaw
|
|
93
|
+
- isfdbma
|
|
94
|
+
- isfdbpu
|
|
95
|
+
- isil
|
|
96
|
+
- ismn
|
|
97
|
+
- isni
|
|
98
|
+
- iso
|
|
99
|
+
- isrc
|
|
100
|
+
- issn
|
|
101
|
+
- issn-l
|
|
102
|
+
- issue-number
|
|
103
|
+
- istc
|
|
104
|
+
- iswc
|
|
105
|
+
- it-acnp
|
|
106
|
+
- itar
|
|
107
|
+
- kda
|
|
108
|
+
- kdw
|
|
109
|
+
- kinopo
|
|
110
|
+
- knpam
|
|
111
|
+
- kulturnav
|
|
112
|
+
- lattes
|
|
113
|
+
- lccn
|
|
114
|
+
- lcmd
|
|
115
|
+
- lcmpt
|
|
116
|
+
- lei
|
|
117
|
+
- libaus
|
|
118
|
+
- lmhl
|
|
119
|
+
- local
|
|
120
|
+
- margaz
|
|
121
|
+
- matrix-number
|
|
122
|
+
- mesh
|
|
123
|
+
- mocofo
|
|
124
|
+
- moma
|
|
125
|
+
- morana
|
|
126
|
+
- moviemetf
|
|
127
|
+
- moviemetr
|
|
128
|
+
- munzing
|
|
129
|
+
- muscl
|
|
130
|
+
- music-plate
|
|
131
|
+
- music-publisher
|
|
132
|
+
- musicb
|
|
133
|
+
- nacat
|
|
134
|
+
- nagb
|
|
135
|
+
- natgazfid
|
|
136
|
+
- nga
|
|
137
|
+
- ngva
|
|
138
|
+
- ngvw
|
|
139
|
+
- nipo
|
|
140
|
+
- nlg
|
|
141
|
+
- nndb
|
|
142
|
+
- npg
|
|
143
|
+
- nzggn
|
|
144
|
+
- odnb
|
|
145
|
+
- ofdb
|
|
146
|
+
- onix
|
|
147
|
+
- opensm
|
|
148
|
+
- orcid
|
|
149
|
+
- orgnr
|
|
150
|
+
- oxforddnb
|
|
151
|
+
- pcadbu
|
|
152
|
+
- pcadpe
|
|
153
|
+
- pcadpf
|
|
154
|
+
- permid
|
|
155
|
+
- picnypl
|
|
156
|
+
- pleiades
|
|
157
|
+
- pnta
|
|
158
|
+
- porthu
|
|
159
|
+
- prabook
|
|
160
|
+
- rbmsbt
|
|
161
|
+
- rbmsgt
|
|
162
|
+
- rbmspe
|
|
163
|
+
- rbmsppe
|
|
164
|
+
- rbmspt
|
|
165
|
+
- rbmsrd
|
|
166
|
+
- rbmste
|
|
167
|
+
- rid
|
|
168
|
+
- rkda
|
|
169
|
+
- ror
|
|
170
|
+
- s2a3bd
|
|
171
|
+
- saam
|
|
172
|
+
- scholaru
|
|
173
|
+
- scope
|
|
174
|
+
- scopus
|
|
175
|
+
- sici
|
|
176
|
+
- smgp
|
|
177
|
+
- snac
|
|
178
|
+
- spotify
|
|
179
|
+
- sprfbsb
|
|
180
|
+
- sprfbsk
|
|
181
|
+
- sprfcbb
|
|
182
|
+
- sprfcfb
|
|
183
|
+
- sprfhoc
|
|
184
|
+
- sprfoly
|
|
185
|
+
- sprfpfb
|
|
186
|
+
- ssaut
|
|
187
|
+
- stock-number
|
|
188
|
+
- strn
|
|
189
|
+
- stw
|
|
190
|
+
- svfilm
|
|
191
|
+
- swets
|
|
192
|
+
- tatearid
|
|
193
|
+
- theatr
|
|
194
|
+
- tpce
|
|
195
|
+
- trove
|
|
196
|
+
- unescot
|
|
197
|
+
- upc
|
|
198
|
+
- uri
|
|
199
|
+
- urn
|
|
200
|
+
- vd16
|
|
201
|
+
- vd17
|
|
202
|
+
- vd18
|
|
203
|
+
- vgmdb
|
|
204
|
+
- viaf
|
|
205
|
+
- videorecording-identifier
|
|
206
|
+
- wikidata
|
|
207
|
+
- wndla
|
|
208
|
+
- xgamea
|
|
209
|
+
- ysopai
|
|
210
|
+
- zbaut
|
|
@@ -7,8 +7,14 @@ module Cocina
|
|
|
7
7
|
class CompositeDescriptionValidator
|
|
8
8
|
VALIDATORS = [
|
|
9
9
|
DescriptionTypesVisitorValidator,
|
|
10
|
+
DescriptionIdentifierSourceCodeVisitorValidator,
|
|
11
|
+
DescriptionRoleSourceCodeVisitorValidator,
|
|
12
|
+
DescriptionFormResourceTypeVisitorValidator,
|
|
10
13
|
DescriptionValuesVisitorValidator,
|
|
11
|
-
DescriptionDateTimeVisitorValidator
|
|
14
|
+
DescriptionDateTimeVisitorValidator,
|
|
15
|
+
DescriptionEventDateVisitorValidator,
|
|
16
|
+
DescriptionSubjectTemporalEncodingVisitorValidator,
|
|
17
|
+
DescriptionLocationSourceCodeVisitorValidator
|
|
12
18
|
].freeze
|
|
13
19
|
|
|
14
20
|
def self.validate(clazz, attributes)
|
|
@@ -8,8 +8,9 @@ module Cocina
|
|
|
8
8
|
# Validates that dates of known types are type-valid using the visitor pattern.
|
|
9
9
|
class DescriptionDateTimeVisitorValidator < BaseDescriptionVisitorValidator
|
|
10
10
|
VALIDATABLE_TYPES = %w[edtf iso8601 w3cdtf].freeze
|
|
11
|
+
VALID_ENCODING_CODES = %w[edtf iso8601 marc temper w3cdtf].freeze
|
|
11
12
|
|
|
12
|
-
def visit_hash(hash:, path:) # rubocop:disable Metrics/CyclomaticComplexity
|
|
13
|
+
def visit_hash(hash:, path:) # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
13
14
|
# Only dates nested under a `date` key are subject to validation.
|
|
14
15
|
# For example, event.date is in scope but event.note is not.
|
|
15
16
|
return unless in_date_path?(path)
|
|
@@ -32,7 +33,10 @@ module Cocina
|
|
|
32
33
|
# recursing into its children, so the encoding is always registered
|
|
33
34
|
# before any child value hashes are visited.
|
|
34
35
|
code = hash.dig(:encoding, :code)
|
|
35
|
-
|
|
36
|
+
if code
|
|
37
|
+
encoding_paths[path.dup] = code if VALIDATABLE_TYPES.include?(code)
|
|
38
|
+
invalid_encoding_codes << "#{path_to_s(path)}.encoding.code (#{code})" unless VALID_ENCODING_CODES.include?(code)
|
|
39
|
+
end
|
|
36
40
|
|
|
37
41
|
value = hash[:value]
|
|
38
42
|
return unless value.is_a?(String)
|
|
@@ -62,17 +66,18 @@ module Cocina
|
|
|
62
66
|
end
|
|
63
67
|
|
|
64
68
|
def validate!
|
|
65
|
-
|
|
69
|
+
errors = []
|
|
66
70
|
|
|
67
|
-
|
|
68
|
-
next if values.empty?
|
|
71
|
+
errors << "Unrecognized date encoding codes in description: #{invalid_encoding_codes.join(', ')}" if invalid_encoding_codes.any?
|
|
69
72
|
|
|
70
|
-
|
|
73
|
+
unless invalid_groups.empty?
|
|
74
|
+
invalid_dates = invalid_groups.filter_map do |path, values|
|
|
75
|
+
[*values, encoding_paths[path]] unless values.empty?
|
|
76
|
+
end
|
|
77
|
+
errors << "Invalid date(s) in description: #{invalid_dates}" if invalid_dates.any?
|
|
71
78
|
end
|
|
72
79
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
raise ValidationError, "Invalid date(s) in description: #{invalid_dates}"
|
|
80
|
+
raise ValidationError, errors.join('; ') if errors.any?
|
|
76
81
|
end
|
|
77
82
|
|
|
78
83
|
private
|
|
@@ -81,6 +86,10 @@ module Cocina
|
|
|
81
86
|
@encoding_paths ||= {}
|
|
82
87
|
end
|
|
83
88
|
|
|
89
|
+
def invalid_encoding_codes
|
|
90
|
+
@invalid_encoding_codes ||= []
|
|
91
|
+
end
|
|
92
|
+
|
|
84
93
|
def invalid_groups
|
|
85
94
|
@invalid_groups ||= {}
|
|
86
95
|
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cocina
|
|
4
|
+
module Models
|
|
5
|
+
module Validators
|
|
6
|
+
# Validates that event date structuredValue entries with a type also have a value.
|
|
7
|
+
class DescriptionEventDateVisitorValidator < BaseDescriptionVisitorValidator
|
|
8
|
+
def visit_hash(hash:, path:)
|
|
9
|
+
return unless hash[:type] && !hash[:value]
|
|
10
|
+
return unless event_date_structured_value?(path)
|
|
11
|
+
|
|
12
|
+
error_paths << path_to_s(path)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def validate!
|
|
16
|
+
return if error_paths.empty?
|
|
17
|
+
|
|
18
|
+
raise ValidationError,
|
|
19
|
+
"Missing value for type in description: #{error_paths.join(', ')}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def error_paths
|
|
25
|
+
@error_paths ||= []
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def event_date_structured_value?(path)
|
|
29
|
+
return false unless path[0] == 'event' && path[2] == 'date'
|
|
30
|
+
|
|
31
|
+
# Direct: event.date.structuredValue, e.g. ["event", 0, "date", 0, "structuredValue", 0]
|
|
32
|
+
# Via parallelValue: event.date.parallelValue.structuredValue, e.g. ["event", 0, "date", 0, "parallelValue", 0, "structuredValue", 0]
|
|
33
|
+
path[4] == 'structuredValue' || (path[4] == 'parallelValue' && path[6] == 'structuredValue')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cocina
|
|
4
|
+
module Models
|
|
5
|
+
module Validators
|
|
6
|
+
# Validates form.value against allowed values when form.source.value is a known controlled vocabulary.
|
|
7
|
+
class DescriptionFormResourceTypeVisitorValidator < BaseDescriptionVisitorValidator
|
|
8
|
+
def validate!
|
|
9
|
+
return if error_paths.empty?
|
|
10
|
+
|
|
11
|
+
raise ValidationError, "Unrecognized resource type values in description: #{error_paths.join(', ')}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def visit_hash(hash:, path:)
|
|
15
|
+
return unless form_entry_path?(path)
|
|
16
|
+
return unless hash[:type].to_s == 'resource type'
|
|
17
|
+
|
|
18
|
+
source_value = hash.dig(:source, :value)
|
|
19
|
+
return unless source_value && valid_values_by_source.key?(source_value)
|
|
20
|
+
|
|
21
|
+
value = hash[:value]
|
|
22
|
+
return unless value
|
|
23
|
+
return if valid_values_by_source[source_value].include?(value)
|
|
24
|
+
|
|
25
|
+
error_paths << "#{path_to_s(path)} (#{value})"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def error_paths
|
|
31
|
+
@error_paths ||= []
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def form_entry_path?(path)
|
|
35
|
+
path.length >= 2 && path[-1].is_a?(Integer) && path[-2].to_s == 'form'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# rubocop:disable Style/ClassVars
|
|
39
|
+
def valid_values_by_source
|
|
40
|
+
@@valid_values_by_source ||= YAML.load_file(::File.expand_path('../../../../resource_type_values.yml', __dir__))
|
|
41
|
+
end
|
|
42
|
+
# rubocop:enable Style/ClassVars
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cocina
|
|
4
|
+
module Models
|
|
5
|
+
module Validators
|
|
6
|
+
# Validates identifier.source.code values against identifier_source_codes.yml.
|
|
7
|
+
class DescriptionIdentifierSourceCodeVisitorValidator < BaseDescriptionVisitorValidator
|
|
8
|
+
def validate!
|
|
9
|
+
return if error_paths.empty?
|
|
10
|
+
|
|
11
|
+
raise ValidationError, "Unrecognized identifier source codes in description: #{error_paths.join(', ')}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def visit_hash(hash:, path:)
|
|
15
|
+
return unless identifier_path?(path)
|
|
16
|
+
|
|
17
|
+
source_code = hash.dig(:source, :code)
|
|
18
|
+
return unless source_code
|
|
19
|
+
|
|
20
|
+
error_paths << "#{path_to_s(path)}.source.code (#{source_code})" unless valid_codes.include?(source_code.downcase)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def error_paths
|
|
26
|
+
@error_paths ||= []
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def identifier_path?(path)
|
|
30
|
+
path.length >= 2 && path[-1].is_a?(Integer) && path[-2].to_s == 'identifier'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# rubocop:disable Style/ClassVars
|
|
34
|
+
def valid_codes
|
|
35
|
+
@@valid_codes ||= YAML.load_file(::File.expand_path('../../../../identifier_source_codes.yml', __dir__)).to_set(&:downcase)
|
|
36
|
+
end
|
|
37
|
+
# rubocop:enable Style/ClassVars
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cocina
|
|
4
|
+
module Models
|
|
5
|
+
module Validators
|
|
6
|
+
# Validates location.source.code values against location_source_codes.yml.
|
|
7
|
+
class DescriptionLocationSourceCodeVisitorValidator < BaseDescriptionVisitorValidator
|
|
8
|
+
def validate!
|
|
9
|
+
return if error_paths.empty?
|
|
10
|
+
|
|
11
|
+
raise ValidationError, "Unrecognized location source codes in description: #{error_paths.join(', ')}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def visit_hash(hash:, path:)
|
|
15
|
+
return unless location_path?(path)
|
|
16
|
+
|
|
17
|
+
source_code = hash.dig(:source, :code)
|
|
18
|
+
return unless source_code
|
|
19
|
+
return if valid_codes.include?(source_code.downcase)
|
|
20
|
+
|
|
21
|
+
error_paths << "#{path_to_s(path)}.source.code (#{source_code})"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def error_paths
|
|
27
|
+
@error_paths ||= []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def location_path?(path)
|
|
31
|
+
# Match entries in a location array (e.g., [:location, 0] or [:relatedResource, 0, :location, 0]).
|
|
32
|
+
path.length >= 2 && path[-1].is_a?(Integer) && path[-2].to_s == 'location'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# rubocop:disable Style/ClassVars
|
|
36
|
+
def valid_codes
|
|
37
|
+
@@valid_codes ||= YAML.load_file(::File.expand_path('../../../../location_source_codes.yml', __dir__)).to_set(&:downcase)
|
|
38
|
+
end
|
|
39
|
+
# rubocop:enable Style/ClassVars
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cocina
|
|
4
|
+
module Models
|
|
5
|
+
module Validators
|
|
6
|
+
# Validates contributor.role.source.code values against role_source_codes.yml.
|
|
7
|
+
class DescriptionRoleSourceCodeVisitorValidator < BaseDescriptionVisitorValidator
|
|
8
|
+
def validate!
|
|
9
|
+
return if error_paths.empty?
|
|
10
|
+
|
|
11
|
+
raise ValidationError, "Unrecognized role source codes in description: #{error_paths.join(', ')}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def visit_hash(hash:, path:)
|
|
15
|
+
return unless role_path?(path)
|
|
16
|
+
|
|
17
|
+
source_code = hash.dig(:source, :code)
|
|
18
|
+
return unless source_code
|
|
19
|
+
return if valid_codes.include?(source_code.downcase)
|
|
20
|
+
|
|
21
|
+
error_paths << "#{path_to_s(path)}.source.code (#{source_code})"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def error_paths
|
|
27
|
+
@error_paths ||= []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def role_path?(path)
|
|
31
|
+
path.length >= 2 && # ensure we have at least two elements (at minimum role and its index)
|
|
32
|
+
path[-1].is_a?(Integer) &&
|
|
33
|
+
path[-2].to_s == 'role' && # we have a nested role in the path
|
|
34
|
+
path.any? { |part| part.to_s == 'contributor' } # there is a contributor in the path (any? allows for nested roles)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Source codes allowed for contributor.role.source.code
|
|
38
|
+
def valid_codes
|
|
39
|
+
%w[aat lcmpt marcrelator rbmsrel]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cocina
|
|
4
|
+
module Models
|
|
5
|
+
module Validators
|
|
6
|
+
# Validates encoding.code for subject entries with type "time" against
|
|
7
|
+
# temporal_subject_encoding_codes.yml (union of LOC date-time and temporal source lists).
|
|
8
|
+
class DescriptionSubjectTemporalEncodingVisitorValidator < BaseDescriptionVisitorValidator
|
|
9
|
+
def validate!
|
|
10
|
+
return if error_paths.empty?
|
|
11
|
+
|
|
12
|
+
raise ValidationError, "Unrecognized subject temporal encoding codes in description: #{error_paths.join(', ')}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def visit_hash(hash:, path:)
|
|
16
|
+
return unless in_subject_path?(path)
|
|
17
|
+
return unless hash[:type].to_s == 'time'
|
|
18
|
+
|
|
19
|
+
encoding_code = hash.dig(:encoding, :code)
|
|
20
|
+
return unless encoding_code
|
|
21
|
+
|
|
22
|
+
error_paths << "#{path_to_s(path)}.encoding.code (#{encoding_code})" unless valid_codes.include?(encoding_code.downcase)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def error_paths
|
|
28
|
+
@error_paths ||= []
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def in_subject_path?(path)
|
|
32
|
+
path.any? { |part| part.to_s == 'subject' }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# rubocop:disable Style/ClassVars
|
|
36
|
+
def valid_codes
|
|
37
|
+
@@valid_codes ||= YAML.load_file(::File.expand_path('../../../../temporal_subject_encoding_codes.yml', __dir__)).to_set(&:downcase)
|
|
38
|
+
end
|
|
39
|
+
# rubocop:enable Style/ClassVars
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|