cocina-models 0.76.0 → 0.79.0

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: ff6e03954275e59dcc8fbf693f3aeef4b90742767771865508e81541f53f1cbf
4
- data.tar.gz: dacc3005506e32d5cca5b599477d1c450844272715e9500f8242bc19bf69972b
3
+ metadata.gz: 193f5886756d2fd6432e90ab5323f6ed5a11c699cb97f49d61394bc5fafd5f53
4
+ data.tar.gz: ecb1493a56b7b20f9733084c8a9a115e3a3c6639a8072bc371f53a51d69d0a2c
5
5
  SHA512:
6
- metadata.gz: bf5f815fb3c09ae4cba6d0e1cf16aafd7502cb731f523004c643806579475d6ac11882845a5d0178732f8d3c9edad56901bf8e05df7d5681a0afdc0032f14058
7
- data.tar.gz: 5b88e55c0e25e6dad32a4326a2063bf5a72fedc8146e90a7ead461a1fad0bb1f0f293d360f16884daf5582fa16f4e95fdb61307487e21b7a28b2250c69c1d9ad
6
+ metadata.gz: 8cc210b897872f3b90fd59e12f381f049b1389b0cf3d798a0375eea57282cf456c6591a8d474c5c612253123bca01ed9a9b931129c89153b8a8dae3ad713254b
7
+ data.tar.gz: f1a23590223b7760780e3b547b053355a1ba600fdc468ce563aef20a4c38cd3571345bde621f3f9f23248d27c29f0f3b5a829dd0c7d5c08d95d27efec472453d
data/README.md CHANGED
@@ -55,8 +55,37 @@ If there is a possibility that a model or validation change will conflict with s
55
55
 
56
56
  1. Create a cocina-models branch containing the proposed change and push to Github.
57
57
  2. On sdr-deploy, check out `main`, update the `Gemfile` so that cocina-models references the branch, and `bundle install`.
58
- 3. Run `bin/validate-cocina`.
59
- 4. Check `validate-cocina.csv` for validation errors.
58
+ 3. Select the appropriate database.
59
+ For QA:
60
+ ```
61
+ export DATABASE_NAME="dor_services"
62
+ export DATABASE_USERNAME=$DOR_SERVICES_DB_USER
63
+ export DATABASE_HOSTNAME=$DOR_SERVICES_DB_QA_HOST
64
+ export DATABASE_PASSWORD=$DOR_SERVICES_DB_QA_PWD
65
+ ```
66
+
67
+ For stage:
68
+ ```
69
+ export DATABASE_NAME="dor_services"
70
+ export DATABASE_USERNAME=$DOR_SERVICES_DB_USER
71
+ export DATABASE_HOSTNAME=$DOR_SERVICES_DB_STAGE_HOST
72
+ export DATABASE_PASSWORD=$DOR_SERVICES_DB_STAGE_PWD
73
+ ```
74
+
75
+ For production:
76
+ ```
77
+ export DATABASE_NAME="dor_services"
78
+ export DATABASE_USERNAME=$DOR_SERVICES_DB_USER
79
+ export DATABASE_HOSTNAME=$DOR_SERVICES_DB_PROD_HOST
80
+ export DATABASE_PASSWORD=$DOR_SERVICES_DB_PROD_PWD
81
+ ```
82
+
83
+ 4. Run `bin/validate-cocina`:
84
+ ```
85
+ export RUBYOPT='-W:no-deprecated -W:no-experimental'
86
+ RAILS_ENV=production bin/validate-cocina -p 8
87
+ ```
88
+ 5. Check `validate-cocina.csv` for validation errors.
60
89
 
61
90
  ## Releasing
62
91
 
@@ -132,6 +132,8 @@ event:
132
132
  description: The discussion of an academic or intellectual work for an audience, such as a seminar.
133
133
  - value: production
134
134
  description: The physical assembly of a resource not considered published, such as page proofs for a book.
135
+ - value: provenance
136
+ description: The resource's origins and history.
135
137
  - value: publication
136
138
  description: The publishing or issuing of a resource.
137
139
  - value: recording
@@ -389,6 +391,8 @@ identifier:
389
391
  - value: record id
390
392
  - value: Senate Number
391
393
  - value: Series
394
+ - value: SICI
395
+ code: sici
392
396
  - value: SIRSI
393
397
  - value: Source ID
394
398
  - value: sourceID
@@ -141,6 +141,8 @@ _Path: event.type_
141
141
  * The discussion of an academic or intellectual work for an audience, such as a seminar.
142
142
  * production
143
143
  * The physical assembly of a resource not considered published, such as page proofs for a book.
