cocina-models 0.80.0 → 0.81.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: 5c78843bdc4b3ba3ec0ea9e2e8fa569fe7979de0e5d1a52fc4923103ed20de36
4
- data.tar.gz: b3e317a0154e15973e9a0e57aab07d0d91702a97a31889963d4df2c26339a6d4
3
+ metadata.gz: 0d8392fadece0bb4ec12ed93e958c99abf04e29ad0a78c14ee8651ec8ecd1e37
4
+ data.tar.gz: db4a5de344bb53d98b2b71f725e8b1d1b9e0d5e0b28416989ad55f19df826376
5
5
  SHA512:
6
- metadata.gz: 2fa6986b659b6474ed9ac476237c6da8ff75487bb5c7ab61b33a0226af95c44b22f14210524f258bd75bf826ea141dcc3bb88ce31e2a85b6f4590ec1ea353eec
7
- data.tar.gz: e41c8c60d4eafe62b0f4025213f73aa7629284a0e5f73e93d7b356204d075635a3ea7da3af1aaf9557de487e1eee5236c3eec23a92a04d17fc71ecec14e50c48
6
+ metadata.gz: 4880e4eb86935116e0bec017926aeab5e5aa12d8792ee5066d0aeef5f514e6f13f63c8bc68c03035fdff2748f95aa7215f236384e109a8e532bd76e9677ae53c
7
+ data.tar.gz: 22154804ee4b103bdbd3aaaee449327bb4a6c9bc1dce9431a5311ed06c5e76039ccb420634d275f56d644a60ffa529bd9cb822f9c549be057f4972d791a34bf7
@@ -92,7 +92,6 @@ module Cocina
92
92
  # ignoring groupedValue
93
93
  slices.flatten
94
94
  end
95
- # private_class_method :value_slices
96
95
 
97
96
  # for a given Hash (from a Cocina DescriptiveValue or Title or Name or ...)
98
97
  # result will be either
@@ -36,7 +36,7 @@ module Cocina
36
36
 
37
37
  def build_parallel
38
38
  names = {
39
- parallelValue: name_elements.map { |name_node| build_parallel_name(name_node) },
39
+ parallelValue: build_parallel_values,
40
40
  type: type_for(name_elements.first['type']),
41
41
  status: name_elements.filter_map { |name_element| name_element['usage'] }.first
42
42
  }.compact
@@ -52,7 +52,7 @@ module Cocina
52
52
  }.compact.merge(common_lang_script(name_node))
53
53
 
54
54
  name_attrs = name_attrs.merge(common_name(name_node, name_attrs[:name], is_parallel: true))
55
- name_parts = build_name_parts(name_node)
55
+ name_parts = build_name_parts(name_node, parallel: true)
56
56
  notifier.warn('Missing name/namePart element') if name_parts.all?(&:empty?)
57
57
  name_parts.each { |name_part| name_attrs = name_part.merge(name_attrs) }
58
58
  name_attrs.compact
@@ -106,7 +106,17 @@ module Cocina
106
106
  end.compact
107
107
  end
108
108
 
109
- def build_name_parts(name_node)
109
+ def build_parallel_values
110
+ parallel_values = []
111
+ name_elements.each do |name_node|
112
+ parallel_values << build_parallel_name(name_node)
113
+ display_val = display_value(name_node)
114
+ parallel_values << display_val if display_val
115
+ end
116
+ parallel_values.compact
117
+ end
118
+
119
+ def build_name_parts(name_node, parallel: false)
110
120
  name_part_nodes = name_node.xpath('mods:namePart', mods: Description::DESC_METADATA_NS)
111
121
  alternative_name_nodes = name_node.xpath('mods:alternativeName', mods: Description::DESC_METADATA_NS)
112
122
 
@@ -116,23 +126,64 @@ module Cocina
116
126
  parts << { valueAt: name_node['xlink:href'] } if name_node['xlink:href']
117
127
  parts << common_authority(name_node) if name_node['valueURI']
118
128
  when 1
119
- parts << build_name_part(name_node, name_part_nodes.first,
120
- default_type: alternative_name_nodes.present?)
121
- .merge(common_authority(name_node)).merge(common_lang_script(name_node)).presence
129
+ name = build_simple_value_name(name_node, name_part_nodes.first, alternative_name_nodes, parallel)
130
+ parts << name.merge(common_authority(name_node)).merge(common_lang_script(name_node)).presence
122
131
  else
123
- vals = name_part_nodes.filter_map do |name_part|
124
- build_name_part(name_node, name_part, default_type: name_node['type'] != 'corporate').presence
125
- end
126
- parts << { structuredValue: vals }.merge(common_authority(name_node)).merge(common_lang_script(name_node))
132
+ name = build_structured_value_name(name_node, name_part_nodes)
133
+ parts << name.merge(common_authority(name_node)).merge(common_lang_script(name_node))
127
134
  end
128
135
 
