cocina-models 0.82.0 → 0.84.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebc24ff8dbe8eb1fe740eb977abb73abc504409aa510905395e6660adcd05b3b
4
- data.tar.gz: 62ad4e7cafce859250323e92cc2173257957b16775e767224a4de2e9fd639bae
3
+ metadata.gz: 9e1b47286ce6d52c99a76f6370a1f1a902d204759a7e0d11966b42d94d01ee19
4
+ data.tar.gz: e6f5f432fab07a70965b78b94f3f5a1ff6e103ce274011ee55b7a130ae7bc974
5
5
  SHA512:
6
- metadata.gz: 7a3b0ed8ab383f945450d42343dbaed6e709854ff0f3deca1f62b93c79883d3157b42f14cdaafd9392ef858620a0c58ae6867c16037c627499efddf3cb33880b
7
- data.tar.gz: 9e1084ea73c6f547eab7b8a076d9e2a61a46361c9da1541effca8529d48d032621b6cd5868bd2886308aea1f834b4c586ae1058ca6f67f0315393e4eb632bbb9
6
+ metadata.gz: '0908f1699111ae772ebea61c0f5824c78cd694640aa3acaaded5311f2039a366469765206cf88f49410734054d660cbb6414afa0695c5a3b831b42be857e30ac'
7
+ data.tar.gz: 075d804c7525993965ffe30ae6d7e266c62d8a1b842cebc7096db3cd0c824af1b733180740faf3ba7db246cdd4c822ca9e67699cfa160810e62f12e0e919ea5d
data/.circleci/config.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  version: 2.1
2
2
  orbs:
3
- ruby-rails: sul-dlss/ruby-rails@2.0.0
3
+ ruby-rails: sul-dlss/ruby-rails@3.1.2
4
4
  workflows:
5
5
  build:
6
6
  jobs:
data/.gitignore CHANGED
@@ -9,5 +9,3 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
-
13
- Gemfile.lock
data/.rubocop.yml CHANGED
@@ -184,7 +184,7 @@ Style/SoleNestedConditional: # (new in 0.89)
184
184
  Style/StringConcatenation:
185
185
  Enabled: true
186
186
 
187
- Gemspec/DateAssignment: # new in 1.10
187
+ Gemspec/DeprecatedAttributeAssignment: # new in 1.10
188
188
  Enabled: true
189
189
  Gemspec/RequireMFA: # new in 1.23
190
190
  Enabled: true
@@ -311,3 +311,28 @@ Style/RedundantInitialize: # new in 1.27
311
311
  Enabled: true
312
312
  RSpec/VerifiedDoubleReference: # new in 2.10.0
313
313
  Enabled: true