144
+ * provenance
145
+ * The resource's origins and history.
144
146
  * publication
145
147
  * The publishing or issuing of a resource.
146
148
  * recording
@@ -15,7 +15,6 @@ module Cocina
15
15
  # @param [TitleBuilder] title_builder - defaults to Title class
16
16
  # @param [Cocina::Models::Mapping::ErrorNotifier] notifier
17
17
  # @return [Hash] a hash that can be mapped to a cocina descriptive model
18
- # @raises [Cocina::Mapper::InvalidDescMetadata] if some assumption about descMetadata is violated
19
18
  def self.props(mods:, druid:, label:, title_builder: Title, notifier: nil)
20
19
  new(title_builder: title_builder, mods: mods, druid: druid, label: label, notifier: notifier).props
21
20
  end
@@ -5,8 +5,7 @@ module Cocina
5
5
  module Mapping
6
6
  # Utility methods for generating purl links
7
7
  class Purl
8
- class_attribute :base_url
9
- self.base_url = 'https://purl.stanford.edu'
8
+ class_attribute :base_url, default: 'https://purl.stanford.edu'
10
9
 
11
10
  def self.for(druid:)
12
11
  return nil if druid.nil?
@@ -199,8 +199,6 @@ module Cocina
199
199
  xml.affiliation note.value
200
200
  when 'description'
201
201
  xml.description note.value
202
- when 'citation status'
203
- xml.description UNCITED_DESCRIPTION if note.value == 'false'
204
202
  end
205
203
  end
206
204
  end
@@ -11,7 +11,7 @@ module Cocina
11
11
 
12
12
  def initialize(clazz, attributes)
13
13
  @clazz = clazz
14
- @attributes = attributes.deep_symbolize_keys
14
+ @attributes = attributes
15
15
  @error_paths = []
16
16
  end
17
17
 
@@ -29,9 +29,7 @@ module Cocina
29
29
  attr_reader :clazz, :attributes, :error_paths
30
30
 
31
31
  def meets_preconditions?
32
- resources.any? do |resource|
33
- titles_with_associated_name_note_for(resource).present?
34
- end
32
+ [Cocina::Models::Description, Cocina::Models::RequestDescription].include?(clazz)
35
33
  end
36
34
 
37
35
  def valid?(resource)
@@ -11,7 +11,7 @@ module Cocina
11
11
 
12
12
  def initialize(clazz, attributes)
13
13
  @clazz = clazz
14
- @attributes = attributes.deep_symbolize_keys
14
+ @attributes = attributes
15
15
  @error_paths = []
16
16
  end
17
17
 
@@ -30,8 +30,7 @@ module Cocina
30
30
  attr_reader :clazz, :attributes, :error_paths
31
31
 
32
32
  def meets_preconditions?
33
- attributes.key?(:description) || [Cocina::Models::Description,
34
- Cocina::Models::RequestDescription].include?(clazz)
33
+ [Cocina::Models::Description, Cocina::Models::RequestDescription].include?(clazz)
35
34
  end
36
35
 
37
36
  def validate_hash(hash, path)
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cocina
4
+ module Models
5
+ module Validators
6
+ # Validates that there is only one of value, groupedValue, structuredValue, or parallelValue.
7
+ class DescriptionValuesValidator
8
+ def self.validate(clazz, attributes)
9
+ new(clazz, attributes).validate
10
+ end
11
+
12
+ def initialize(clazz, attributes)
13
+ @clazz = clazz
14
+ @attributes = attributes
15
+ @error_paths = []
16
+ end
17
+
18
+ def validate
19
+ return unless meets_preconditions?
20
+
21
+ validate_obj(attributes, [])
22
+
23
+ return if error_paths.empty?
24
+
25
+ raise ValidationError, "Multiple value, groupedValue, structuredValue, and parallelValue in description: #{error_paths.join(', ')}"
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :clazz, :attributes, :error_paths
31
+
32
+ def meets_preconditions?
33
+ [Cocina::Models::Description, Cocina::Models::RequestDescription].include?(clazz)
34
+ end
35
+
36
+ def validate_hash(hash, path)
37
+ validate_values(hash, path)
38
+ hash.each do |key, obj|
39
+ validate_obj(obj, path + [key])
40
+ end
41
+ end
42
+
43
+ def validate_array(array, path)
44
+ array.each_with_index do |obj, index|
45
+ validate_obj(obj, path + [index])
46
+ end
47
+ end
48
+
49
+ def validate_obj(obj, path)
50
+ validate_hash(obj, path) if obj.is_a?(Hash)
51
+ validate_array(obj, path) if obj.is_a?(Array)
52
+ end
53
+
54
+ def validate_values(hash, path)
55
+ return unless hash.count { |key, value| %i[value groupedValue structuredValue parallelValue].include?(key) && value.present? } > 1
56
+
57
+ error_paths << path_to_s(path)
58
+ end
59
+
60
+ def path_to_s(path)
61
+ # This matches the format used by descriptive spreadsheets
62
+ path_str = ''
63
+ path.each_with_index do |part, index|
64
+ if part.is_a?(Integer)
65
+ path_str += (part + 1).to_s
66
+ else
67
+ path_str += '.' if index.positive?
68
+ path_str += part.to_s
69
+ end
70
+ end
71
+ path_str
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -11,7 +11,8 @@ module Cocina
11
11
  PurlValidator,
