cocina-models 0.80.0 → 0.81.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: 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