cocina-models 0.92.0 → 0.93.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: 0fb90197036280ad978dc4e59b548fcb954d7b602799294cfdde8bd3ef2a1568
4
- data.tar.gz: fd7c2c49522772f866dc04d629296c537f88d88dd8943ce4b74bb77460be31d9
3
+ metadata.gz: 9cf74f9126fce8106b3bfd5964c11731c460546a4f457da9ba7f35f895243c7a
4
+ data.tar.gz: 58467364ec8a96eac4f6d335dce400c0086833830f5704e263bae7365741d473
5
5
  SHA512:
6
- metadata.gz: 84a09b86f9f922ba9b8c433760fe3613035d72cba102f5a93dc9e7ec07a4d7bfdef5f449375fa4792eb0b8045f3324f23360183b0f9b5aa8ea21082336681b22
7
- data.tar.gz: 93b59a61650aae4c19cab66d84a216f66f65a289444e58fc48fdbd9088d33dd083fe9c57f57971574dae13a0b21ab4453ee48f8bad14f408ee3149534eb2aa99
6
+ metadata.gz: e2106344f663362d1609f5e40daf001c43f976abbbe7ae8a43c52295b2a2e280952c7d6d01b6f6b4cbdf124a07c26372bdfc17f9a903cce666edc39ba3b3db35
7
+ data.tar.gz: 5675d10901a099d8869baed51c4bdb82608305053d0e830130c28577644daddf73a650410cb20425e4e27ff4dfc60188f0e2cb0b77954c49bd3f00980ee56cf1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cocina-models (0.92.0)
4
+ cocina-models (0.93.0)
5
5
  activesupport
6
6
  deprecation
7
7
  dry-struct (~> 1.0)
@@ -97,7 +97,7 @@ GEM
97
97
  racc
98
98
  patience_diff (1.2.0)
99
99
  optimist (~> 3.0)
100
- racc (1.7.1)
100
+ racc (1.7.3)
101
101
  rack (3.0.8)
102
102
  rainbow (3.1.1)
103
103
  rake (13.1.0)
@@ -23,9 +23,9 @@ module Cocina
23
23
  # MIME Type of the File.
24
24
  attribute? :hasMimeType, Types::Strict::String
25
25
  # BCP 47 language tag: https://www.rfc-editor.org/rfc/rfc4646.txt -- other applications (like media players) expect language codes of this format, see e.g. https://videojs.com/guides/text-tracks/#srclang
26
- attribute? :languageTag, Types::Strict::String
26
+ attribute? :languageTag, LanguageTag.optional
27
27
  # Use for the File.
28
- attribute? :use, Types::Strict::String
28
+ attribute? :use, FileUse.optional
29
29
  attribute :hasMessageDigests, Types::Strict::Array.of(MessageDigest).default([].freeze)
30
30
  attribute(:access, FileAccess.default { FileAccess.new })
31
31
  attribute(:administrative, FileAdministrative.default { FileAdministrative.new })
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cocina
4
+ module Models
5
+ FileUse = Types::String
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cocina
4
+ module Models
5
+ LanguageTag = Types::String
6
+ end
7
+ end
@@ -13,9 +13,11 @@ module Cocina
13
13
  attribute? :size, Types::Strict::Integer
14
14
  attribute :version, Types::Strict::Integer
15
15
  attribute? :hasMimeType, Types::Strict::String
16
- attribute? :languageTag, Types::Strict::String
16
+ # BCP 47 language tag: https://www.rfc-editor.org/rfc/rfc4646.txt -- other applications (like media players) expect language codes of this format, see e.g. https://videojs.com/guides/text-tracks/#srclang
17
+ attribute? :languageTag, LanguageTag.optional
17
18
  attribute? :externalIdentifier, Types::Strict::String
18
- attribute? :use, Types::Strict::String
19
+ # Use for the File.
20
+ attribute? :use, FileUse.optional
19
21
  attribute :hasMessageDigests, Types::Strict::Array.of(MessageDigest).default([].freeze)
20
22
  attribute(:access, FileAccess.default { FileAccess.new })
21
23
  attribute(:administrative, FileAdministrative.default { FileAdministrative.new })
@@ -39,12 +39,7 @@ module Cocina
39
39
  end
40
40
 
41
41
  def invalid_files
42
- @invalid_files ||=
43
- [].tap do |invalid_files|
44
- files.each do |file|
45
- invalid_files << file if invalid?(file)
46
- end
47
- end
42
+ @invalid_files ||= files.select { |file| invalid?(file) }
48
43
  end