12
12
  CatalogLinksValidator,
13
13
  AssociatedNameValidator,
14
- DescriptionTypesValidator
14
+ DescriptionTypesValidator,
15
+ DescriptionValuesValidator
15
16
  ].freeze
16
17
 
17
18
  def self.validate(clazz, attributes)
@@ -25,8 +26,7 @@ module Cocina
25
26
  # In the meantime, copying code.
26
27
  attributes_hash = deep_transform_values(attributes.to_h) do |value|
27
28
  value.class.name.starts_with?('Cocina::Models') ? value.to_h : value
28
- end.with_indifferent_access
29
-
29
+ end.deep_symbolize_keys.with_indifferent_access
30
30
  VALIDATORS.each { |validator| validator.validate(clazz, attributes_hash) }
31
31
  end
32
32
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Cocina
4
4
  module Models
5
- VERSION = '0.76.0'
5
+ VERSION = '0.79.0'
6
6
  end
7
7
  end
data/lib/cocina/models.rb CHANGED
@@ -119,7 +119,7 @@ module Cocina
119
119
  # @param [DROWithMetadata,CollectionWithMetadata,AdminPolicyWithMetadata] cocina_object
120
120
  # @return [DRO,Collection,AdminPolicy]
121
121
  def self.without_metadata(cocina_object)
122
- build(cocina_object.to_h.except(:created, :modified, :lock))
122
+ build(cocina_object.to_h.except(:created, :modified, :lock), validate: false)
123
123
  end
124
124
 
125
125
  # Adds metadata to a DRO, Collection, AdminPolicy
@@ -144,7 +144,7 @@ module Cocina
144
144
  else
145
145
  AdminPolicyWithMetadata
146
146
  end
147
- clazz.new(props)
147
+ clazz.new(props, false, false)
148
148
  end
149
149
 
150
150
  def self.type_for(dyn)
@@ -12,8 +12,20 @@ module Cocina
12
12
  end
13
13
  end
14
14
 
15
+ SUPPORTED_TYPES = %i[
16
+ admin_policy
17
+ admin_policy_with_metadata
18
+ collection
19
+ collection_with_metadata
20
+ dro
21
+ dro_with_metadata
22
+ request_admin_policy
23
+ request_collection
24
+ request_dro
25
+ ].freeze
26
+
15
27
  def self.supported_type?(type)
16
- %i[dro collection admin_policy dro_with_metadata collection_with_metadata admin_policy_with_metadata].include?(type)
28
+ SUPPORTED_TYPES.include?(type)
17
29
  end
18
30
 
19
31
  WITH_METADATA_SUFFIX = '_with_metadata'
@@ -33,37 +45,60 @@ module Cocina
33
45
  type: Cocina::Models::ObjectType.object,
34
46
  id: 'druid:bc234fg5678',
35
47
  version: 1,
36
- label: 'test object',
37
- title: 'test object',
48
+ label: 'factory DRO label',
49
+ title: 'factory DRO title',
38
50
  source_id: 'sul:1234',
39
51
  admin_policy_id: 'druid:hv992ry2431'
40
52
  }.freeze
41
53
 
42
- COLLECTION_DEFAULTS = DRO_DEFAULTS.except(:source_id).merge(type: Cocina::Models::ObjectType.collection)
54
+ REQUEST_DRO_DEFAULTS = DRO_DEFAULTS.except(:id)
55
+
56
+ COLLECTION_DEFAULTS = {
57
+ type: Cocina::Models::ObjectType.collection,
58
+ id: 'druid:bb222ff5555',
59
+ version: 1,
60
+ label: 'factory collection label',
61
+ title: 'factory collection title',
62
+ admin_policy_id: 'druid:hv992ry2431'
63
+ }.freeze
64
+
65
+ REQUEST_COLLECTION_DEFAULTS = COLLECTION_DEFAULTS.except(:id)
43
66
 
