Check for compressibility at parse/load time, not during formatting..
authordjfiander <djfiander@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 11 Nov 2008 02:46:30 +0000 (02:46 +0000)
committerdjfiander <djfiander@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 11 Nov 2008 02:46:30 +0000 (02:46 +0000)
Compress across volume boundaries when issues are numbered continuously (eg, Economist)

git-svn-id: svn://svn.open-ils.org/ILS/trunk@11126 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/perlmods/OpenILS/Utils/MFHD.pm
Open-ILS/src/perlmods/OpenILS/Utils/MFHD/Caption.pm
Open-ILS/src/perlmods/OpenILS/Utils/MFHD/Holding.pm

index 42911c4..6a6d610 100755 (executable)
@@ -16,6 +16,7 @@ sub new {
 
     $self->{RECORD} = $rec;
     $self->{CAPTIONS} = {};
+    $self->{COMPRESSIBLE} = (substr($rec->leader, 17, 1) =~ /[45]/);
 
     foreach my $field ('853', '854', '855') {
        my $captions = {};
@@ -27,6 +28,9 @@ sub new {
                carp "Multiple unlabelled MFHD captions";
            }
            $captions->{$cap_id} = new MFHD::Caption($caption);
+           if ($self->{COMPRESSIBLE}) {
+               $self->{COMPRESSIBLE} &&= $captions->{$cap_id}->compressible;
+           }
        }
        $self->{CAPTIONS}->{$field} = $captions;
     }
@@ -37,18 +41,24 @@ sub new {
 
        ($cap_field = $field) =~ s/6/5/;
 
-       foreach my $holding ($rec->field($field)) {
+       foreach my $hfield ($rec->field($field)) {
            my $linkage;
            my ($link_id, $seqno);
+           my $holding;
 
-           $linkage = $holding->subfield('8');
+           $linkage = $hfield->subfield('8');
            ($link_id, $seqno) = split(/\./, $linkage);
 
            if (!exists $holdings->{$link_id}) {
                $holdings->{$link_id} = {};
            }
-           $holdings->{$link_id}->{$seqno} =
-             new MFHD::Holding($seqno, $holding, $self->{CAPTIONS}->{$cap_field}->{$link_id});
+           $holding = new MFHD::Holding($seqno, $hfield,
+                                        $self->{CAPTIONS}->{$cap_field}->{$link_id});
+           $holdings->{$link_id}->{$seqno} = $holding;
+
+           if ($self->{COMPRESSIBLE}) {
+               $self->{COMPRESSIBLE} &&= $holding->validate;
+           }
        }
        $self->{HOLDINGS}->{$field} = $holdings;
     }
@@ -57,44 +67,10 @@ sub new {
     return $self;
 }
 
-# 
-# validate_captions: confirm that fields specified for holdings
-# data all have captions assigned to them
-# 
-sub validate_captions {
-    my $self = shift;
-
-    foreach my $cap_fieldno ('853' .. '855') {
-       foreach my $cap_id ($self->captions($cap_fieldno)) {
-           my $enum_fieldno;
-           ($enum_fieldno = $cap_fieldno) =~ s/5/6/;
-           foreach my $enum ($self->holdings($enum_fieldno, $cap_id)) {
-               foreach my $key (keys %{$enum->{ENUMS}}) {
-                   if (!exists $enum->{CAPTION}->{ENUMS}->{$key}) {
-                       print "$key doesn't exist: ", Dumper($enum);
-                       return 0;
-                   }
-               }
-           }
-       }
-       return 1;
-    }
-}
-
 sub compressible {
     my $self = shift;
-    my $leader = $self->{RECORD}->leader;
-    my $holdings_level = substr($leader, 17, 1);
-
-    # Can only compress level 4 detailed holdings
-    # or detailed holdings with piece designation
-    return 0 unless (($holdings_level == 4) || ($holdings_level = 5));
-
-    # Can only compress if fields specified in each enumeration are
-    # defined in the corresponding caption
-    return 0 unless $self->validate_captions;
 
-    return 1;
+    return $self->{COMPRESSIBLE};
 }
 
 sub captions {
index b1abc20..345ab52 100755 (executable)
@@ -19,6 +19,7 @@ sub new
     $self->{PATTERN} = {};
     $self->{COPY} = undef;
     $self->{UNIT} = undef;
+    $self->{COMPRESSIBLE} = 1; # until proven otherwise
 
     foreach my $subfield ($caption->subfields) {
        my ($key, $val) = @$subfield;
@@ -59,10 +60,37 @@ sub new
        }
     }
 
+    # subsequent levels of enumeration (primary and alternate)
+    # If an enumeration level doesn't document the number
+    # of "issues" per "volume", or whether numbering of issues
+    # restarts, then we can't compress.
+    foreach my $key ('b', 'c', 'd', 'e', 'f', 'h') {
+       if (exists $self->{ENUMS}->{$key}) {
+           my $pattern = $self->{ENUMS}->{$key};
+           if (!$pattern->{RESTART} || !$pattern->{COUNT}
+               || ($pattern->{COUNT} eq 'var')
+               || ($pattern->{COUNT} eq 'und')) {
+               $self->{COMPRESSIBLE} = 0;
+               last;
+           }
+       }
+    }
+
+    # If there's a $x subfield and a $j, then it's compressible
+    if (exists $self->{PATTERN}->{x} && exists $self->{CHRONS}->{'j'}) {
+       $self->{COMPRESSIBLE} = 1;
+    }
+
     bless ($self, $class);
     return $self;
 }
 
+sub compressible {
+    my $self = shift;
+
+    return $self->{COMPRESSIBLE};
+}
+
 sub caption {
     my $self = shift;
     my $key;
index 422e731..395de87 100755 (executable)
@@ -165,8 +165,18 @@ sub next {
 sub match {
     my $self = shift;
     my $pat = shift;
+    my $caption = $self->{CAPTION};
 
     foreach my $key ('a'..'f') {
+       my $nextkey;
+
+       ($nextkey = $key)++;
+       # If the next smaller enumeration exists, and is numbered
+       # continuously, then we don't need to check this one, because
+       # gaps in issue numbering matter, not changes in volume numbering
+       next if (exists $self->{ENUMS}->{$nextkey}
+                && !$caption->{ENUMS}->{$nextkey}->{RESTART});
+
        # If a subfield exists in $self but not in $pat, or vice versa
        # or if the field has different values, then fail
        if (exists($self->{ENUMS}->{$key}) != exists($pat->{$key})
@@ -178,4 +188,18 @@ sub match {
     return 1;
 }
 
+# 
+# Check that all the fields in a holdings statement are
+# included in the corresponding caption.
+# 
+sub validate {
+    my $self = shift;
+
+    foreach my $key (keys %{$self->{ENUMS}}) {
+       if (!exists $self->{CAPTION}->{ENUMS}->{$key}) {
+           return 0;
+       }
+    }
+    return 1;
+}
 1;