314
+
315
+ Layout/LineContinuationLeadingSpace: # new in 1.31
316
+ Enabled: true
317
+ Layout/LineContinuationSpacing: # new in 1.31
318
+ Enabled: true
319
+ Lint/ConstantOverwrittenInRescue: # new in 1.31
320
+ Enabled: true
321
+ Lint/NonAtomicFileOperation: # new in 1.31
322
+ Enabled: true
323
+ Lint/RequireRangeParentheses: # new in 1.32
324
+ Enabled: true
325
+ Style/EmptyHeredoc: # new in 1.32
326
+ Enabled: true
327
+ Style/EnvHome: # new in 1.29
328
+ Enabled: true
329
+ Style/MagicCommentFormat: # new in 1.35
330
+ Enabled: true
331
+ Style/MapCompactWithConditionalBlock: # new in 1.30
332
+ Enabled: true
333
+ RSpec/ChangeByZero: # new in 2.11.0
334
+ Enabled: true
335
+ RSpec/Capybara/SpecificMatcher: # new in 2.12
336
+ Enabled: false
337
+ RSpec/Rails/HaveHttpStatus: # new in 2.12
338
+ Enabled: false
data/Gemfile.lock ADDED
@@ -0,0 +1,158 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cocina-models (0.84.1)
5
+ activesupport
6
+ deprecation
7
+ dry-struct (~> 1.0)
8
+ dry-types (~> 1.1)
9
+ edtf
10
+ equivalent-xml
11
+ jsonpath
12
+ nokogiri
13
+ openapi3_parser
14
+ openapi_parser (>= 0.11.1, < 1.0)
15
+ rss
16
+ super_diff
17
+ thor
18
+ zeitwerk (~> 2.1)
19
+
20
+ GEM
21
+ remote: https://rubygems.org/
22
+ specs:
23
+ activesupport (7.0.3.1)
24
+ concurrent-ruby (~> 1.0, >= 1.0.2)
25
+ i18n (>= 1.6, < 2)
26
+ minitest (>= 5.1)
27
+ tzinfo (~> 2.0)
28
+ ast (2.4.2)
29
+ attr_extras (6.2.5)
30
+ byebug (11.1.3)
31
+ committee (4.4.0)
32
+ json_schema (~> 0.14, >= 0.14.3)
33
+ openapi_parser (>= 0.11.1, < 1.0)
34
+ rack (>= 1.5)
35
+ commonmarker (0.23.5)
36
+ concurrent-ruby (1.1.10)
37
+ deprecation (1.1.0)
38
+ activesupport
39
+ diff-lcs (1.5.0)
40
+ docile (1.4.0)
41
+ dry-container (0.10.1)
42
+ concurrent-ruby (~> 1.0)
43
+ dry-core (0.8.1)
44
+ concurrent-ruby (~> 1.0)
45
+ dry-inflector (0.3.0)
46
+ dry-logic (1.2.0)
47
+ concurrent-ruby (~> 1.0)
48
+ dry-core (~> 0.5, >= 0.5)
49
+ dry-struct (1.4.0)
50
+ dry-core (~> 0.5, >= 0.5)
51
+ dry-types (~> 1.5)
52
+ ice_nine (~> 0.11)
53
+ dry-types (1.5.1)
54
+ concurrent-ruby (~> 1.0)
55
+ dry-container (~> 0.3)
56
+ dry-core (~> 0.5, >= 0.5)
57
+ dry-inflector (~> 0.1, >= 0.1.2)
58
+ dry-logic (~> 1.0, >= 1.0.2)
59
+ edtf (3.1.0)
60
+ activesupport (>= 3.0, < 8.0)
61
+ equivalent-xml (0.6.0)
62
+ nokogiri (>= 1.4.3)
63
+ i18n (1.12.0)
64
+ concurrent-ruby (~> 1.0)
65
+ ice_nine (0.11.2)
66
+ json (2.6.2)
67
+ json_schema (0.21.0)
68
+ jsonpath (1.1.2)
69
+ multi_json
70
+ mini_portile2 (2.8.0)
71
+ minitest (5.16.3)
72
+ multi_json (1.15.0)
73
+ nokogiri (1.13.8)
74
+ mini_portile2 (~> 2.8.0)
75
+ racc (~> 1.4)
76
+ openapi3_parser (0.9.2)
77
+ commonmarker (~> 0.17)
78
+ openapi_parser (0.15.0)
79
+ optimist (3.0.1)
80
+ parallel (1.22.1)
81
+ parser (3.1.2.1)
82
+ ast (~> 2.4.1)
83
+ patience_diff (1.2.0)
84
+ optimist (~> 3.0)
85
+ racc (1.6.0)
86
+ rack (2.2.4)
87
+ rainbow (3.1.1)
88
+ rake (13.0.6)
89
+ regexp_parser (2.5.0)
90
+ rexml (3.2.5)
91
+ rspec (3.11.0)
92
+ rspec-core (~> 3.11.0)
93
+ rspec-expectations (~> 3.11.0)
94
+ rspec-mocks (~> 3.11.0)
95
+ rspec-core (3.11.0)
96
+ rspec-support (~> 3.11.0)
97
+ rspec-expectations (3.11.0)
98
+ diff-lcs (>= 1.2.0, < 2.0)
99
+ rspec-support (~> 3.11.0)
100
+ rspec-mocks (3.11.1)
101
+ diff-lcs (>= 1.2.0, < 2.0)
102
+ rspec-support (~> 3.11.0)
103
+ rspec-support (3.11.0)
104
+ rspec_junit_formatter (0.5.1)
105
+ rspec-core (>= 2, < 4, != 2.12.0)
106
+ rss (0.2.9)
107
+ rexml
108
+ rubocop (1.35.1)
109
+ json (~> 2.3)
110
+ parallel (~> 1.10)
111
+ parser (>= 3.1.2.1)
112
+ rainbow (>= 2.2.2, < 4.0)
113
+ regexp_parser (>= 1.8, < 3.0)
114
+ rexml (>= 3.2.5, < 4.0)
115
+ rubocop-ast (>= 1.20.1, < 2.0)
116
+ ruby-progressbar (~> 1.7)
117
+ unicode-display_width (>= 1.4.0, < 3.0)
118
+ rubocop-ast (1.21.0)
119
+ parser (>= 3.1.1.0)
120
+ rubocop-rake (0.6.0)
121
+ rubocop (~> 1.0)
122
+ rubocop-rspec (2.12.1)
123
+ rubocop (~> 1.31)
124
+ ruby-progressbar (1.11.0)
125
+ simplecov (0.21.2)
126
+ docile (~> 1.1)
127
+ simplecov-html (~> 0.11)
128
+ simplecov_json_formatter (~> 0.1)
129
+ simplecov-html (0.12.3)
130
+ simplecov_json_formatter (0.1.4)
131
+ super_diff (0.9.0)
132
+ attr_extras (>= 6.2.4)
133
+ diff-lcs
134
+ patience_diff
135
+ thor (1.2.1)
136
+ tzinfo (2.0.5)
137
+ concurrent-ruby (~> 1.0)
138
+ unicode-display_width (2.2.0)
139
+ zeitwerk (2.6.0)
140
+
141
+ PLATFORMS
142
+ ruby
143
+
144
+ DEPENDENCIES
145
+ bundler (~> 2.0)
146
+ byebug
147
+ cocina-models!
148
+ committee
149
+ rake (~> 13.0)
150
+ rspec (~> 3.0)
151
+ rspec_junit_formatter
152
+ rubocop (~> 1.24)
153
+ rubocop-rake
154
+ rubocop-rspec (~> 2.1)
155
+ simplecov
156
+
157
+ BUNDLED WITH
158
+ 2.3.17
data/README.md CHANGED
@@ -51,10 +51,10 @@ Beyond what is necessary to test the generator, the Cocina model classes are not
51
51
 