44
67
  ADMIN_POLICY_DEFAULTS = {
45
68
  type: Cocina::Models::ObjectType.admin_policy,
46
- id: 'druid:bc234fg5678',
69
+ id: 'druid:cb432gf8765',
47
70
  version: 1,
48
- label: 'test admin policy',
49
- title: 'test admin policy',
71
+ label: 'factory APO label',
72
+ title: 'factory APO title',
50
73
  admin_policy_id: 'druid:hv992ry2431',
51
74
  agreement_id: 'druid:hp308wm0436'
52
75
  }.freeze
53
76
 
77
+ REQUEST_ADMIN_POLICY_DEFAULTS = ADMIN_POLICY_DEFAULTS.except(:id)
78
+
79
+ def self.build_dro_properties(id:, **kwargs)
80
+ build_request_dro_properties(**kwargs)
81
+ .merge(externalIdentifier: id)
82
+ .tap do |props|
83
+ props[:description][:purl] = "https://purl.stanford.edu/#{id.delete_prefix('druid:')}"
84
+ end
85
+ end
86
+
87
+ def self.build_dro(attributes)
88
+ Cocina::Models.build(build_dro_properties(**DRO_DEFAULTS.merge(attributes)))
89
+ end
90
+
54
91
  # rubocop:disable Metrics/ParameterLists