49
44
 
50
45
  def invalid_filenames
@@ -12,7 +12,8 @@ module Cocina
12
12
  def initialize(clazz, attributes)
13
13
  @clazz = clazz
14
14
  @attributes = attributes
15
- @error_paths = []
15
+ @error_paths_multiple = []
16
+ @error_paths_blank = []
16
17
  end
17
18
 
18
19
  def validate
@@ -20,21 +21,21 @@ module Cocina
20
21
 
21
22
  validate_obj(attributes, [])
22
23
 
23
- return if error_paths.empty?
24
-
25
- raise ValidationError, "Multiple value, groupedValue, structuredValue, and parallelValue in description: #{error_paths.join(', ')}"
24
+ raise ValidationError, "Multiple value, groupedValue, structuredValue, and parallelValue in description: #{error_paths_multiple.join(', ')}" unless error_paths_multiple.empty?
25
+ raise ValidationError, "Blank value in description: #{error_paths_blank.join(', ')}" unless error_paths_blank.empty?
26
26
  end
27
27
 
28
28
  private
29
29
 
30
- attr_reader :clazz, :attributes, :error_paths
30
+ attr_reader :clazz, :attributes, :error_paths_blank, :error_paths_multiple
31
31
 
32
32
  def meets_preconditions?
33
33
  [Cocina::Models::Description, Cocina::Models::RequestDescription].include?(clazz)
34
34
  end
35
35
 
36
36
  def validate_hash(hash, path)
37
- validate_values(hash, path)
37
+ validate_values_for_blanks(hash, path)
38
+ validate_values_for_multiples(hash, path)
38
39
  hash.each do |key, obj|
39
40
  validate_obj(obj, path + [key])
40
41
  end
@@ -51,10 +52,16 @@ module Cocina
51
52
  validate_array(obj, path) if obj.is_a?(Array)
52
53
  end
53
54
 
54
- def validate_values(hash, path)
55
+ def validate_values_for_blanks(hash, path)
56
+ return unless hash[:value] && hash[:value].is_a?(String) && /\A\s+\z/.match?(hash[:value]) # rubocop:disable Style/SafeNavigation
57
+
58
+ error_paths_blank << path_to_s(path)
59
+ end
60
+
61
+ def validate_values_for_multiples(hash, path)
55
62
  return unless hash.count { |key, value| %i[value groupedValue structuredValue parallelValue].include?(key) && value.present? } > 1
56
63
 
57
- error_paths << path_to_s(path)
64
+ error_paths_multiple << path_to_s(path)
58
65
  end
59
66
 
60
67
  def path_to_s(path)
@@ -17,10 +17,10 @@ module Cocina
17
17
  def validate
18
18
  return unless meets_preconditions?
19
19
 
20
- return if valid_language_tag?
20
+ return if invalid_files.empty?
21
21
 
22
- raise ValidationError, 'The provided language tag is not valid according to RFC 4646: ' \
23
- "#{attributes[:languageTag]}"
22
+ raise ValidationError, 'Some files have invalid language tags according to RFC 4646: ' \
23
+ "#{invalid_filenames_with_language_tags.join(', ')}"
24
24
  end
25
25
 
26
26
  private
@@ -28,19 +28,45 @@ module Cocina
28
28
  attr_reader :clazz, :attributes
29
29
 
30
30
  def meets_preconditions?
31
- file? && attributes[:languageTag].present?
31
+ dro?
32
32
  end
33
33
 
34
- def file?
35
- (clazz::TYPES & File::TYPES).any?
34
+ def dro?
35
+ (clazz::TYPES & DRO::TYPES).any?
36
36
  rescue NameError
37
37
  false
38
38
  end
39
39
 
40
- def valid_language_tag?
41
- parsed_tag = I18n::Locale::Tag::Rfc4646.tag(attributes[:languageTag])
40
+ def valid_language_tag?(file)
41
+ # I18n::Locale::Tag::Rfc4646.tag will return an instance of I18n::Locale::Tag::Rfc4646 (with fields like language, script,
42
+ # region) for strings that can be parsed according to RFC 4646, and nil for strings that do not conform to the spec.
43
+ I18n::Locale::Tag::Rfc4646.tag(file[:languageTag]).present?
44
+ end
45
+
46
+ def invalid_files
47
+ @invalid_files ||= language_tag_files.reject { |file| valid_language_tag?(file) }
48
+ end
49
+
50
+ def invalid_filenames_with_language_tags
51
+ invalid_files.map { |invalid_file| "#{invalid_file[:filename] || invalid_file[:label]} (#{invalid_file[:languageTag]})" }
52
+ end
53
+
54
+ def language_tag_files
55
+ files.select { |file| file[:languageTag].present? }
56
+ end
57
+
58
+ def files
59
+ [].tap do |files|
60
+ next if attributes.dig(:structural, :contains).nil?
61
+
62
+ attributes[:structural][:contains].each do |fileset|
63
+ next if fileset.dig(:structural, :contains).nil?
42
64
 
