cocina-models 0.71.0 → 0.73.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -0
- data/description_types.yml +554 -0
- data/docs/_config.yml +1 -0
- data/docs/description_types.md +456 -0
- data/lib/cocina/generator/generator.rb +49 -1
- data/lib/cocina/models/access_role.rb +1 -1
- data/lib/cocina/models/catalog_link.rb +3 -1
- data/lib/cocina/models/title_builder.rb +16 -16
- data/lib/cocina/models/validatable.rb +2 -2
- data/lib/cocina/models/validators/catalog_links_validator.rb +54 -0
- data/lib/cocina/models/validators/dark_validator.rb +79 -0
- data/lib/cocina/models/validators/description_types_validator.rb +119 -0
- data/lib/cocina/models/validators/open_api_validator.rb +53 -0
- data/lib/cocina/models/validators/validator.rb +21 -0
- data/lib/cocina/models/version.rb +1 -1
- data/lib/cocina/models/vocabulary.rb +9 -0
- data/openapi.yml +16 -9
- metadata +11 -4
- data/lib/cocina/models/validator.rb +0 -49
@@ -0,0 +1,456 @@
|
|
1
|
+
# Description types
|
2
|
+
|
3
|
+
## Access accesscontact types
|
4
|
+
_Path: access.accessContact_
|
5
|
+
* email: Email address for a contact person or institution concerning the resource.
|
6
|
+
* repository: Institution providing access to the resource.
|
7
|
+
|
8
|
+
## Access digitallocation types
|
9
|
+
_Path: access.digitalLocation_
|
10
|
+
* discovery: Online location for the purpose of discovering the resource.
|
11
|
+
|
12
|
+
## Access note types
|
13
|
+
_Path: access.note_
|
14
|
+
* access restriction: Restrictions on or conditions for gaining access to the resource.
|
15
|
+
* display label: Display label for the purl.
|
16
|
+
* license: License describing allowed uses of the resource.
|
17
|
+
* use and reproduction: Information related to allowed uses of the resource in other contexts.
|
18
|
+
|
19
|
+
## Access physicallocation types
|
20
|
+
_Path: access.physicalLocation_
|
21
|
+
* discovery: Location where a user may find the resource.
|
22
|
+
* location: Physical location of the resource, or path to the resource on a hard drive or disk.
|
23
|
+
* repository: The institution holding the resource.
|
24
|
+
* series: Archival series of the resource.
|
25
|
+
* shelf locator: Identifier or shelfmark indicating the location of the resource.
|
26
|
+
|
27
|
+
## Adminmetadata note types
|
28
|
+
_Path: adminMetadata.note_
|
29
|
+
* record information: General information about the metadata record.
|
30
|
+
* record origin: The source of the record, such as another record transformed to generate the current record.
|
31
|
+
|
32
|
+
# Contributor types
|
33
|
+
_Path: contributor_
|
34
|
+
* conference: An event focusing on a particular topic or discipline.
|
35
|
+
* event: A time-bound occurrence.
|
36
|
+
* family: A group of individuals related by blood or personal alliance.
|
37
|
+
* organization: An institution or other corporate or collective body.
|
38
|
+
* person: An individual identity.
|
39
|
+
* unspecified others: Designator for one or more additional contributors not named individually.
|
40
|
+
|
41
|
+
## Contributor identifier types
|
42
|
+
_Path: contributor.identifier_
|
43
|
+
* ORCID: Identifier from orcid.org.
|
44
|
+
* Wikidata: Identifier from wikidata.org.
|
45
|
+
|
46
|
+
## Contributor name types
|
47
|
+
_Path: contributor.name_
|
48
|
+
* alternative: Additional nonpreferred form of name.
|
49
|
+
* display: Preferred form of the name for display.
|
50
|
+
* forename: First or given name or names.
|
51
|
+
* inverted full name: Name given in last name, first name order.
|
52
|
+
* pseudonym: Name used that differs from legal or primary form of name.
|
53
|
+
* surname: Last or family name.
|
54
|
+
* transliteration: Name originally in non-Latin script presented phonetically using Latin characters.
|
55
|
+
|
56
|
+
### Contributor name part types for structured value
|
57
|
+
_Path: contributor.name.structuredValue_
|
58
|
+
* activity dates: The date or dates when someone was producing work.
|
59
|
+
* forename: First or given name or names.
|
60
|
+
* life dates: Birth and death dates, or dates when an entity was in existence.
|
61
|
+
* name: Name provided alongside additional information.
|
62
|
+
* ordinal: Indicator that the name is one in a series (e.g. Elizabeth I, Martin Luther King, Jr.).
|
63
|
+
* surname: Last or family name.
|
64
|
+
* term of address: Title or other signifier associated with name.
|
65
|
+
|
66
|
+
### Contributor name types for grouped value (MODS legacy)
|
67
|
+
_Path: contributor.name.groupedValue_
|
68
|
+
* alternative: Additional nonpreferred form of name.
|
69
|
+
* name: Primary form of name within group of values.
|
70
|
+
* pseudonym: Name used that differs from legal or primary form of name.
|
71
|
+
|
72
|
+
## Contributor note types
|
73
|
+
_Path: contributor.note_
|
74
|
+
* affiliation: Institution with which the contributor is associated.
|
75
|
+
* citation status: Indicator of whether the contributor should be included in the citation.
|
76
|
+
* description: Biographical information about the contributor.
|
77
|
+
|
78
|
+
# Event types
|
79
|
+
_Path: event_
|
80
|
+
* acquisition: The transferral of ownership of a resource to a repository.
|
81
|
+
* capture: A record of the resource in a fixed form at a specific time.
|
82
|
+
* collection: The addition of a resource to a set of other resources.
|
83
|
+
* copyright: The activity by which a resource may be considered subject to copyright law.
|
84
|
+
* copyright notice: An explicit statement that a resource is under copyright.
|
85
|
+
* creation: The coming into being of a resource.
|
86
|
+
* degree conferral: The institutional approval of a thesis or other resource leading to an academic degree.
|
87
|
+
* development: The creation of a print from a photographic negative or other source medium.
|
88
|
+
* distribution: The delivery of the resource to an external audience.
|
89
|
+
* generation: The creation of a resource by an automatic or natural process.
|
90
|
+
* manufacture: The physical assembly of a resource, often in multiple copies, for publication or other distribution.
|
91
|
+
* modification: A change to an existing resource.
|
92
|
+
* performance: The enactment of an artistic or cultural work for an audience, such as a play.
|
93
|
+
* presentation: The discussion of an academic or intellectual work for an audience, such as a seminar.
|
94
|
+
* production: The physical assembly of a resource not considered published, such as page proofs for a book.
|
95
|
+
* publication: The publishing or issuing of a resource.
|
96
|
+
* recording: The initial fixation to a medium of live audio and/or visual activity.
|
97
|
+
* release: Making a resource available to a broader audience.
|
98
|
+
* submission: The provision of a resource for review or evaluation.
|
99
|
+
* validity: When a resource takes effect, such as a revised train schedule.
|
100
|
+
* withdrawal: The removal of previous access to a resource, often due to its obsolescence.
|
101
|
+
|
102
|
+
## Event date types
|
103
|
+
_Path: event.date_
|
104
|
+
* acquisition: The transferral of ownership of a resource to a repository.
|
105
|
+
* capture: A record of the resource in a fixed form at a specific time.
|
106
|
+
* collection: The addition of a resource to a set of other resources.
|
107
|
+
* copyright: The activity by which a resource may be considered subject to copyright law.
|
108
|
+
* creation: The coming into being of a resource.
|
109
|
+
* degree conferral: The institutional approval of a thesis or other resource leading to an academic degree.
|
110
|
+
* developed: The creation of a print from a photographic negative or other source medium.
|
111
|
+
* development: The creation of a print from a photographic negative or other source medium.
|
112
|
+
* distribution: The delivery of the resource to an external audience.
|
113
|
+
* generation: The creation of a resource by an automatic or natural process.
|
114
|
+
* manufacture: The physical assembly of a resource, often in multiple copies, for publication or other distribution.
|
115
|
+
* modification: A change to an existing resource.
|
116
|
+
* performance: The enactment of an artistic or cultural work for an audience, such as a play.
|
117
|
+
* presentation: The discussion of an academic or intellectual work for an audience, such as a seminar.
|
118
|
+
* production: The physical assembly of a resource not considered published, such as page proofs for a book.
|
119
|
+
* publication: The publishing or issuing of a resource.
|
120
|
+
* recording: The initial fixation to a medium of live audio and/or visual activity.
|
121
|
+
* release: Making a resource available to a broader audience.
|
122
|
+
* submission: The provision of a resource for review or evaluation.
|
123
|
+
* validity: When a resource takes effect, such as a revised train schedule.
|
124
|
+
* withdrawal: The removal of previous access to a resource, often due to its obsolescence.
|
125
|
+
|
126
|
+
### Event date part types for structured value
|
127
|
+
_Path: event.date.structuredValue_
|
128
|
+
* start: The start date in a range.
|
129
|
+
* end: The end date in a range.
|
130
|
+
|
131
|
+
## Event note types
|
132
|
+
_Path: event.note_
|
133
|
+
* copyright statement: A formal declaration of copyright on a resource.
|
134
|
+
* edition
|
135
|
+
* frequency: How often a resource is issued, such as monthly.
|
136
|
+
* issuance: How the resource is issued, such as serially.
|
137
|
+
|
138
|
+
# Form types
|
139
|
+
_Path: form_
|
140
|
+
* carrier
|
141
|
+
* data format
|
142
|
+
* digital original
|
143
|
+
* extent
|
144
|
+
* form
|
145
|
+
* genre
|
146
|
+
* map projection
|
147
|
+
* map scale
|
148
|
+
* material
|
149
|
+
* media
|
150
|
+
* media type
|
151
|
+
* reformatting quality
|
152
|
+
* resource type
|
153
|
+
* technique
|
154
|
+
* type
|
155
|
+
|
156
|
+
## Form note types
|
157
|
+
_Path: form.note_
|
158
|
+
* additions
|
159
|
+
* arrangement
|
160
|
+
* binding
|
161
|
+
* codicology
|
162
|
+
* collation
|
163
|
+
* colophon
|
164
|
+
* condition
|
165
|
+
* decoNote
|
166
|
+
* decoration
|
167
|
+
* dimensions
|
168
|
+
* explicit
|
169
|
+
* foliation
|
170
|
+
* genre type
|
171
|
+
* hand note
|
172
|
+
* handNote
|
173
|
+
* incipit
|
174
|
+
* instrumentation
|
175
|
+
* layout
|
176
|
+
* material
|
177
|
+
* medium of performance
|
178
|
+
* provenance
|
179
|
+
* reassembly
|
180
|
+
* reproduction
|
181
|
+
* research
|
182
|
+
* rubric
|
183
|
+
* secfol
|
184
|
+
* second folio
|
185
|
+
* secondFolio
|
186
|
+
* unit
|
187
|
+
* writing
|
188
|
+
|
189
|
+
## Form part types for structured value
|
190
|
+
_Path: form.structuredValue_
|
191
|
+
* type
|
192
|
+
* subtype
|
193
|
+
|
194
|
+
## Geographic form types
|
195
|
+
_Path: geographic.form_
|
196
|
+
* data format
|
197
|
+
* media type
|
198
|
+
* type
|
199
|
+
|
200
|
+
## Geographic subject types
|
201
|
+
_Path: geographic.subject_
|
202
|
+
* bounding box coordinates
|
203
|
+
* coverage
|
204
|
+
* point coordinates
|
205
|
+
|
206
|
+
### Geographic subject part types for structured value
|
207
|
+
_Path: geographic.subject.structuredValue_
|
208
|
+
* east
|
209
|
+
* latitude
|
210
|
+
* longitude
|
211
|
+
* north
|
212
|
+
* south
|
213
|
+
* west
|
214
|
+
|
215
|
+
# Identifier types
|
216
|
+
_Path: identifier_
|
217
|
+
* accession number
|
218
|
+
* alternate case number
|
219
|
+
* Apis ID
|
220
|
+
* ARK
|
221
|
+
* arXiv
|
222
|
+
* case identifier
|
223
|
+
* case number
|
224
|
+
* document number
|
225
|
+
* DOI
|
226
|
+
* druid
|
227
|
+
* GTIN-14 ID
|
228
|
+
* Handle
|
229
|
+
* inventory number
|
230
|
+
* ISBN
|
231
|
+
* ISMN
|
232
|
+
* ISRC
|
233
|
+
* ISSN
|
234
|
+
* ISSN-L
|
235
|
+
* issue number
|
236
|
+
* LCCN
|
237
|
+
* local
|
238
|
+
* Local ID
|
239
|
+
* matrix number
|
240
|
+
* music plate
|
241
|
+
* music publisher
|
242
|
+
* OCLC
|
243
|
+
* PMCID
|
244
|
+
* PMID
|
245
|
+
* record id
|
246
|
+
* Senate Number
|
247
|
+
* Series
|
248
|
+
* SIRSI
|
249
|
+
* Source ID
|
250
|
+
* sourceID
|
251
|
+
* stock number
|
252
|
+
* Swets (Netherlands) ID
|
253
|
+
* UPC
|
254
|
+
* URI
|
255
|
+
* URN
|
256
|
+
* videorecording identifier
|
257
|
+
* West Mat \#
|
258
|
+
* Wikidata
|
259
|
+
|
260
|
+
# Note types
|
261
|
+
_Path: note_
|
262
|
+
* abstract
|
263
|
+
* access
|
264
|
+
* access note
|
265
|
+
* acquisition
|
266
|
+
* action
|
267
|
+
* additional physical form
|
268
|
+
* additions
|
269
|
+
* admin
|
270
|
+
* affiliation
|
271
|
+
* bibliographic
|
272
|
+
* bibliography
|
273
|
+
* biographical/historical
|
274
|
+
* biographical/historical note
|
275
|
+
* biography
|
276
|
+
* boat note
|
277
|
+
* citation/reference
|
278
|
+
* contact
|
279
|
+
* content
|
280
|
+
* content note
|
281
|
+
* content warning
|
282
|
+
* contents
|
283
|
+
* copyright
|
284
|
+
* creation/production credits
|
285
|
+
* date
|
286
|
+
* date/sequential designation
|
287
|
+
* description
|
288
|
+
* digitization
|
289
|
+
* duration
|
290
|
+
* event
|
291
|
+
* exhibitions
|
292
|
+
* funding
|
293
|
+
* general
|
294
|
+
* genre type
|
295
|
+
* geography
|
296
|
+
* host
|
297
|
+
* language
|
298
|
+
* local
|
299
|
+
* location
|
300
|
+
* medium of performance
|
301
|
+
* names
|
302
|
+
* numbering
|
303
|
+
* original location
|
304
|
+
* other relation type
|
305
|
+
* ownership
|
306
|
+
* part
|
307
|
+
* performer
|
308
|
+
* performers
|
309
|
+
* preferred citation
|
310
|
+
* provenance
|
311
|
+
* publications
|
312
|
+
* qualifications
|
313
|
+
* quote
|
314
|
+
* reassembly
|
315
|
+
* reference
|
316
|
+
* references
|
317
|
+
* related publication
|
318
|
+
* reproduction
|
319
|
+
* research
|
320
|
+
* restriction
|
321
|
+
* scope and content
|
322
|
+
* source characteristics
|
323
|
+
* source identifier
|
324
|
+
* statement of responsibility
|
325
|
+
* summary
|
326
|
+
* system details
|
327
|
+
* system requirements
|
328
|
+
* table of contents
|
329
|
+
* target audience
|
330
|
+
* technical note
|
331
|
+
* thesis
|
332
|
+
* transcript
|
333
|
+
* translation
|
334
|
+
* update
|
335
|
+
* use and reproduction
|
336
|
+
* venue
|
337
|
+
* version
|
338
|
+
* version identification
|
339
|
+
* writing
|
340
|
+
|
341
|
+
## Note types for grouped value (MODS legacy)
|
342
|
+
_Path: note.groupedValue_
|
343
|
+
* caption
|
344
|
+
* date
|
345
|
+
* detail type
|
346
|
+
* extent unit
|
347
|
+
* list
|
348
|
+
* marker
|
349
|
+
* number
|
350
|
+
* title
|
351
|
+
* text
|
352
|
+
|
353
|
+
# Relatedresource types
|
354
|
+
_Path: relatedResource_
|
355
|
+
* has original version: An initial form of the resource.
|
356
|
+
* has other format: A version of the resource in a different physical or digital format.
|
357
|
+
* has part: A constituent unit of the resource.
|
358
|
+
* has version: A version of the resource with different intellectual content.
|
359
|
+
* in series: The name of a series of publications to which the resource belongs.
|
360
|
+
* other relation type: Resource type not otherwise described.
|
361
|
+
* part of: A larger resource to which the resource belongs, such as a collection.
|
362
|
+
* preceded by: A predecessor to the resource, such as a preceding journal title.
|
363
|
+
* referenced by: Other resources that cite the resource, such as a catalog.
|
364
|
+
* references: A resource which the resource references or cites.
|
365
|
+
* related to: A generically related resource.
|
366
|
+
* reviewed by: A review of the resource.
|
367
|
+
* succeeded by: A successor to the resource, such as a subsequent journal title.
|
368
|
+
|
369
|
+
# Subject types
|
370
|
+
_Path: subject_
|
371
|
+
* classification
|
372
|
+
* conference
|
373
|
+
* display
|
374
|
+
* event
|
375
|
+
* family
|
376
|
+
* genre
|
377
|
+
* map coordinates
|
378
|
+
* name
|
379
|
+
* occupation
|
380
|
+
* organization
|
381
|
+
* person
|
382
|
+
* place
|
383
|
+
* point coordinates
|
384
|
+
* time
|
385
|
+
* title
|
386
|
+
* topic
|
387
|
+
|
388
|
+
## Subject note types
|
389
|
+
_Path: subject.note_
|
390
|
+
* role
|
391
|
+
|
392
|
+
## Subject part types for structured value
|
393
|
+
_Path: subject.structuredValue_
|
394
|
+
* activity dates
|
395
|
+
* city
|
396
|
+
* conference
|
397
|
+
* continent
|
398
|
+
* country
|
399
|
+
* end
|
400
|
+
* east
|
401
|
+
* event
|
402
|
+
* display
|
403
|
+
* family
|
404
|
+
* forename
|
405
|
+
* genre
|
406
|
+
* latitude
|
407
|
+
* life dates
|
408
|
+
* longitude
|
409
|
+
* main title
|
410
|
+
* name
|
411
|
+
* north
|
412
|
+
* occupation
|
413
|
+
* ordinal
|
414
|
+
* organization
|
415
|
+
* part name
|
416
|
+
* person
|
417
|
+
* place
|
418
|
+
* south
|
419
|
+
* start
|
420
|
+
* surname
|
421
|
+
* term of address
|
422
|
+
* time
|
423
|
+
* title
|
424
|
+
* topic
|
425
|
+
* west
|
426
|
+
|
427
|
+
### Subject note types
|
428
|
+
_Path: subject.structuredValue.note_
|
429
|
+
* role: The relation of the subject entity to the resource.
|
430
|
+
|
431
|
+
## Subject types for grouped value (MODS legacy)
|
432
|
+
_Path: subject.groupedValue_
|
433
|
+
* uniform: Form of title in Library of Congress title authority.
|
434
|
+
|
435
|
+
# Title types
|
436
|
+
_Path: title_
|
437
|
+
* abbreviated: Abbreviated form of title for indexing or identification.
|
438
|
+
* alternative: Variant title.
|
439
|
+
* parallel: Title transcribed from the resource in multiple languages or scripts.
|
440
|
+
* supplied: Title provided by metadata creator rather than transcribed from the resource.
|
441
|
+
* translated: Title translated into another language.
|
442
|
+
* transliterated: Title transliterated from non-Latin script to Latin script.
|
443
|
+
* uniform: Form of title in Library of Congress title authority.
|
444
|
+
|
445
|
+
## Title note types
|
446
|
+
_Path: title.note_
|
447
|
+
* associated name: A name linked to the title, such as for a name-title heading.
|
448
|
+
* nonsorting character count: The number of characters at the beginning of the string to be disregarded when sorting.
|
449
|
+
|
450
|
+
## Title part types for structured value
|
451
|
+
_Path: title.structuredValue_
|
452
|
+
* main title: The primary part of a multipart title.
|
453
|
+
* nonsorting characters: A string at the beginning of the title to be disregarded when sorting.
|
454
|
+
* part name: The distinct name of a resource as part of a series or multivolume set.
|
455
|
+
* part number: The distinct number of a resource as part of a series or multivolume set.
|
456
|
+
* subtitle: The secondary part of a title.
|
@@ -28,6 +28,7 @@ module Cocina
|
|
28
28
|
# rubocop:enable Style/HashEachMethods
|
29
29
|
|
30
30
|
generate_vocab
|
31
|
+
generate_descriptive_docs
|
31
32
|
end
|
32
33
|
|
33
34
|
desc 'generate_schema SCHEMA_NAME', 'generate for SCHEMA_NAME'
|
@@ -45,8 +46,56 @@ module Cocina
|
|
45
46
|
Vocab.generate(schemas, output_dir: options[:output])
|
46
47
|
end
|
47
48
|
|
49
|
+
desc 'generate_descriptive_docs', 'generate descriptive documentation'
|
50
|
+
def generate_descriptive_docs
|
51
|
+
markdown = YAML.load_file('description_types.yml').map do |field, types|
|
52
|
+
header_markdown = field_markdown_from(field)
|
53
|
+
types_markdown = types_markdown_from(types)
|
54
|
+
|
55
|
+
<<~MARKDOWN
|
56
|
+
#{'#' * (field.count('.') + 1)} #{header_markdown}
|
57
|
+
_Path: #{field}_
|
58
|
+
#{types_markdown}
|
59
|
+
MARKDOWN
|
60
|
+
end.join("\n")
|
61
|
+
|
62
|
+
remove_file 'docs/description_types.md'
|
63
|
+
create_file 'docs/description_types.md', h1_markdown + markdown
|
64
|
+
end
|
65
|
+
|
48
66
|
private
|
49
67
|
|
68
|
+
def h1_markdown
|
69
|
+
<<~MARKDOWN
|
70
|
+
# Description types
|
71
|
+
|
72
|
+
MARKDOWN
|
73
|
+
end
|
74
|
+
|
75
|
+
def field_markdown_from(field)
|
76
|
+
header = field.split('.')
|
77
|
+
.grep_v(/groupedValue|structuredValue/)
|
78
|
+
.join(' ')
|
79
|
+
.capitalize
|
80
|
+
|
81
|
+
header_suffix = if field.ends_with?('structuredValue')
|
82
|
+
'part types for structured value'
|
83
|
+
elsif field.ends_with?('groupedValue')
|
84
|
+
'types for grouped value (MODS legacy)'
|
85
|
+
else
|
86
|
+
'types'
|
87
|
+
end
|
88
|
+
"#{header} #{header_suffix}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def types_markdown_from(types)
|
92
|
+
types.map do |type|
|
93
|
+
" * #{type['value']}".tap do |type_value|
|
94
|
+
type_value << ": #{type['description']}" if type['description']
|
95
|
+
end
|
96
|
+
end.join("\n")
|
97
|
+
end
|
98
|
+
|
50
99
|
def schemas
|
51
100
|
@schemas ||= Openapi3Parser.load_file(options[:openapi]).components.schemas
|
52
101
|
end
|
@@ -78,7 +127,6 @@ module Cocina
|
|
78
127
|
'rights_description_builder.rb',
|
79
128
|
'title_builder.rb',
|
80
129
|
'validatable.rb',
|
81
|
-
'validator.rb',
|
82
130
|
'version.rb',
|
83
131
|
'vocabulary.rb'
|
84
132
|
].freeze
|
@@ -4,7 +4,7 @@ module Cocina
|
|
4
4
|
module Models
|
5
5
|
class AccessRole < Struct
|
6
6
|
# Name of role
|
7
|
-
attribute :name, Types::Strict::String.enum('dor-apo-
|
7
|
+
attribute :name, Types::Strict::String.enum('dor-apo-depositor', 'dor-apo-manager', 'dor-apo-viewer', 'sdr-administrator', 'sdr-viewer', 'hydrus-collection-creator', 'hydrus-collection-manager', 'hydrus-collection-depositor', 'hydrus-collection-item-depositor', 'hydrus-collection-reviewer', 'hydrus-collection-viewer')
|
8
8
|
attribute :members, Types::Strict::Array.of(AccessRoleMember).default([].freeze)
|
9
9
|
end
|
10
10
|
end
|
@@ -5,7 +5,9 @@ module Cocina
|
|
5
5
|
class CatalogLink < Struct
|
6
6
|
# Catalog that is the source of the linked record.
|
7
7
|
# example: symphony
|
8
|
-
attribute :catalog, Types::Strict::String
|
8
|
+
attribute :catalog, Types::Strict::String.enum('symphony', 'previous symphony')
|
9
|
+
# Only one of the catkeys should be designated for refreshing. This means that this key is the one used to pull metadata from the catalog if there is more than one key present.
|
10
|
+
attribute :refresh, Types::Strict::Bool.default(false)
|
9
11
|
# Record identifier that is unique within the context of the linked record's catalog.
|
10
12
|
# example: 11403803
|
11
13
|
attribute :catalogRecordId, Types::Strict::String
|
@@ -46,8 +46,7 @@ module Cocina
|
|
46
46
|
result = if cocina_title.value
|
47
47
|
cocina_title.value
|
48
48
|
elsif cocina_title.structuredValue.present?
|
49
|
-
title_from_structured_values(cocina_title
|
50
|
-
non_sorting_char_count(cocina_title))
|
49
|
+
title_from_structured_values(cocina_title)
|
51
50
|
elsif cocina_title.parallelValue.present?
|
52
51
|
return build(cocina_title.parallelValue)
|
53
52
|
end
|
@@ -104,20 +103,17 @@ module Cocina
|
|
104
103
|
# rubocop:disable Metrics/PerceivedComplexity
|
105
104
|
# rubocop:disable Metrics/MethodLength
|
106
105
|
# rubocop:disable Metrics/AbcSize
|
107
|
-
# @param [
|
108
|
-
# @param [Integer] the length of the non_sorting_characters
|
106
|
+
# @param [Cocina::Models::Title] title with structured values
|
109
107
|
# @return [String] the title value from combining the pieces of the structured_values by type and order
|
110
108
|
# with desired punctuation per specs
|
111
|
-
def title_from_structured_values(
|
109
|
+
def title_from_structured_values(title)
|
112
110
|
structured_title = ''
|
113
111
|
part_name_number = ''
|
114
112
|
# combine pieces of the cocina structuredValue into a single title
|
115
|
-
|
113
|
+
title.structuredValue.each do |structured_value|
|
116
114
|
# There can be a structuredValue inside a structuredValue. For example,
|
117
115
|
# a uniform title where both the name and the title have internal StructuredValue
|
118
|
-
if structured_value.structuredValue.present?
|
119
|
-
return title_from_structured_values(structured_value.structuredValue, non_sorting_char_count)
|
120
|
-
end
|
116
|
+
return title_from_structured_values(structured_value) if structured_value.structuredValue.present?
|
121
117
|
|
122
118
|
value = structured_value.value&.strip
|
123
119
|
next unless value
|
@@ -125,8 +121,7 @@ module Cocina
|
|
125
121
|
# additional types: name, uniform ...
|
126
122
|
case structured_value.type&.downcase
|
127
123
|
when 'nonsorting characters'
|
128
|
-
|
129
|
-
non_sort_value = "#{value}#{' ' * non_sorting_size}"
|
124
|
+
non_sort_value = "#{value}#{non_sorting_padding(title, value)}"
|
130
125
|
structured_title = if structured_title.present?
|
131
126
|
"#{structured_title}#{non_sort_value}"
|
132
127
|
else
|
@@ -134,7 +129,7 @@ module Cocina
|
|
134
129
|
end
|
135
130
|
when 'part name', 'part number'
|
136
131
|
if part_name_number.blank?
|
137
|
-
part_name_number = part_name_number(
|
132
|
+
part_name_number = part_name_number(title.structuredValue)
|
138
133
|
structured_title = if !add_punctuation?
|
139
134
|
[structured_title, part_name_number].join(' ')
|
140
135
|
elsif structured_title.present?
|
@@ -168,11 +163,16 @@ module Cocina
|
|
168
163
|
title.sub(%r{[ .,;:/\\]+$}, '')
|
169
164
|
end
|
170
165
|
|
171
|
-
def
|
166
|
+
def non_sorting_padding(title, non_sorting_value)
|
172
167
|
non_sort_note = title.note&.find { |note| note.type&.downcase == 'nonsorting character count' }
|
173
|
-
|
174
|
-
|
175
|
-
|
168
|
+
if non_sort_note
|
169
|
+
padding_count = [non_sort_note.value.to_i - non_sorting_value.length, 0].max
|
170
|
+
' ' * padding_count
|
171
|
+
elsif ['\'', '-'].include?(non_sorting_value.last)
|
172
|
+
''
|
173
|
+
else
|
174
|
+
' '
|
175
|
+
end
|
176
176
|
end
|
177
177
|
|
178
178
|
# combine part name and part number:
|
@@ -8,7 +8,7 @@ module Cocina
|
|
8
8
|
|
9
9
|
class_methods do
|
10
10
|
def new(attributes = default_attributes, safe = false, validate = true, &block)
|
11
|
-
Validator.validate(self, attributes.with_indifferent_access) if validate
|
11
|
+
Validators::Validator.validate(self, attributes.with_indifferent_access) if validate
|
12
12
|
super(attributes, safe, &block)
|
13
13
|
end
|
14
14
|
end
|
@@ -16,7 +16,7 @@ module Cocina
|
|
16
16
|
def new(*args)
|
17
17
|
validate = args.first.delete(:validate) if args.present?
|
18
18
|
new_model = super(*args)
|
19
|
-
Validator.validate(new_model.class, new_model.to_h) if
|
19
|
+
Validators::Validator.validate(new_model.class, new_model.to_h) if validate || validate.nil?
|
20
20
|
new_model
|
21
21
|
end
|
22
22
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cocina
|
4
|
+
module Models
|
5
|
+
module Validators
|
6
|
+
# Validates that only a single CatalogLink has refresh set to true
|
7
|
+
class CatalogLinksValidator
|
8
|
+
MAX_REFRESH_CATALOG_LINKS = 1
|
9
|
+
|
10
|
+
def self.validate(clazz, attributes)
|
11
|
+
new(clazz, attributes).validate
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(clazz, attributes)
|
15
|
+
@clazz = clazz
|
16
|
+
@attributes = attributes
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate
|
20
|
+
return unless meets_preconditions?
|
21
|
+
|
22
|
+
return if refresh_catalog_links.length <= MAX_REFRESH_CATALOG_LINKS
|
23
|
+
|
24
|
+
raise ValidationError, "Multiple catalog links have 'refresh' property set to true " \
|
25
|
+
"(only one allowed) #{refresh_catalog_links}"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :clazz, :attributes
|
31
|
+
|
32
|
+
def meets_preconditions?
|
33
|
+
(dro? || collection?) && Array(attributes.dig(:identification, :catalogLinks)).any?
|
34
|
+
end
|
35
|
+
|
36
|
+
def refresh_catalog_links
|
37
|
+
attributes.dig(:identification, :catalogLinks).select { |catalog_link| catalog_link[:refresh] }
|
38
|
+
end
|
39
|
+
|
40
|
+
def dro?
|
41
|
+
(clazz::TYPES & DRO::TYPES).any?
|
42
|
+
rescue NameError
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def collection?
|
47
|
+
(clazz::TYPES & Collection::TYPES).any?
|
48
|
+
rescue NameError
|
49
|
+
false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|