From ad02a0eac60ef3e57060a86abec052504675953c Mon Sep 17 00:00:00 2001 From: djfiander Date: Sun, 10 Jan 2010 21:50:21 +0000 Subject: [PATCH] First pass at formatting holdings properly, including textual holdings statements git-svn-id: svn://svn.open-ils.org/ILS/trunk@15291 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm | 144 +++++++++++++++++++++ .../src/perlmods/OpenILS/Utils/MFHD/test/mfhd.t | 4 +- 2 files changed, 147 insertions(+), 1 deletion(-) diff --git a/Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm b/Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm index b7d7686fe..52a180235 100755 --- a/Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm +++ b/Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm @@ -200,4 +200,148 @@ sub generate_predictions { return @predictions; } +# +# format_holdings(): Generate textual display of all holdings in record +# for given type of caption (853--855) taking into account all the +# captions, holdings statements, and textual +# holdings. +# +# returns string formatted holdings as one very long line. +# Caller must provide any label (such as "library has:" and insert +# line breaks as appropriate. + +# Translate caption field labels to the corresponding textual holdings +# statement labels. That is, convert 853 "Basic bib unit" caption to +# 866 "basic bib unit" text holdings label. + +my %cap_to_txt = ( + '853' => '866', + '854' => '867', + '855' => '868', + ); + +sub format_holdings { + my $self = shift; + my $field = shift; + my $holdings_field; + my @txt_holdings; + my %txt_link_ids; + my $holdings_stmt = ''; + my ($l, $start); + + # convert caption field id to holdings field id + ($holdings_field = $field) =~ s/5/6/; + + # Textual holdings statements complicate the basic algorithm for + # formatting the holdings: If there's a textual holdings statement + # with the subfield "$80", then that overrides ALL the MFHD holdings + # information and is all that is displayed. Otherwise, the textual + # holdings statements will either replace some of the MFHD holdings + # information, or supplement it, depending on the value of the + # $8 linkage subfield. + + if (defined $self->field($cap_to_txt{$field})) { + @txt_holdings = $self->field($cap_to_txt{$field}); + + foreach my $txt (@txt_holdings) { + + # if there's a $80 subfield, then we're done, it's + # all the formatted holdings + if ($txt->subfield('8') eq '0') { + # textual holdings statement that completely + # replaces MFHD holdings in 853/863, etc. + $holdings_stmt = $txt->subfield('a'); + + if (defined $txt->subfield('z')) { + $holdings_stmt .= ' -- ' . $txt->subfield('z'); + } + + printf("# format_holdings() returning %s txt holdings\n", + $cap_to_txt{$field}); + return $holdings_stmt; + } + + # If there are non-$80 subfields in the textual holdings + # then we need to keep track of the subfields, so we can + # intersperse the textual holdings in with the the calculated + # holdings from the 853/863 fields. + foreach my $linkid ($txt->subfield('8')) { + $txt_link_ids{$linkid} = $txt; + } + } + } + + # Now loop through all the captions, finding the corresponding + # holdings statements (either MFHD or textual), and build up the + # complete formatted holdings statement. The textual holdings statements + # have either the same link id field as a caption, which means that + # the text holdings win, or they have ids that are interfiled with + # the captions, which mean they go into the middle. + + my @ids = sort($self->caption_link_ids($field), keys %txt_link_ids); + foreach my $cap_id (@ids) { + my $last_txt = undef; + + if (exists $txt_link_ids{$cap_id}) { + # there's a textual holding statement with this caption ID, + # so just use that. This covers both the "replaces" and + # the "supplements" holdings information options. + + # a single textual holdings statement can replace multiple + # captions. If the _last_ caption we saw had a textual + # holdings statement, and this caption has the same one, then + # we don't add the holdings again. + if (!defined $last_txt || ($last_txt != $txt_link_ids{$cap_id})) { + $holdings_stmt .= ',' if $holdings_stmt; + $holdings_stmt .= $txt_link_ids{$cap_id}->subfield('a'); + $last_txt = $txt_link_ids{$cap_id}; + } + next; + } + + # We found a caption that doesn't have a corresponding textual + # holdings statement, so reset $last_txt to undef. + $last_txt = undef; + + my @holdings = $self->holdings($holdings_field, $cap_id); + + next unless scalar @holdings; + + # XXX Need to format compressed holdings. see code in test.pl + # for example. Try to do it without indexing? + $holdings_stmt .= ',' if $holdings_stmt; + + if ($self->compressible) { + $start = $l = shift @holdings; + $holdings_stmt .= $l->format; + + while (my $h = shift @holdings) { + if (!$h->matches($l->next)) { + # this item is not part of the current run + # close out the run and record this item + if ($l != $start) { + $holdings_stmt .= '-' . $l->format; + } + + $holdings_stmt .= ',' . $h->format; + $start = $h + } elsif (!scalar(@holdings)) { + # This is the end of the holdings for this caption + $holdings_stmt .= '-' . $h->format; + } + + $l = $h; + } + } else { + $holdings_stmt .= ',' if $holdings_stmt; + $holdings_stmt .= (shift @holdings)->format; + foreach my $h (@holdings) { + $holdings_stmt .= ',' . $h->format; + } + } + } + + return $holdings_stmt; +} + 1; diff --git a/Open-ILS/src/perlmods/OpenILS/Utils/MFHD/test/mfhd.t b/Open-ILS/src/perlmods/OpenILS/Utils/MFHD/test/mfhd.t index e414f9ee4..a1f71f84c 100644 --- a/Open-ILS/src/perlmods/OpenILS/Utils/MFHD/test/mfhd.t +++ b/Open-ILS/src/perlmods/OpenILS/Utils/MFHD/test/mfhd.t @@ -92,7 +92,9 @@ while ($rec = load_MARC_rec) { ($htag = $cap->tag) =~ s/^85/86/; @holdings = $rec->holdings($htag, $cap->subfield('8')); - ok(scalar @holdings, "holdings defined " . $cap->subfield('8')); + if (!ok(scalar @holdings, "holdings defined " . $cap->subfield('8'))) { + next; + } foreach my $field (@holdings) { TODO: { -- 2.11.0