43
- parsed_tag.present? && parsed_tag.is_a?(I18n::Locale::Tag::Rfc4646)
65
+ fileset[:structural][:contains].each do |file|
66
+ files << file
67
+ end
68
+ end
69
+ end
44
70
  end
45
71
  end
46
72
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Cocina
4
4
  module Models
5
- VERSION = '0.92.0'
5
+ VERSION = '0.93.0'
6
6
  end
7
7
  end
data/openapi.yml CHANGED
@@ -1045,11 +1045,9 @@ components:
1045
1045
  description: MIME Type of the File.
1046
1046
  type: string
1047
1047
  languageTag:
1048
- description: "BCP 47 language tag: https://www.rfc-editor.org/rfc/rfc4646.txt -- other applications (like media players) expect language codes of this format, see e.g. https://videojs.com/guides/text-tracks/#srclang"
1049
- type: string
1048
+ $ref: '#/components/schemas/LanguageTag'
1050
1049
  use:
1051
- description: Use for the File.
1052
- type: string
1050
+ $ref: '#/components/schemas/FileUse'
1053
1051
  hasMessageDigests:
1054
1052
  type: array
1055
1053
  items:
@@ -1144,6 +1142,10 @@ components:
1144
1142
  type: array
1145
1143
  items:
1146
1144
  $ref: '#/components/schemas/File'
1145
+ FileUse:
1146
+ description: Use for the File.
1147
+ type: string
1148
+ nullable: true
1147
1149
  FolioCatalogLink:
1148
1150
  description: A linkage between an object and a Folio catalog record
1149
1151
  type: object
@@ -1272,6 +1274,10 @@ components:
1272
1274
  valueLanguage:
1273
1275
  # description: present for mapping to additional schemas in the future and for consistency but not otherwise used
1274
1276
  $ref: "#/components/schemas/DescriptiveValueLanguage"
1277
+ LanguageTag:
1278
+ description: "BCP 47 language tag: https://www.rfc-editor.org/rfc/rfc4646.txt -- other applications (like media players) expect language codes of this format, see e.g. https://videojs.com/guides/text-tracks/#srclang"
1279
+ type: string
1280
+ nullable: true
1275
1281
  License:
1276
1282
  description: The license governing reuse of the DRO. Should be an IRI for known licenses (i.e. CC, RightsStatement.org URI, etc.).
1277
1283
  type: string
@@ -1779,11 +1785,11 @@ components:
1779
1785
  hasMimeType:
1780
1786
  type: string
1781
1787
  languageTag:
1782
- type: string
1788
+ $ref: '#/components/schemas/LanguageTag'
1783
1789
  externalIdentifier:
1784
1790
  type: string
1785
1791
  use:
1786
- type: string
1792
+ $ref: '#/components/schemas/FileUse'
1787
1793
  hasMessageDigests:
1788
1794
  type: array
1789
1795
  items:
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.92.0
4
+ version: 0.93.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: 2023-11-02 00:00:00.000000000 Z
11
+ date: 2023-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -429,11 +429,13 @@ files:
429
429
  - lib/cocina/models/file_set.rb
430
430
  - lib/cocina/models/file_set_structural.rb
431
431
  - lib/cocina/models/file_set_type.rb
432
+ - lib/cocina/models/file_use.rb
432
433
  - lib/cocina/models/folio_catalog_link.rb
433
434
  - lib/cocina/models/geographic.rb
434
435
  - lib/cocina/models/identification.rb
435
436
  - lib/cocina/models/lane_medical_barcode.rb
436
437
  - lib/cocina/models/language.rb
438
+ - lib/cocina/models/language_tag.rb
437
439
  - lib/cocina/models/license.rb
438
440
  - lib/cocina/models/location_based_access.rb
439
441
  - lib/cocina/models/location_based_download_access.rb