First pass at formatting holdings properly, including textual holdings statements
authordjfiander <djfiander@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Sun, 10 Jan 2010 21:50:21 +0000 (21:50 +0000)
committerdjfiander <djfiander@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Sun, 10 Jan 2010 21:50:21 +0000 (21:50 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@15291 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm
Open-ILS/src/perlmods/OpenILS/Utils/MFHD/test/mfhd.t

index b7d7686..52a1802 100755 (executable)
@@ -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;
index e414f9e..a1f71f8 100644 (file)
@@ -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: {