cocina-models 0.111.0 → 0.112.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9413e8b89ec5fb07324b39abda8c6f972805fef2efa4f34f8033822d871805d9
4
- data.tar.gz: 65e171f1d076c1d8b9d3663afd54d7f7824e01f3a34ac191620749294ca3346d
3
+ metadata.gz: 021d53c09f577e12fbfd215fc37bec5acb2b4da9dd6c8b4803153d107c9d9e80
4
+ data.tar.gz: e0e1553f9e8f6e3a3a7bbb032fb6bdb9f9b41c98e71d0c46b1bbe9ef53eab23a
5
5
  SHA512:
6
- metadata.gz: 7bbcac9101f211ca947e80c9e8c8ae0549cec2ecee1de138b0d0295525381590bfad717b72fa765fc37e94021b0c9e9ba2e6f65294a933ef7ade7ac64b58d035
7
- data.tar.gz: 7f7581fe97bf77bc0ac1dce8fbb47fe9ee4689f6f03012b53618df6d891da4c04c4580b7cf141f356b218d6dfcacc4d27f317e059dbf53ed07fa27a6059a4df6
6
+ metadata.gz: df70b91ae041970111a9a30a299a33e35057a6beaede5894e5a94cf01909072c62e441744dd2c638f05dd19b2634d7dc0fe5ffecbc0d23cfb67a5cc231baa4d3
7
+ data.tar.gz: 6f66fd83a7d8d41b361ef7c7c24600796272f68f41b74161e756519039ae37703e24edc7362c60cfae7c78dec95bae7d9ee2b4eaef36dcc1dc9fd4a83b15262b
data/.circleci/config.yml CHANGED
@@ -4,10 +4,12 @@ orbs:
4
4
  workflows:
5
5
  build:
6
6
  jobs:
7
- - ruby-rails/validate-api:
8
- name: validate
9
7
  - ruby-rails/lint:
10
8
  name: lint
11
9
  - ruby-rails/test-gem:
12
10
  name: test
13
11
  context: dlss
12
+ before-test:
13
+ - run:
14
+ name: validate openapi
15
+ command: bin/validate-schema schema.json
@@ -1,5 +1,3 @@
1
- **NOTE: Changes to openapi.yml require updating openapi.yml for sdr-api and dor-services-app and generating models - see README.**
2
-
3
1
  ## Why was this change made? 🤔
4
2
 
5
3
 
@@ -7,6 +5,3 @@
7
5
  ## How was this change tested? 🤨
8
6
 
