diff --git a/app/models/dor/update_marc_record_service.rb b/app/models/dor/update_marc_record_service.rb
index eef6ee0843..3b295a6ec2 100644
--- a/app/models/dor/update_marc_record_service.rb
+++ b/app/models/dor/update_marc_record_service.rb
@@ -34,6 +34,7 @@ def push_symphony_records
# Subfield x #5 (optional): the file-id to be used as thumb if available, recorded as file:file-id-value
# Subfield x #6..n (optional): Collection(s) this object is a member of, recorded as collection:druid-value:ckey-value:title
# Subfield x #7..n (optional): Set(s) this object is a member of, recorded as set:druid-value:ckey-value:title
+ # Subfield x #8..n (optional): label and part sort keys for the member
def generate_symphony_records
return [] unless ckeys?
@@ -71,6 +72,7 @@ def new_856_record(ckey)
new856 << thumb.prepend('|xfile:') unless thumb.nil?
new856 << get_x2_collection_info unless get_x2_collection_info.nil?
new856 << get_x2_constituent_info unless get_x2_constituent_info.nil?
+ new856 << get_x2_part_info unless get_x2_part_info.nil?
end
def get_identifier(ckey)
@@ -138,6 +140,27 @@ def get_x2_constituent_info
end.join('')
end
+ def get_x2_part_info
+ return '' unless @druid_obj.datastreams['descMetadata']
+
+ titleInfo = @druid_obj.datastreams['descMetadata'].ng_xml.xpath('//mods/titleInfo[not(@type)]').first
+ titleInfo ||= @druid_obj.datastreams['descMetadata'].ng_xml.xpath('//mods/titleInfo[@usage="primary"]').first
+ titleInfo ||= @druid_obj.datastreams['descMetadata'].ng_xml.xpath('//mods/titleInfo').first
+
+ part_parts = titleInfo.children.select do |child|
+ %w(partName partNumber).include?(child.name)
+ end
+ part_label = part_parts.map(&:text).compact.join(parts_delimiter(part_parts))
+
+ part_sort = @druid_obj.datastreams['descMetadata'].ng_xml.xpath('//*[@type="date/sequential designation"]').first
+
+ str = ''
+ str << "|xlabel:#{part_label}" unless part_label.empty?
+ str << "|xsort:#{part_sort.text}" if part_sort
+
+ str
+ end
+
def born_digital?
BORN_DIGITAL_APOS.include? @druid_obj.admin_policy_object_id
end
@@ -156,5 +179,15 @@ def dor_items_for_constituents
Dor::Item.find(cons_druid)
end
end
+
+ # adapted from mods_display
+ def parts_delimiter(elements)
+ # index will retun nil which is not comparable so we call 100
+ # if the element isn't present (thus meaning it's at the end of the list)
+ if (elements.index { |c| c.name == 'partNumber' } || 100) < (elements.index { |c| c.name == 'partName' } || 100)
+ return ', '
+ end
+ '. '
+ end
end
end
diff --git a/spec/dor/update_marc_record_service_spec.rb b/spec/dor/update_marc_record_service_spec.rb
index 44d044340a..0b8d0dd347 100644
--- a/spec/dor/update_marc_record_service_spec.rb
+++ b/spec/dor/update_marc_record_service_spec.rb
@@ -469,6 +469,161 @@
end
end
+ describe '#get_x2_part_info' do
+ let(:dor_item) { setup_test_objects('druid:aa111aa1111', '') }
+ let(:desc_metadata_xml) { instance_double(Dor::DescMetadataDS, ng_xml: Nokogiri::XML(xml) ) }
+
+ context 'without descMetadata' do
+ it 'returns an empty string for objects with part information' do
+ expect(umrs.get_x2_part_info).to be_empty
+ end
+ end
+
+ context 'with descMetadata without part information' do
+ let(:xml) do
+ <<-xml
+
+
+ Some label
+
+ xml
+ end
+ before do
+ allow(dor_item).to receive_messages(datastreams: { 'descMetadata' => desc_metadata_xml })
+ end
+ it 'returns an empty string for objects with part information' do
+ expect(umrs.get_x2_part_info).to be_empty
+ end
+ end
+
+ context 'with descMetadata with some part numbers' do
+ let(:xml) do
+ <<-xml
+
+
+ Some label
+ 55th legislature
+ 1997-1998
+
+ xml
+ end
+ before do
+ allow(dor_item).to receive_messages(datastreams: { 'descMetadata' => desc_metadata_xml })
+ end
+ it 'returns a part label' do
+ expect(umrs.get_x2_part_info).to eq '|xlabel:55th legislature, 1997-1998'
+ end
+ end
+
+ context 'with descMetadata with a part name and number' do
+ let(:xml) do
+ <<-xml
+
+
+ Some label
+ Issue #3
+ 2011
+
+ xml
+ end
+ before do
+ allow(dor_item).to receive_messages(datastreams: { 'descMetadata' => desc_metadata_xml })
+ end
+ it 'returns a part label' do
+ expect(umrs.get_x2_part_info).to eq '|xlabel:Issue #3. 2011'
+ end
+ end
+
+ context 'with descMetadata with a sequential designation in a note' do
+ let(:xml) do
+ <<-xml
+
+
+ Some label
+ Issue #3
+ 2011
+
+ 123
+
+ xml
+ end
+ before do
+ allow(dor_item).to receive_messages(datastreams: { 'descMetadata' => desc_metadata_xml })
+ end
+ it 'returns both the label and part number' do
+ expect(umrs.get_x2_part_info).to eq '|xlabel:Issue #3. 2011|xsort:123'
+ end
+ end
+
+ context 'with descMetadata with a sequential designation on a part number' do
+ let(:xml) do
+ <<-xml
+
+
+ Some label
+ Issue #3
+ 2011
+
+
+ xml
+ end
+ before do
+ allow(dor_item).to receive_messages(datastreams: { 'descMetadata' => desc_metadata_xml })
+ end
+ it 'returns both the label and part number' do
+ expect(umrs.get_x2_part_info).to eq '|xlabel:Issue #3. 2011|xsort:2011'
+ end
+ end
+
+ context 'with descMetadata with multiple titles, one of them marked as the primary title' do
+ let(:xml) do
+ <<-xml
+
+
+ Some label
+ Some lie
+
+
+ Some label
+ Issue #3
+ 2011
+
+
+ xml
+ end
+ before do
+ allow(dor_item).to receive_messages(datastreams: { 'descMetadata' => desc_metadata_xml })
+ end
+ it 'returns the label from the primary title' do
+ expect(umrs.get_x2_part_info).to eq '|xlabel:Issue #3. 2011'
+ end
+ end
+
+ context 'with descMetadata with multiple titles' do
+ let(:xml) do
+ <<-xml
+
+
+ Some label
+ Issue #3
+ 2011
+
+
+ Some label
+ Some lie
+
+
+ xml
+ end
+ before do
+ allow(dor_item).to receive_messages(datastreams: { 'descMetadata' => desc_metadata_xml })
+ end
+ it 'returns the label from the first title' do
+ expect(umrs.get_x2_part_info).to eq '|xlabel:Issue #3. 2011'
+ end
+ end
+ end
+
describe 'Released to Searchworks' do
it 'returns true if release_data tag has release to=Searchworks and value is true' do
setup_test_objects('druid:aa111aa1111', build_identity_metadata_1)