55
- def self.build_dro_properties(type:, id:, version:, label:, title:, source_id:, admin_policy_id:,
56
- barcode: nil, catkeys: [], collection_ids: [])
92
+ def self.build_request_dro_properties(type:, version:, label:, title:, source_id:, admin_policy_id:,
93
+ barcode: nil, catkeys: [], collection_ids: [])
57
94
  {
58
95
  type: type,
59
- externalIdentifier: id,
60
96
  version: version,
61
97
  label: label,
62
98
  access: {},
63
99
  administrative: { hasAdminPolicy: admin_policy_id },
64
100
  description: {
65
- title: [{ value: title }],
66
- purl: "https://purl.stanford.edu/#{id.delete_prefix('druid:')}"
101
+ title: [{ value: title }]
67
102
  },
68
103
  identification: {
69
104
  sourceId: source_id
@@ -82,22 +117,28 @@ module Cocina
82
117
  end
83
118
  # rubocop:enable Metrics/ParameterLists
84
119
 
85
- def self.build_dro(attributes)
86
- Cocina::Models.build(build_dro_properties(**DRO_DEFAULTS.merge(attributes)))
120
+ def self.build_request_dro(attributes)
121
+ Cocina::Models.build_request(build_request_dro_properties(**REQUEST_DRO_DEFAULTS.merge(attributes)))
122
+ end
123
+
124
+ def self.build_collection_properties(id:, **kwargs)
125
+ build_request_collection_properties(**kwargs)
126
+ .merge(externalIdentifier: id)
127
+ .tap do |props|
128
+ props[:description][:purl] = "https://purl.stanford.edu/#{id.delete_prefix('druid:')}"
129
+ end
87
130
  end
88
131
 
89
132
  # rubocop:disable Metrics/ParameterLists
90
- def self.build_collection_properties(type:, id:, version:, label:, title:, admin_policy_id:, source_id: nil, catkeys: [])
133
+ def self.build_request_collection_properties(type:, version:, label:, title:, admin_policy_id:, source_id: nil, catkeys: [])
91
134
  {
92
135
  type: type,
93
- externalIdentifier: id,
94
136
  version: version,
95
137
  label: label,
96
138
  access: {},
97
139
  administrative: { hasAdminPolicy: admin_policy_id },
98
140
  description: {
99
- title: [{ value: title }],
100
- purl: "https://purl.stanford.edu/#{id.delete_prefix('druid:')}"
141
+ title: [{ value: title }]
101
142
  },
102
143
  identification: {}
103
144
  }.tap do |props|
@@ -115,19 +156,34 @@ module Cocina
115
156
  Cocina::Models.build(build_collection_properties(**COLLECTION_DEFAULTS.merge(attributes)))
116
157
  end
117
158
 
159
+ def self.build_request_collection(attributes)
160
+ Cocina::Models.build_request(build_request_collection_properties(**REQUEST_COLLECTION_DEFAULTS.merge(attributes)))
161
+ end
162
+
118
163
  def self.build_admin_policy(attributes)
119
164
  Cocina::Models.build(build_admin_policy_properties(**ADMIN_POLICY_DEFAULTS.merge(attributes)))
120
165
  end
121
166
 
167
+ def self.build_request_admin_policy(attributes)
168
+ Cocina::Models.build_request(build_request_admin_policy_properties(**REQUEST_ADMIN_POLICY_DEFAULTS.merge(attributes)))
169
+ end
170
+
171
+ def self.build_admin_policy_properties(id:, **kwargs)
172
+ build_request_admin_policy_properties(**kwargs)
173
+ .merge(externalIdentifier: id)
174
+ .tap do |props|
175
+ props[:description][:purl] = "https://purl.stanford.edu/#{id.delete_prefix('druid:')}"
176
+ end
177
+ end
178
+
122
179
  # rubocop:disable Metrics/ParameterLists
123
- def self.build_admin_policy_properties(type:, id:, version:, label:, title:,
124
- admin_policy_id:, agreement_id:,
125
- use_statement: nil, copyright: nil, license: nil,
126
- registration_workflow: nil, collections_for_registration: nil,
127
- without_description: false)
180
+ def self.build_request_admin_policy_properties(type:, version:, label:, title:,
181
+ admin_policy_id:, agreement_id:,
182
+ use_statement: nil, copyright: nil, license: nil,
183
+ registration_workflow: nil, collections_for_registration: nil,
184
+ without_description: false)
128
185
  {
129
186
  type: type,
130
- externalIdentifier: id,
131
187
  version: version,
132
188
  label: label,
133
189
  administrative: {
@@ -139,8 +195,7 @@ module Cocina
139
195
  }
140
196
  },
141
197
  description: {
142
- title: [{ value: title }],
143
- purl: "https://purl.stanford.edu/#{id.delete_prefix('druid:')}"
198
+ title: [{ value: title }]
144
199
  }
145
200
  }.tap do |props|
146
201
  props[:administrative][:accessTemplate][:useAndReproductionStatement] = use_statement if use_statement
data/openapi.yml CHANGED
@@ -691,7 +691,7 @@ components:
691
691
  items:
692
692
  $ref: "#/components/schemas/DescriptiveValue"
693
693
  DescriptiveBasicValue:
694
- description: Basic value model for descriptive elements.
694
+ description: Basic value model for descriptive elements. Can only have one of value, parallelValue, groupedValue, or structuredValue.
695
695
  type: object
696
696
  # additionalProperties breaks the validator for allOf, unclear as to why.
697
697
  # additionalProperties: false
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.76.0
4
+ version: 0.79.0
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-04-28 00:00:00.000000000 Z
11
+ date: 2022-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -306,20 +306,6 @@ files:
306
306
  - docs/cocina-base.jsonld
307
307
  - docs/description_types.md
308
308
  - docs/index.html
309
- - docs/maps/Agent.json
310
- - docs/maps/Collection.json
311
- - docs/maps/DRO.json
312
- - docs/maps/Description.json
313
- - docs/maps/File.json
314
- - docs/maps/Fileset.json
315
- - docs/maps/README.md
316
- - docs/maps/ReleaseTag.json
317
- - docs/maps/Sequence.json
318
- - docs/maps/Title.json
319
- - docs/sampleETD/foxml-export.xml
320
- - docs/sampleETD/foxml.xml
321
- - docs/sampleETD/xn109qc9773_bibframe.ttl
322
- - docs/sampleETD/xn109qc9773_taco.json
323
309
  - exe/generator
324
310
  - lib/cocina/generator.rb
325
311
  - lib/cocina/generator/datatype.rb
@@ -476,6 +462,7 @@ files:
476
462
  - lib/cocina/models/validators/catalog_links_validator.rb
477
463
  - lib/cocina/models/validators/dark_validator.rb
478
464
  - lib/cocina/models/validators/description_types_validator.rb
465
+ - lib/cocina/models/validators/description_values_validator.rb
479
466
  - lib/cocina/models/validators/open_api_validator.rb
480
467
  - lib/cocina/models/validators/purl_validator.rb
481
468
  - lib/cocina/models/validators/validator.rb
data/docs/maps/Agent.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-06/schema#",
3
- "id": "http://cocina.sul.stanford.edu/schemas/Agent",
4
- "title": "Agent",
5
- "description": "An Agent - Person, Group, Organization, or other Acting body.",
6
- "type": "object",
7
- "required": ["name"],
8
- "properties": {
9
- "name": {
10
- "description": "Primary label or name for an Agent.",
11
- "type": "string"
12
- },
13
- "sunetID": {
14
- "description": "Stanford University NetID for the Agent.",
15
- "type": "string"
16
- }
17
- }
18
- }