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)