52
52
  ## Testing validation changes
53
53
 
54
- If there is a possibility that a model or validation change will conflict with some existing objects then [validate-cocina](https://github.com/sul-dlss/dor-services-app/blob/main/bin/validate-cocina) should be used for testing. This must be run on sdr-deploy since it requires deploying a branch of cocina-models.
54
+ If there is a possibility that a model or validation change will conflict with some existing objects then [validate-cocina](https://github.com/sul-dlss/dor-services-app/blob/main/bin/validate-cocina) should be used for testing. This must be run on sdr-infra since it requires deploying a branch of cocina-models.
55
55
 
56
- 1. Create a cocina-models branch containing the proposed change and push to Github.
57
- 2. On sdr-deploy, check out `main`, update the `Gemfile` so that cocina-models references the branch, and `bundle install`.
56
+ 1. Create a cocina-models branch containing the proposed change and push to GitHub.
57
+ 2. On sdr-infra, check out `main`, update the `Gemfile` so that cocina-models references the branch, and `bundle install`.
58
58
  3. Select the appropriate database.
59
59
  For QA:
60
60
  ```
@@ -124,18 +124,9 @@ At the same, we have found it convenient to use these PRs to also bump the versi
124
124
 
125
125
  ### Step 4: Update other dependent applications
126
126
 
127
- Once the above listed steps have been completed, all the following applications that use cocina-models should be updated and released at the same time. "Cocina Level 2" describes this set of updates.
127
+ Once the above listed steps have been completed, all applications that use cocina-models should be updated and released at the same time. "Cocina Level 2" describes this set of updates. The applications that use cocina-models are those in [this list](https://github.com/sul-dlss/access-update-scripts/blob/master/infrastructure/projects.yml) that are NOT marked with `cocina_level2: false`.
128
128
 
129
- * [sul-dlss/argo](https://github.com/sul-dlss/argo/)
130
- * [sul-dlss/common-accessioning](https://github.com/sul-dlss/common-accessioning/)
131
- * [sul-dlss/dor_indexing_app](https://github.com/sul-dlss/dor_indexing_app/)
132
- * [sul-dlss/google-books](https://github.com/sul-dlss/google-books/)
133
- * [sul-dlss/happy-heron](https://github.com/sul-dlss/happy-heron/)
134
- * [sul-dlss/hydra_etd](https://github.com/sul-dlss/hydra_etd/)
135
- * [sul-dlss/infrastructure-integration-test](https://github.com/sul-dlss/infrastructure-integration-test/)
136
- * [sul-dlss/pre-assembly](https://github.com/sul-dlss/pre-assembly/)
137
-
138
- There are scripts to help with this:
129
+ There are scripts to help with updating other dependent applications:
139
130
 
140
131
  #### Step 4A: Create the PRs
141
132
 
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cocina
4
+ module Models
5
+ DoiExceptions = Types::String.constrained(
6
+ format: %r{^10\.(25740/([vV][aA]90-[cC][tT]15|[sS][yY][xX][aA]-[mM]256|12[qQ][fF]-5243|65[jJ]8-6114)|25936/629[tT]-[bB][xX]79)$}i
7
+ )
8
+ end
9
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cocina
4
4
  module Models
5
- DOI = Types::String.constrained(
5
+ DoiPattern = Types::String.constrained(
6
6
  format: %r{^10\.(25740|80343)/[b-df-hjkmnp-tv-z]{2}[0-9]{3}[b-df-hjkmnp-tv-z]{2}[0-9]{4}$}i
7
7
  )
8
8
  end
@@ -7,8 +7,7 @@ module Cocina
7
7
  attribute? :barcode, Types::Nominal::Any
8
8
  attribute :catalogLinks, Types::Strict::Array.of(CatalogLink).default([].freeze)
9
9
  # Digital Object Identifier (https://www.doi.org)
10
- # example: 10.25740/bc123df4567
11
- attribute? :doi, Types::Strict::String
10
+ attribute? :doi, Types::Nominal::Any
12
11
  # Unique identifier in some other system. This is because a large proportion of what is deposited in SDR, historically and currently, are representations of objects that are also represented in other systems. For example, digitized paper and A/V collections have physical manifestations, and those physical objects are managed in systems that have their own identifiers. Similarly, books have barcodes, archival materials have collection numbers and physical locations, etc. The sourceId allows determining if an item has been deposited before and where to look for the original item if you're looking at its SDR representation. The format is: "namespace:identifier"
13
12
 
14
13
  # example: sul:PC0170_s3_Fiesta_Bowl_2012-01-02_210609_2026
@@ -339,7 +339,8 @@ module Cocina
339
339
  end
340
340
  notes = name_notes_for(full_name[:role], node)
341
341
  name_attrs[:note] = notes unless notes.empty?
342
- name_attrs.merge(attrs)
342
+ name_attrs[:identifier] = full_name[:identifier]
343
+ name_attrs.compact.merge(attrs)
343
344
  end
344
345
 
345
346
  def name_notes_for(roles, name_node)
@@ -70,12 +70,10 @@ module Cocina
70
70
  end
71
71
 
72
72
  def extract_type(geo)
73
- type = geo[:form].find do |form|
74
- form[:type].match(TYPE_REGEX) || (form[:type].match(MEDIA_REGEX) && form[:value] == 'Image')
73
+ type = geo.form.find do |form|
74
+ form.type.match?(TYPE_REGEX) || (form.type.match?(MEDIA_REGEX) && form.value == 'Image')
75
75
  end
76
- return type[:value] if type
77
-
78
- nil
76
+ type&.value
79
77
  end
80
78
 
81
79
  def about(druid)
@@ -230,8 +230,11 @@ module Cocina
230
230
  # Write nodes within MODS subject
231
231
  def write_topic(subject, subject_value, is_parallel: false, type: nil, subject_values_have_same_authority: true)
232
232
  type ||= subject_value.type
233
- topic_attributes = topic_attributes_for(subject, subject_value, type, is_parallel: is_parallel,
234
- subject_values_have_same_authority: subject_values_have_same_authority)
233
+ topic_attributes = topic_attributes_for(subject,
234
+ subject_value,
235
+ type,
236
+ is_parallel: is_parallel,
237
+ subject_values_have_same_authority: subject_values_have_same_authority)
235
238
  case type
236
239
  when 'person'
237
240
  xml.name topic_attributes.merge(type: 'personal') do
@@ -395,6 +398,7 @@ module Cocina
395
398
  write_name_part(subject_value)
396
399
  write_display_form(display_values)
397
400
  write_roles(subject_value.note)
401
+ write_identifier(subject.identifier)
398
402
  write_other_notes(subject.note, 'description')
399
403
  write_other_notes(subject.note, 'affiliation')
400
404
  end
@@ -427,6 +431,12 @@ module Cocina
427
431
  end.each { |role| RoleWriter.write(xml: xml, role: role) }
428
432
  end
429
433
 
434
+ def write_identifier(identifiers)
435
+ identifiers.each do |identifier|
436
+ xml.nameIdentifier identifier.value, type: identifier.source.code
437
+ end
438
+ end
439
+
430
440
  def write_other_notes(notes, type)
431
441
  Array(notes).filter { |note| note.type == type }.each { |note| xml.public_send(type, note.value) }
432
442
  end
@@ -68,7 +68,15 @@ module Cocina
68
68
  Date.edtf!(value)
69
69
  true
70
70
  rescue StandardError
71
- false
71
+ # NOTE: the upstream EDTF implementation in the `edtf` gem does not
72
+ # allow a valid pattern that we use (possibly because only level
73
+ # 0 of the spec was implemented?):
74
+ #
75
+ # * Y-20555
76
+ #
77
+ # So we catch the false positives from the upstream gem and allow
78
+ # this pattern to validate
79
+ /\AY-?\d{5,}\Z/.match?(value)
72
80
  end
73
81
 
74
82
  def valid_iso8601?(value)
@@ -90,7 +98,9 @@ module Cocina
90
98
  #
91
99
  # So we catch the false positives from the upstream gem and allow
92
100
  # these two patterns to validate
93
- /\A\d{4}(-0[1-9]|1[0-2])?\Z/.match?(value)
101
+ #
102
+ # Also have a temporary exemption for MM/DD/YY
103
+ %r{\A((\d{4}(-0[1-9]|-1[0-2])?)|(\d{2}/\d{2}/\d{2}))\Z}.match?(value)
94
104
  end
95
105
 
96
106
  def druid
@@ -12,7 +12,8 @@ module Cocina
12
12
  CatalogLinksValidator,
13
13
  AssociatedNameValidator,
14
14
  DescriptionTypesValidator,
15
- DescriptionValuesValidator
15
+ DescriptionValuesValidator,
16
+ DateTimeValidator
16
17
  ].freeze
17
18
 
18
19
  def self.validate(clazz, attributes)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Cocina
4
4
  module Models
5
- VERSION = '0.82.0'
5
+ VERSION = '0.84.1'
6
6
  end
7
7
  end
data/lib/cocina/models.rb CHANGED
@@ -40,7 +40,7 @@ loader = Zeitwerk::Loader.new
40
40
  loader.inflector = CocinaModelsInflector.new
41
41
  loader.push_dir(File.absolute_path("#{__FILE__}/../.."))
42
42
  loader.ignore("#{__dir__}/rspec.rb")
43
- loader.ignore("#{__dir__}/rspec/**/*.rb")
43
+ loader.ignore("#{__dir__}/rspec")
44
44
  loader.setup
45
45
 
46
46
  module Cocina
@@ -153,5 +153,12 @@ module Cocina
153
153
  raise ValidationError, 'Type field not found'
154
154
  end
155
155
  private_class_method :type_for
156
+
157
+ def self.druid_regex
158
+ @druid_regex ||= begin
159
+ str = Openapi3Parser.load_file('openapi.yml').components.schemas['Druid'].pattern
160
+ Regexp.new(str)
161
+ end
162
+ end
156
163
  end
157
164
  end
data/openapi.yml CHANGED
@@ -390,7 +390,7 @@ components:
390
390
  - catalogRecordId
391
391
  - refresh
392
392
  CatkeyBarcode:
393
- description: The barcode associated with a DRO object based on catkey, prefixed with 36105
393
+ description: The barcode associated with a DRO object based on catkey, prefixed with a catkey followed by a hyphen
394
394
  type: string
395
395
  pattern: '^[0-9]+-[0-9]+$'
396
396
  example: '6772719-1001'
@@ -896,8 +896,18 @@ components:
896
896
  # description: An alphabet or other notation used to represent a
897
897
  # language or other symbolic system of the descriptive element value.
898
898
  DOI:
899
- type: string
900
899
  description: Digital Object Identifier (https://www.doi.org)
900
+ oneOf:
901
+ - $ref: '#/components/schemas/DoiPattern'
902
+ - $ref: '#/components/schemas/DoiExceptions'
903
+ DoiExceptions:
904
+ type: string
905
+ description: pre-existing Digital Object Identifiers (https://www.doi.org) not matching the pattern (case insensitive)
906
+ pattern: '^10\.(25740\/([vV][aA]90-[cC][tT]15|[sS][yY][xX][aA]-[mM]256|12[qQ][fF]-5243|65[jJ]8-6114)|25936\/629[tT]-[bB][xX]79)$'
907
+ example: '10.25740/12qF-5243'
908
+ DoiPattern:
909
+ type: string
910
+ description: Digital Object Identifier (https://www.doi.org) regex pattern
901
911
  # The prod and test prefixes are permitted
902
912
  pattern: '^10\.(25740|80343)\/[b-df-hjkmnp-tv-z]{2}[0-9]{3}[b-df-hjkmnp-tv-z]{2}[0-9]{4}$'
903
913
  example: '10.25740/bc123df4567'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocina-models
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.82.0
4
+ version: 0.84.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-06-17 00:00:00.000000000 Z
11
+ date: 2022-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -339,6 +339,7 @@ files:
339
339
  - ".rubocop.yml"
340
340
  - ".rubocop_todo.yml"
341
341
  - Gemfile
342
+ - Gemfile.lock
342
343
  - README.md
343
344
  - Rakefile
344
345
  - bin/console
@@ -397,7 +398,8 @@ files:
397
398
  - lib/cocina/models/descriptive_structured_value.rb
398
399
  - lib/cocina/models/descriptive_value.rb
399
400
  - lib/cocina/models/descriptive_value_language.rb
400
- - lib/cocina/models/doi.rb
401
+ - lib/cocina/models/doi_exceptions.rb
402
+ - lib/cocina/models/doi_pattern.rb
401
403
  - lib/cocina/models/dro.rb
402
404
  - lib/cocina/models/dro_access.rb
403
405
  - lib/cocina/models/dro_structural.rb