129
136
  parts = build_alternative_name(alternative_name_nodes, parts) if alternative_name_nodes.present?
130
-
131
- display_form = name_node.xpath('mods:displayForm', mods: Description::DESC_METADATA_NS).first
132
- parts << { value: display_form.text, type: 'display' } if display_form
133
137
  parts.compact
134
138
  end
135
139
 
140
+ def build_simple_value_name(name_node, name_part_node, alternative_name_nodes, parallel)
141
+ name_value_hash = build_name_part(name_node, name_part_node, default_type: alternative_name_nodes.present?)
142
+ display_form_node = name_node.xpath('mods:displayForm', mods: Description::DESC_METADATA_NS).first
143
+ if display_form_node.present? && !parallel
144
+ cocina_contrib_name =
145
+ {
146
+ parallelValue: [
147
+ name_value_hash
148
+ ]
149
+ }
150
+ add_display_parallel_value(name_node, cocina_contrib_name)
151
+ else
152
+ name_value_hash
153
+ end
154
+ end
155
+
156
+ def build_structured_value_name(name_node, name_part_nodes)
157
+ vals = name_part_nodes.filter_map { |name_part_node| build_name_part(name_node, name_part_node, default_type: name_node['type'] != 'corporate').presence }
158
+ display_form_node = name_node.xpath('mods:displayForm', mods: Description::DESC_METADATA_NS).first
159
+ if display_form_node.present?
160
+ cocina_contrib_name =
161
+ {
162
+ parallelValue: [
163
+ { structuredValue: vals }
164
+ ]
165
+ }
166
+ add_display_parallel_value(name_node, cocina_contrib_name)
167
+ else
168
+ { structuredValue: vals }
169
+ end
170
+ end
171
+
172
+ def add_display_parallel_value(name_node, cocina_contrib_name)
173
+ display_form = name_node.xpath('mods:displayForm', mods: Description::DESC_METADATA_NS)&.text
174
+ return cocina_contrib_name if display_form.blank?
175
+
176
+ display_parallel_value = display_value(name_node)
177
+ cocina_contrib_name[:parallelValue] << display_parallel_value if display_parallel_value && cocina_contrib_name[:parallelValue].present?
178
+
179
+ cocina_contrib_name
180
+ end
181
+
182
+ def display_value(name_node)
183
+ display_form = name_node.xpath('mods:displayForm', mods: Description::DESC_METADATA_NS)&.text
184
+ { value: display_form, type: 'display' } if display_form.present?
185
+ end
186
+
136
187
  def build_name_part(name_node, name_part_node, default_type: true)
137
188
  if name_part_node.content.blank? && !name_part_node['xlink:href']
138
189
  notifier.warn('name/namePart missing value')
@@ -36,25 +36,11 @@ module Cocina
36
36
  if contributor.type == 'unspecified others'
37
37
  write_etal
38
38
  elsif contributor.name.present?
39
+ # Expect contributor to have a single value for name property
39
40
  contrib_name = contributor.name.first
40
- parallel_values = contrib_name.parallelValue
41
- if parallel_values.present?
42
- altrepgroup_id = id_generator.next_altrepgroup
43
- parallel_values.each do |parallel_contrib_name|
44
- Cocina::Models::Builders::NameTitleGroupBuilder.value_slices(parallel_contrib_name)&.each do |parallel_contrib_name_slice|
45
- if name_title_vals_index[parallel_contrib_name_slice]
46
- name_title_group = name_title_vals_index[parallel_contrib_name_slice]&.values&.first
47
- write_parallel_contributor(contributor, contrib_name, parallel_contrib_name,
48
- name_title_group, altrepgroup_id)
49
- else
50
- # TODO: want a way to notify that we hit a problem - either notifier or HB error (issue #3751)
51
- # OR validate for semantic correctness upon creation/update so we can't get here.
52
- # notifier.warn("For contributor name '#{parallel_contrib_name_val}', no title matching '#{title_from_contrib}'")
53
- write_parallel_contributor(contributor, contrib_name, parallel_contrib_name, nil,
54
- altrepgroup_id)
55
- end
56
- end
57
- end
41
+ parallel_name_values = contrib_name.parallelValue
42
+ if parallel_name_values.present?
43
+ write_contributor_with_parallel_names(parallel_name_values, contrib_name)
58
44
  else
59
45
  write_contributor(contributor)
60
46
  end
@@ -105,7 +91,50 @@ module Cocina
105
91
  end
106
92
  end
107
93
 