9
7
  ⚡ ⚠ If this change has cross service impact, ***run [integration tests](https://github.com/sul-dlss/infrastructure-integration-test)*** and/or test in [stage|qa] environment, in addition to specs. ⚡
10
-
11
-
12
-
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cocina-models (0.111.0)
4
+ cocina-models (0.112.0)
5
5
  activesupport
6
6
  deprecation
7
7
  dry-struct (~> 1.0)
@@ -98,13 +98,13 @@ GEM
98
98
  minitest (6.0.1)
99
99
  prism (~> 1.5)
100
100
  multi_json (1.19.1)
101
- nokogiri (1.19.0-arm64-darwin)
101
+ nokogiri (1.19.1-arm64-darwin)
102
102
  racc (~> 1.4)
103
- nokogiri (1.19.0-x86_64-linux-gnu)
103
+ nokogiri (1.19.1-x86_64-linux-gnu)
104
104
  racc (~> 1.4)
105
105
  optimist (3.2.1)
106
106
  parallel (1.27.0)
107
- parser (3.3.10.1)
107
+ parser (3.3.10.2)
108
108
  ast (~> 2.4.1)
109
109
  racc
110
110
  patience_diff (1.2.0)
@@ -183,7 +183,7 @@ GEM
183
183
  unicode-emoji (~> 4.1)
184
184
  unicode-emoji (4.2.0)
185
185
  uri (1.1.1)
186
- zeitwerk (2.7.4)
186
+ zeitwerk (2.7.5)
187
187
 
188
188
  PLATFORMS
189
189
  arm64-darwin
@@ -207,7 +207,7 @@ CHECKSUMS
207
207
  attr_extras (7.1.0) sha256=d96fc9a9dd5d85ba2d37762440a816f840093959ae26bb90da994c2d9f1fc827
208
208
  base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
209
209
  bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7
210
- cocina-models (0.111.0)
210
+ cocina-models (0.112.0)
211
211
  concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
212
212
  connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
213
213
  date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0
@@ -237,11 +237,11 @@ CHECKSUMS
237
237
  logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
238
238
  minitest (6.0.1) sha256=7854c74f48e2e975969062833adc4013f249a4b212f5e7b9d5c040bf838d54bb
239
239
  multi_json (1.19.1) sha256=7aefeff8f2c854bf739931a238e4aea64592845e0c0395c8a7d2eea7fdd631b7
240
- nokogiri (1.19.0-arm64-darwin) sha256=0811dfd936d5f6dd3f6d32ef790568bf29b2b7bead9ba68866847b33c9cf5810
241
- nokogiri (1.19.0-x86_64-linux-gnu) sha256=f482b95c713d60031d48c44ce14562f8d2ce31e3a9e8dd0ccb131e9e5a68b58c
240
+ nokogiri (1.19.1-arm64-darwin) sha256=dfe2d337e6700eac47290407c289d56bcf85805d128c1b5a6434ddb79731cb9e
241
+ nokogiri (1.19.1-x86_64-linux-gnu) sha256=1a4902842a186b4f901078e692d12257678e6133858d0566152fe29cdb98456a
242
242
  optimist (3.2.1) sha256=8cf8a0fd69f3aa24ab48885d3a666717c27bc3d9edd6e976e18b9d771e72e34e
243
243
  parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
244
- parser (3.3.10.1) sha256=06f6a725d2cd91e5e7f2b7c32ba143631e1f7c8ae2fb918fc4cebec187e6a688
244
+ parser (3.3.10.2) sha256=6f60c84aa4bdcedb6d1a2434b738fe8a8136807b6adc8f7f53b97da9bc4e9357
245
245
  patience_diff (1.2.0) sha256=f492094486af02fff4a80070fa6b4d0ebbcf4d42fb38bba29d095eef43f6822c
246
246
  pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
247
247
  prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
@@ -277,7 +277,7 @@ CHECKSUMS
277
277
  unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
278
278
  unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
279
279
  uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
280
- zeitwerk (2.7.4) sha256=2bef90f356bdafe9a6c2bd32bcd804f83a4f9b8bc27f3600fff051eb3edcec8b
280
+ zeitwerk (2.7.5) sha256=d8da92128c09ea6ec62c949011b00ed4a20242b255293dd66bf41545398f73dd
281
281
 
282
282
  BUNDLED WITH
283
283
  4.0.6
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  The cocina-models gem is a Ruby implementation of the Stanford Digital Repository (SDR) data model, which we named "Cocina." The data being modeled is oriented around digital repository objects.
9
9
 
10
- The data model is expressed in an OpenAPI specification that lives in this codebase. Expressing the model in such a spec allows for rich validation (using gems such as `OpenAPIParser` and `committee`). The gem provides a set of generators (see below) to generate Ruby classes from the specification, with modeling provided by dry-struct / dry-types. Together, these provide a way for consumers to validate objects against models and to manipulate those objects.
10
+ The data model is expressed in an OpenAPI specification that lives in this codebase. Expressing the model in such a spec allows for rich validation (using gems such as `json_schemer`). The gem provides a set of generators (see below) to generate Ruby classes from the specification, with modeling provided by dry-struct / dry-types. Together, these provide a way for consumers to validate objects against models and to manipulate those objects.
11
11
 
12
12
  Note that the data model encodes properties as camelCase, which the team believes to be consistent with other HTTP APIs and the original design of the Cocina data model. While using camelCase in Ruby code may look and feel wrong, we did explore automagic conversion between camelCase in the model and snake_case in the Ruby context. We ultimately concluded that we have enough representations of the data model in enough codebases to reasonably worry about data inconsistency problems, none of which we need in our work on SDR.
13
13
 
@@ -20,9 +20,9 @@ Set the PURL url base:
20
20
  Cocina::Models::Mapping::Purl.base_url = Settings.release.purl_base_url
21
21
  ```
22
22
 
23
- ## Generate models from openapi.yml
23
+ ## Generate models from schema.json
24
24
 
25
- Note that only a small subset of openapi is supported. If you are using a new openapi feature or pattern, verify that the model will be generated as expected.
25
+ Note that only a small subset of JSON Schema is supported. If you are using a new JSON Schema feature or pattern, verify that the model will be generated as expected.
26
26
 
27
27
  ### All
28
28
  ```
@@ -46,14 +46,16 @@ exe/generator generate_descriptive_docs
46
46
 
47
47
  ## Testing
48
48
 
49
- The generator is tested via its output when run against `openapi.yml`, viz., the Cocina model classes. Thus, `generate` should be run after any changes to `openapi.yml`.
49
+ The generator is tested via its output when run against `schema.json`, viz., the Cocina model classes. Thus, `generate` should be run after any changes to `schema.json`.
50
50
 
51
- Beyond what is necessary to test the generator, the Cocina model classes are not tested, i.e., they are assumed to be as specified in `openapi.yml`.
51
+ Beyond what is necessary to test the generator, the Cocina model classes are not tested, i.e., they are assumed to be as specified in `schema.json`.
52
52
 
53
53
  ## Testing validation changes
54
54
 
55
55
  If there is a possibility that a model, mapping, 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 the `sdr-infra` VM since it requires deploying a branch of cocina-models.
56
56
 
57
+ For background on object validation, as it relates to migrating versions, see: https://github.com/sul-dlss/dor-services-app/wiki/Migrating-Cocina
58
+
57
59
  1. Create a cocina-models branch containing the proposed change and push to GitHub.
58
60
  2. On the `sdr-infra` VM, while logged in as the `deploy` user, check out `main`, update the `Gemfile` so that cocina-models references the branch, and `bundle install`.
59
61
  3. Select the appropriate environment vars below - they are set to values in puppet. (first 2 lines are the same; last two lines use different variables)
@@ -87,6 +89,13 @@ export DATABASE_PASSWORD=$DOR_SERVICES_DB_PROD_PWD
87
89
  export RUBYOPT='-W:no-deprecated -W:no-experimental'
88
90
  RAILS_ENV=production bin/validate-cocina -p 8
89
91
  ```
92
+
93
+ To run against head_version and latest_closed_version (when the object is open) only, use the `-l` option for `latest_versions_only`
94
+ ```
95
+ export RUBYOPT='-W:no-deprecated -W:no-experimental'
96
+ RAILS_ENV=production bin/validate-cocina -p 8 -l
97
+ ```
98
+
90
99
  5. Check `validate-cocina.csv` for validation errors.
91
100
 
92
101
  ## Running Reports in DSA
@@ -95,7 +104,7 @@ See https://github.com/sul-dlss/dor-services-app/blob/main/README.md#running-rep
95
104
 
96
105
 
97
106
  ## Releasing a patch change
98
- A patch change is a change that (1) does not affect the data model; (2) does not alter the openapi.yml; and more broadly (3) does not matter if some applications have the change and others do not.
107
+ A patch change is a change that (1) does not affect the data model; (2) does not alter the schema.json; and more broadly (3) does not matter if some applications have the change and others do not.
99
108
 
100
109
  A patch change can be released as part of regular dependency updates or selectively released for individual applications.
101
110
 
@@ -146,13 +155,11 @@ This list of services is known to include:
146
155
 
147
156
  **NOTE**: You can skip step 3A if there have not been any changes to the `cocina-models` OpenAPI spec since the prior release.
148
157
 
149
- The cocina-models gem is used in applications that have an API specification that accepts Cocina models. Make sure that the `openapi.yml` for these two applications includes the `openapi.yml` schema changes made in cocina-models.
150
-
151
- Copy and paste the cocina-models schemas to each project's `openapi.yml`. By convention, these schemas are listed first, followed by the application-specific schemas.
158
+ The cocina-models gem is used in applications that have an API specification that accepts Cocina models.
152
159
 
153
160
  #### Step 3B: Bump gems and create the PRs
154
161
 
155
- If you updated the `openapi.yml` in step 3A, use the same PR for step 3B. Why? When [dor-services-app](https://github.com/sul-dlss/dor-services-app), for example, is updated to use the new models (via the auto-update script), these clients should be updated at the same time or there is risk of models produced by dor-services-app not being acceptable to the clients.
162
+ If you updated the `schema.json` in step 3A, use the same PR for step 3B. Why? When [dor-services-app](https://github.com/sul-dlss/dor-services-app), for example, is updated to use the new models (via the auto-update script), these clients should be updated at the same time or there is risk of models produced by dor-services-app not being acceptable to the clients.
156
163
 
157
164
  1. Perform `bundle update --conservative cocina-models dor-services-client` in the services above and make PRs for those repos if they don't already exist. You may first need to update how these gems are pinned in the `Gemfile` in order to bump them.
158
165
  2. Note that sdr-client is not currently used in these applications, but if it were, would also need to be bumped to the latest release.
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'cocina/models'
6
+
7
+ filepath = ARGV[0]
8
+ exit(1) unless JSONSchemer.valid_schema?(Pathname.new(filepath))
@@ -8,7 +8,7 @@ module Cocina
8
8
  class Generator < Thor # rubocop:disable Metrics/ClassLength
9
9
  include Thor::Actions
10
10
 
11
- class_option :openapi, desc: 'Path of openapi.yml', default: 'openapi.yml'
11
+ class_option :schema, desc: 'Path of schema.json', default: 'schema.json'
12
12
  class_option :output, desc: 'Path for output', default: 'lib/cocina/models'
13
13
 
14
14
  def self.source_root
@@ -96,9 +96,9 @@ module Cocina
96
96
  end
97
97
 
98
98
  def schemas
99
- @schemas ||= Cocina::OpenApiWrapper.parse(YAML.load_file(options[:openapi]), strict_reference_validation: true)
100
- .components
101
- .schemas
99
+ file_content = File.read(options[:schema])
100
+ data = JSON.parse(file_content)
101
+ @schemas ||= Cocina::JsonSchemaWrapper.parse(data, strict_reference_validation: true).schemas
102
102
  end
103
103
 
104
104
  def schema_for(schema_name, lite: false)
@@ -8,6 +8,9 @@ module Cocina
8
8
  @schema_properties ||= (properties + all_of_properties + one_of_properties).uniq(&:key)
9
9
  end
10
10
 
11
+ VALIDATE_TYPES = %w[DRO RequestDRO DROWithMetadata Collection RequestCollection CollectionWithMetadata AdminPolicy
12
+ RequestAdminPolicy AdminPolicyWithMetadata Description RequestDescription].freeze
13
+
11
14
  def generate
12
15
  <<~RUBY
13
16
  # frozen_string_literal: true
@@ -71,7 +74,7 @@ module Cocina
71
74
  end
72
75
 
73
76
  def validatable?
74
- !schema_doc.root.paths.path["/validate/#{schema_doc.name}"].nil? && !lite
77
+ VALIDATE_TYPES.include?(name) && !lite
75
78
  end
76
79
 
77
80
  def properties
@@ -40,6 +40,8 @@ module Cocina
40
40
  def quote(item)
41
41
  return item unless schema_doc.type == 'string'
42
42
 
43
+ return 'nil' if item.nil?
44
+
43
45
  "'#{item}'"
44
46
  end
45
47
 
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cocina
4
- # Wrapper for OpenAPI support using json_schemer
5
- class OpenApiWrapper
4
+ # Wrapper for JSON Schema support using json_schemer
5
+ class JsonSchemaWrapper
6
6
  class OpenApiError < StandardError; end
7
7
  class MissingReferenceError < OpenApiError; end
8
8
 
@@ -18,33 +18,18 @@ module Cocina
18
18
  new(spec_hash, strict_reference_validation:)
19
19
  end
20
20
 
21
- def components
22
- @components ||= ComponentsWrapper.new(self)
23
- end
24
-
25
21
  attr_reader :schemas, :spec
26
22
 
27
23
  private
28
24
 
29
25
  def initialize_schemas
30
- return unless @spec.dig('components', 'schemas')
26
+ return unless @spec.key?('$defs')
31
27
 
32
- spec['components']['schemas'].each do |name, schema|
28
+ spec.fetch('$defs').each do |name, schema|
33
29
  @schemas[name] = SchemaWrapper.new(schema, name, self)
34
30
  end
35
31
  end
36
32
 
37
- # Wrapper for components section
38
- class ComponentsWrapper
39
- def initialize(parent)
40
- @parent = parent
41
- end
42
-
43
- def schemas
44
- @parent.schemas
45
- end
46
- end
47
-
48
33
  # Wrapper for individual schemas
49
34
  class SchemaWrapper
50
35
  attr_reader :name
@@ -65,7 +50,7 @@ module Cocina
65
50
  @schema_def['oneOf'].map do |schema|
66
51
  if schema['$ref']
67
52
  ref_name = schema['$ref'].split('/').last
68
- SchemaWrapper.new(@parent.spec.dig('components', 'schemas', ref_name), ref_name, @parent)
53
+ SchemaWrapper.new(@parent.spec.dig('$defs', ref_name), ref_name, @parent)
69
54
  else
70
55
  SchemaWrapper.new(schema, nil, @parent)
71
56
  end
@@ -78,7 +63,7 @@ module Cocina
78
63
  @schema_def['allOf'].map do |schema|
79
64
  if schema['$ref']
80
65
  ref_name = schema['$ref'].split('/').last
81
- SchemaWrapper.new(@parent.spec.dig('components', 'schemas', ref_name), ref_name, @parent)
66
+ SchemaWrapper.new(@parent.spec.dig('$defs', ref_name), ref_name, @parent)
82
67
  else
83
68
  SchemaWrapper.new(schema, nil, @parent)
84
69
  end
@@ -89,7 +74,7 @@ module Cocina
89
74
  @schema_def['properties']&.transform_values do |schema|
90
75
  if schema['$ref']
91
76
  ref_name = schema['$ref'].split('/').last
92
- SchemaWrapper.new(@parent.spec.dig('components', 'schemas', ref_name), ref_name, @parent)
77
+ SchemaWrapper.new(@parent.spec.dig('$defs', ref_name), ref_name, @parent)
93
78
  else
94
79
  SchemaWrapper.new(schema, nil, @parent)
95
80
  end
@@ -137,7 +122,7 @@ module Cocina
137
122
 
138
123
  if @schema_def['items']['$ref']
139
124
  ref_name = @schema_def['items']['$ref'].split('/').last
140
- SchemaWrapper.new(@parent.spec.dig('components', 'schemas', ref_name), ref_name, @parent)
125
+ SchemaWrapper.new(@parent.spec.dig('$defs', ref_name), ref_name, @parent)
141
126
  else
142
127
  SchemaWrapper.new(@schema_def['items'], Generator::SchemaArray::GENERIC_ITEMS_NAME, @parent)
143
128
  end
@@ -17,7 +17,7 @@ module Cocina
17
17
  attribute? :useAndReproductionStatement, UseAndReproductionStatement.optional
18
18
  # The license governing reuse of the DRO. Should be an IRI for known licenses (i.e.
19
19
  # CC, RightsStatement.org URI, etc.).
20
- attribute? :license, License.optional.enum('https://www.gnu.org/licenses/agpl.txt', 'https://www.apache.org/licenses/LICENSE-2.0', 'https://opensource.org/licenses/BSD-2-Clause', 'https://opensource.org/licenses/BSD-3-Clause', 'https://creativecommons.org/licenses/by/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode', 'https://creativecommons.org/licenses/by-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-sa/4.0/legalcode', 'https://creativecommons.org/publicdomain/zero/1.0/legalcode', 'https://opensource.org/licenses/cddl1', 'https://www.eclipse.org/legal/epl-2.0', 'https://www.gnu.org/licenses/gpl-3.0-standalone.html', 'https://www.isc.org/downloads/software-support-policy/isc-license/', 'https://www.gnu.org/licenses/lgpl-3.0-standalone.html', 'https://opensource.org/licenses/MIT', 'https://www.mozilla.org/MPL/2.0/', 'https://opendatacommons.org/licenses/by/1-0/', 'http://opendatacommons.org/licenses/odbl/1.0/', 'https://opendatacommons.org/licenses/odbl/1-0/', 'https://creativecommons.org/publicdomain/mark/1.0/', 'https://opendatacommons.org/licenses/pddl/1-0/', 'https://creativecommons.org/licenses/by/3.0/legalcode', 'https://creativecommons.org/licenses/by-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nd/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', 'https://cocina.sul.stanford.edu/licenses/none')
20
+ attribute? :license, License.optional.enum(nil, 'https://www.gnu.org/licenses/agpl.txt', 'https://www.apache.org/licenses/LICENSE-2.0', 'https://opensource.org/licenses/BSD-2-Clause', 'https://opensource.org/licenses/BSD-3-Clause', 'https://creativecommons.org/licenses/by/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode', 'https://creativecommons.org/licenses/by-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-sa/4.0/legalcode', 'https://creativecommons.org/publicdomain/zero/1.0/legalcode', 'https://opensource.org/licenses/cddl1', 'https://www.eclipse.org/legal/epl-2.0', 'https://www.gnu.org/licenses/gpl-3.0-standalone.html', 'https://www.isc.org/downloads/software-support-policy/isc-license/', 'https://www.gnu.org/licenses/lgpl-3.0-standalone.html', 'https://opensource.org/licenses/MIT', 'https://www.mozilla.org/MPL/2.0/', 'https://opendatacommons.org/licenses/by/1-0/', 'http://opendatacommons.org/licenses/odbl/1.0/', 'https://opendatacommons.org/licenses/odbl/1-0/', 'https://creativecommons.org/publicdomain/mark/1.0/', 'https://opendatacommons.org/licenses/pddl/1-0/', 'https://creativecommons.org/licenses/by/3.0/legalcode', 'https://creativecommons.org/licenses/by-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nd/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', 'https://cocina.sul.stanford.edu/licenses/none')
21
21
  # Access level.
22
22
  # Validation of this property is relaxed. See the openapi for full validation.
23
23
  attribute? :view, Types::Strict::String.optional.default('dark')
@@ -10,7 +10,7 @@ module Cocina
10
10
  # Download access level.
11
11
  attribute :download, Types::Strict::String.enum('none')
12
12
  # Not used for this access type, must be null.
13
- attribute? :location, Types::Strict::String.optional.enum('')
13
+ attribute? :location, Types::Strict::String.optional.enum(nil)
14
14
  attribute? :controlledDigitalLending, Types::Strict::Bool.default(false).enum(false)
15
15
  end
16
16
  end
@@ -17,7 +17,7 @@ module Cocina
17
17
  attribute? :useAndReproductionStatement, UseAndReproductionStatement.optional
18
18
  # The license governing reuse of the DRO. Should be an IRI for known licenses (i.e.
19
19
  # CC, RightsStatement.org URI, etc.).
20
- attribute? :license, License.optional.enum('https://www.gnu.org/licenses/agpl.txt', 'https://www.apache.org/licenses/LICENSE-2.0', 'https://opensource.org/licenses/BSD-2-Clause', 'https://opensource.org/licenses/BSD-3-Clause', 'https://creativecommons.org/licenses/by/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode', 'https://creativecommons.org/licenses/by-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-sa/4.0/legalcode', 'https://creativecommons.org/publicdomain/zero/1.0/legalcode', 'https://opensource.org/licenses/cddl1', 'https://www.eclipse.org/legal/epl-2.0', 'https://www.gnu.org/licenses/gpl-3.0-standalone.html', 'https://www.isc.org/downloads/software-support-policy/isc-license/', 'https://www.gnu.org/licenses/lgpl-3.0-standalone.html', 'https://opensource.org/licenses/MIT', 'https://www.mozilla.org/MPL/2.0/', 'https://opendatacommons.org/licenses/by/1-0/', 'http://opendatacommons.org/licenses/odbl/1.0/', 'https://opendatacommons.org/licenses/odbl/1-0/', 'https://creativecommons.org/publicdomain/mark/1.0/', 'https://opendatacommons.org/licenses/pddl/1-0/', 'https://creativecommons.org/licenses/by/3.0/legalcode', 'https://creativecommons.org/licenses/by-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nd/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', 'https://cocina.sul.stanford.edu/licenses/none')
20
+ attribute? :license, License.optional.enum(nil, 'https://www.gnu.org/licenses/agpl.txt', 'https://www.apache.org/licenses/LICENSE-2.0', 'https://opensource.org/licenses/BSD-2-Clause', 'https://opensource.org/licenses/BSD-3-Clause', 'https://creativecommons.org/licenses/by/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode', 'https://creativecommons.org/licenses/by-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-sa/4.0/legalcode', 'https://creativecommons.org/publicdomain/zero/1.0/legalcode', 'https://opensource.org/licenses/cddl1', 'https://www.eclipse.org/legal/epl-2.0', 'https://www.gnu.org/licenses/gpl-3.0-standalone.html', 'https://www.isc.org/downloads/software-support-policy/isc-license/', 'https://www.gnu.org/licenses/lgpl-3.0-standalone.html', 'https://opensource.org/licenses/MIT', 'https://www.mozilla.org/MPL/2.0/', 'https://opendatacommons.org/licenses/by/1-0/', 'http://opendatacommons.org/licenses/odbl/1.0/', 'https://opendatacommons.org/licenses/odbl/1-0/', 'https://creativecommons.org/publicdomain/mark/1.0/', 'https://opendatacommons.org/licenses/pddl/1-0/', 'https://creativecommons.org/licenses/by/3.0/legalcode', 'https://creativecommons.org/licenses/by-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nd/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', 'https://cocina.sul.stanford.edu/licenses/none')
21
21
  end
22
22
  end
23
23
  end
@@ -8,7 +8,7 @@ module Cocina
8
8
  # Download access level.
9
9
  attribute :download, Types::Strict::String.enum('none')
10
10
  # Not used for this access type, must be null.
11
- attribute? :location, Types::Strict::String.optional.enum('')
11
+ attribute? :location, Types::Strict::String.optional.enum(nil)
12
12
  # Available for controlled digital lending.
13
13
  attribute? :controlledDigitalLending, Types::Strict::Bool.default(false)
14
14
  end
@@ -8,7 +8,7 @@ module Cocina
8
8
  # Download access level.
9
9
  attribute? :download, Types::Strict::String.default('none').enum('none')
10
10
  # Not used for this access type, must be null.
11
- attribute? :location, Types::Strict::String.optional.enum('')
11
+ attribute? :location, Types::Strict::String.optional.enum(nil)
12
12
  attribute? :controlledDigitalLending, Types::Strict::Bool.default(false).enum(false)
13
13
  end
14
14
  end
@@ -26,7 +26,7 @@ module Cocina
26
26
  attribute? :useAndReproductionStatement, UseAndReproductionStatement.optional
27
27
  # The license governing reuse of the DRO. Should be an IRI for known licenses (i.e.
28
28
  # CC, RightsStatement.org URI, etc.).
29
- attribute? :license, License.optional.enum('https://www.gnu.org/licenses/agpl.txt', 'https://www.apache.org/licenses/LICENSE-2.0', 'https://opensource.org/licenses/BSD-2-Clause', 'https://opensource.org/licenses/BSD-3-Clause', 'https://creativecommons.org/licenses/by/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode', 'https://creativecommons.org/licenses/by-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-sa/4.0/legalcode', 'https://creativecommons.org/publicdomain/zero/1.0/legalcode', 'https://opensource.org/licenses/cddl1', 'https://www.eclipse.org/legal/epl-2.0', 'https://www.gnu.org/licenses/gpl-3.0-standalone.html', 'https://www.isc.org/downloads/software-support-policy/isc-license/', 'https://www.gnu.org/licenses/lgpl-3.0-standalone.html', 'https://opensource.org/licenses/MIT', 'https://www.mozilla.org/MPL/2.0/', 'https://opendatacommons.org/licenses/by/1-0/', 'http://opendatacommons.org/licenses/odbl/1.0/', 'https://opendatacommons.org/licenses/odbl/1-0/', 'https://creativecommons.org/publicdomain/mark/1.0/', 'https://opendatacommons.org/licenses/pddl/1-0/', 'https://creativecommons.org/licenses/by/3.0/legalcode', 'https://creativecommons.org/licenses/by-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nd/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', 'https://cocina.sul.stanford.edu/licenses/none')
29
+ attribute? :license, License.optional.enum(nil, 'https://www.gnu.org/licenses/agpl.txt', 'https://www.apache.org/licenses/LICENSE-2.0', 'https://opensource.org/licenses/BSD-2-Clause', 'https://opensource.org/licenses/BSD-3-Clause', 'https://creativecommons.org/licenses/by/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode', 'https://creativecommons.org/licenses/by-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-sa/4.0/legalcode', 'https://creativecommons.org/publicdomain/zero/1.0/legalcode', 'https://opensource.org/licenses/cddl1', 'https://www.eclipse.org/legal/epl-2.0', 'https://www.gnu.org/licenses/gpl-3.0-standalone.html', 'https://www.isc.org/downloads/software-support-policy/isc-license/', 'https://www.gnu.org/licenses/lgpl-3.0-standalone.html', 'https://opensource.org/licenses/MIT', 'https://www.mozilla.org/MPL/2.0/', 'https://opendatacommons.org/licenses/by/1-0/', 'http://opendatacommons.org/licenses/odbl/1.0/', 'https://opendatacommons.org/licenses/odbl/1-0/', 'https://creativecommons.org/publicdomain/mark/1.0/', 'https://opendatacommons.org/licenses/pddl/1-0/', 'https://creativecommons.org/licenses/by/3.0/legalcode', 'https://creativecommons.org/licenses/by-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nd/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', 'https://cocina.sul.stanford.edu/licenses/none')
30
30
  end
31
31
  end
32
32
  end
@@ -27,7 +27,7 @@ module Cocina
27
27
  # BCP 47 language tag: https://www.rfc-editor.org/rfc/rfc4646.txt -- other applications
28
28
  # (like media players) expect language codes of this format, see e.g. https://videojs.com/guides/text-tracks/#srclang
29
29
  attribute? :languageTag, LanguageTag.optional
30
- # Use for the File (e.g. "transcription" for OCR).
30
+ # Use for the File (e.g. 'transcription' for OCR).
31
31
  attribute? :use, FileUse.optional
32
32
  # Indicates if the text (OCR/captioning) was generated by SDR.
33
33
  attribute? :sdrGeneratedText, Types::Strict::Bool.default(false)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Cocina
4
4
  module Models
5
- # Use for the File (e.g. "transcription" for OCR).
5
+ # Use for the File (e.g. 'transcription' for OCR).
6
6
  FileUse = Types::String
7
7
  end
8
8
  end
@@ -4,6 +4,6 @@ module Cocina
4
4
  module Models
5
5
  # The license governing reuse of the DRO. Should be an IRI for known licenses (i.e.
6
6
  # CC, RightsStatement.org URI, etc.).
7
- License = Types::String.enum('https://www.gnu.org/licenses/agpl.txt', 'https://www.apache.org/licenses/LICENSE-2.0', 'https://opensource.org/licenses/BSD-2-Clause', 'https://opensource.org/licenses/BSD-3-Clause', 'https://creativecommons.org/licenses/by/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode', 'https://creativecommons.org/licenses/by-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-sa/4.0/legalcode', 'https://creativecommons.org/publicdomain/zero/1.0/legalcode', 'https://opensource.org/licenses/cddl1', 'https://www.eclipse.org/legal/epl-2.0', 'https://www.gnu.org/licenses/gpl-3.0-standalone.html', 'https://www.isc.org/downloads/software-support-policy/isc-license/', 'https://www.gnu.org/licenses/lgpl-3.0-standalone.html', 'https://opensource.org/licenses/MIT', 'https://www.mozilla.org/MPL/2.0/', 'https://opendatacommons.org/licenses/by/1-0/', 'http://opendatacommons.org/licenses/odbl/1.0/', 'https://opendatacommons.org/licenses/odbl/1-0/', 'https://creativecommons.org/publicdomain/mark/1.0/', 'https://opendatacommons.org/licenses/pddl/1-0/', 'https://creativecommons.org/licenses/by/3.0/legalcode', 'https://creativecommons.org/licenses/by-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nd/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', 'https://cocina.sul.stanford.edu/licenses/none')
7
+ License = Types::String.enum(nil, 'https://www.gnu.org/licenses/agpl.txt', 'https://www.apache.org/licenses/LICENSE-2.0', 'https://opensource.org/licenses/BSD-2-Clause', 'https://opensource.org/licenses/BSD-3-Clause', 'https://creativecommons.org/licenses/by/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode', 'https://creativecommons.org/licenses/by-nd/4.0/legalcode', 'https://creativecommons.org/licenses/by-sa/4.0/legalcode', 'https://creativecommons.org/publicdomain/zero/1.0/legalcode', 'https://opensource.org/licenses/cddl1', 'https://www.eclipse.org/legal/epl-2.0', 'https://www.gnu.org/licenses/gpl-3.0-standalone.html', 'https://www.isc.org/downloads/software-support-policy/isc-license/', 'https://www.gnu.org/licenses/lgpl-3.0-standalone.html', 'https://opensource.org/licenses/MIT', 'https://www.mozilla.org/MPL/2.0/', 'https://opendatacommons.org/licenses/by/1-0/', 'http://opendatacommons.org/licenses/odbl/1.0/', 'https://opendatacommons.org/licenses/odbl/1-0/', 'https://creativecommons.org/publicdomain/mark/1.0/', 'https://opendatacommons.org/licenses/pddl/1-0/', 'https://creativecommons.org/licenses/by/3.0/legalcode', 'https://creativecommons.org/licenses/by-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nd/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode', 'https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode', 'https://cocina.sul.stanford.edu/licenses/none')
8
8
  end
9
9
  end
@@ -7,7 +7,7 @@ module Cocina
7
7
  attribute :view, Types::Strict::String.enum('location-based')
8
8
  # Download access level.
9
9
  attribute :download, Types::Strict::String.enum('location-based', 'none')
10
- # If access or download is "location-based", which location should have access.
10
+ # If access or download is 'location-based', which location should have access.
11
11
  attribute :location, Types::Strict::String.enum('spec', 'music', 'ars', 'art', 'hoover', 'm&m')
12
12
  attribute? :controlledDigitalLending, Types::Strict::Bool.default(false).enum(false)
13
13
  end
@@ -17,7 +17,7 @@ module Cocina
17
17
  # (like media players) expect language codes of this format, see e.g. https://videojs.com/guides/text-tracks/#srclang
18
18
  attribute? :languageTag, LanguageTag.optional
19
19
  attribute? :externalIdentifier, Types::Strict::String
20
- # Use for the File (e.g. "transcription" for OCR).
20
+ # Use for the File (e.g. 'transcription' for OCR).
21
21
  attribute? :use, FileUse.optional
22
22
  # Indicates if the text (OCR/captioning) was generated by SDR.
23
23
  attribute? :sdrGeneratedText, Types::Strict::Bool.default(false)
@@ -8,7 +8,7 @@ module Cocina
8
8
  # Download access level.
9
9
  attribute :download, Types::Strict::String.enum('stanford')
10
10
  # Not used for this access type, must be null.
11
- attribute? :location, Types::Strict::String.optional.enum('')
11
+ attribute? :location, Types::Strict::String.optional.enum(nil)
12
12
  attribute? :controlledDigitalLending, Types::Strict::Bool.default(false).enum(false)
13
13
  end
14
14
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cocina
4
+ module Models
5
+ module Validators
6
+ # Perform validation against JSON schema
7
+ class JsonSchemaValidator
8
+ def self.validate(clazz, attributes)
9
+ return unless clazz.name
10
+
11
+ method_name = clazz.name.split('::').last
12
+
13
+ attributes['cocinaVersion'] = Cocina::Models::VERSION if %w[DRO RequestDRO AdminPolicy RequestAdminPolicy Collection RequestCollection DROWithMetadata].include? method_name
14
+
15
+ errors = openapi.ref("#/components/schemas/#{method_name}").validate(attributes.as_json).to_a
16
+ return unless errors.any?
17
+
18
+ raise ValidationError, "When validating #{method_name}: " + errors.map { |e| e['error'] }.uniq.join(', ')
19
+ end
20
+
21
+ # @return [Hash] a hash representation of the openapi document
22
+ def self.document
23
+ @document ||= YAML.load_file(openapi_path)
24
+ end
25
+
26
+ # @return [JSONSchemer::OpenAPI]
27
+ def self.openapi
28
+ @openapi ||= JSONSchemer.openapi(YAML.load_file(openapi_path))
29
+ end
30
+ private_class_method :openapi
31
+
32
+ def self.openapi_path
33
+ ::File.expand_path('../../../../openapi.yml', __dir__)
34
+ end
35
+ private_class_method :openapi_path
36
+ end
37
+ end
38
+ end
39
+ end
@@ -6,7 +6,7 @@ module Cocina
6
6
  # Perform validation against all other Validators
7
7
  class Validator
8
8
  VALIDATORS = [
9
- OpenApiValidator,
9
+ JsonSchemaValidator,
10
10
  DarkValidator,
11
11
  PurlValidator,
12
12
  CatalogLinksValidator,
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Cocina
4
4
  module Models
5
- VERSION = '0.111.0'
5
+ VERSION = '0.112.0'
6
6
  end
7
7
  end
@@ -8,7 +8,7 @@ module Cocina
8
8
  # Download access level.
9
9
  attribute :download, Types::Strict::String.enum('none', 'stanford', 'world')
10
10
  # Not used for this access type, must be null.
11
- attribute? :location, Types::Strict::String.optional.enum('')
11
+ attribute? :location, Types::Strict::String.optional.enum(nil)
12
12
  attribute? :controlledDigitalLending, Types::Strict::Bool.default(false).enum(false)
13
13
  end
14
14
  end
data/lib/cocina/models.rb CHANGED
@@ -191,15 +191,5 @@ module Cocina
191
191
  METADATA_KEYS.any? { |key| dyn[key] || dyn[key.to_s] }
192
192
  end
193
193
  private_class_method :has_metadata?
194
-
195
- def self.druid_regex
196
- @druid_regex ||= begin
197
- str = Cocina::OpenApiWrapper.parse(YAML.load_file('openapi.yml'), strict_reference_validation: true)
198
- .components
199
- .schemas['Druid']
200
- .pattern
201
- Regexp.new(str)
202
- end
203
- end
204
194
  end
205
195
  end