108
- def write_parallel_contributor(contributor, name, parallel_name, name_title_group, altrepgroup_id)
94
+ def write_contributor_with_parallel_names(parallel_name_values, contrib_name)
95
+ display_type_parallel_name = display_type_parallel_name(parallel_name_values)
96
+ if parallel_name_values.size == 1
97
+ contrib_name_value_slice = Cocina::Models::Builders::NameTitleGroupBuilder.value_slices(parallel_name_values.first)
98
+ name_title_group = name_title_vals_index[contrib_name_value_slice]&.values&.first
99
+ write_name_from_parallel(contributor, contributor.name.first, parallel_name_values, name_title_group, nil)
100
+ elsif parallel_name_values.size == 2 && display_type_parallel_name
101
+ contrib_name_value_slice = Cocina::Models::Builders::NameTitleGroupBuilder.value_slices(parallel_name_values.first)
102
+ name_title_group = name_title_vals_index[contrib_name_value_slice]&.values&.first
103
+ write_name_with_display_form(contributor, contributor.name.first, parallel_name_values, 0, name_title_group, nil)
104
+ else
105
+ write_multiple_parallel_contributors(parallel_name_values, contrib_name)
106
+ end
107
+ end
108
+
109
+ def write_multiple_parallel_contributors(parallel_name_values, contrib_name)
110
+ altrepgroup_id = id_generator.next_altrepgroup
111
+ parallel_name_values.each_with_index do |parallel_contrib_name, index|
112
+ display_name_present = parallel_name_values[index + 1].present? && parallel_name_values[index + 1].type == 'display'
113
+ Cocina::Models::Builders::NameTitleGroupBuilder.value_slices(parallel_contrib_name)&.each do |parallel_contrib_name_slice|
114
+ if name_title_vals_index[parallel_contrib_name_slice]
115
+ name_title_group = name_title_vals_index[parallel_contrib_name_slice]&.values&.first
116
+ if display_name_present
117
+ # associate type 'display' with the previous value
118
+ write_name_with_display_form(contributor, contrib_name, parallel_name_values, index, name_title_group, altrepgroup_id)
119
+ else
120
+ write_name_from_parallel(contributor, contrib_name, parallel_contrib_name, name_title_group, altrepgroup_id)
121
+ end
122
+ elsif display_name_present
123
+ # TODO: want a way to notify that we hit a problem - either notifier or HB error (issue #3751)
124
+ # OR validate for semantic correctness upon creation/update so we can't get here.
125
+ # notifier.warn("For contributor name '#{parallel_contrib_name_slice}', no contrib matching")
126
+ write_name_with_display_form(contributor, contrib_name, parallel_name_values, index, nil, altrepgroup_id)
127
+ elsif parallel_name_values[index].type == 'display'
128
+ # we assume we included this as part of a previous name
129
+ next
130
+ else
131
+ write_name_from_parallel(contributor, contrib_name, parallel_contrib_name, nil, altrepgroup_id)
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ def write_name_from_parallel(contributor, name, parallel_name, name_title_group, altrepgroup_id)
109
138
  attributes = parallel_name_attributes(name, parallel_name, name_title_group, altrepgroup_id)
110
139
  type_attr = NAME_TYPE.fetch(contributor.type, name_title_group ? 'personal' : nil)
111
140
  attributes[:type] = type_attr if type_attr
@@ -121,6 +150,37 @@ module Cocina
121
150
  end
122
151
  end
123
152
 
153
+ # rubocop:disable Metrics/ParameterLists
154
+ def write_name_with_display_form(contributor, name, parallel_name_values, index, name_title_group, altrepgroup_id)
155
+ display_type_parallel_name = display_type_parallel_name(parallel_name_values)
156
+ parallel_name = parallel_name_values[index]
157
+ return if parallel_name.blank?
158
+
159
+ attributes = if altrepgroup_id.present?
160
+ parallel_name_attributes(name, parallel_name, name_title_group, altrepgroup_id)
161
+ else
162
+ name_attributes(contributor, name, nil)
163
+ end
164
+ type_attr = NAME_TYPE.fetch(contributor.type, name_title_group ? 'personal' : nil)
165
+ attributes[:type] = type_attr if type_attr
166
+ xml.name attributes do
167
+ if parallel_name.structuredValue.present?
168
+ write_structured(parallel_name)
169
+ else
170
+ write_basic(parallel_name)
171
+ end
172
+ write_display_form(display_type_parallel_name) if display_type_parallel_name.present?
173
+ write_identifier(contributor) if contributor.identifier.present?
174
+ write_note(contributor)
175
+ write_roles(contributor)
176
+ end
177
+ end
178
+ # rubocop:enable Metrics/ParameterLists
179
+
180
+ def display_type_parallel_name(parallel_name_values)
181
+ parallel_name_values.detect { |parallel_value| parallel_value.type == 'display' }
182
+ end
183
+
124
184
  def parallel_name_attributes(name, parallel_name, name_title_group, altrepgroup_id)
125
185
  {
126
186
  nameTitleGroup: name_title_group,
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Cocina
4
4
  module Models
5
- VERSION = '0.80.0'
5
+ VERSION = '0.81.0'
6
6
  end
7
7
  end
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.80.0
4
+ version: 0.81.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-05-13 00:00:00.000000000 Z
11
+ date: 2022-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport