]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Utils/MFHD/Holding.pm
Protect against the horrifying possibility that a caption might not exist
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Utils / MFHD / Holding.pm
1 package MFHD::Holding;
2 use strict;
3 use integer;
4 use Carp;
5
6 use DateTime;
7
8 use Data::Dumper;
9
10 use base 'MARC::Field';
11
12 sub new {
13     my $proto = shift;
14     my $class = ref($proto) || $proto;
15     my $seqno = shift;
16     my $self = shift;
17     my $caption = shift;
18     my $last_enum = undef;
19
20     $self->{_mfhdh_SEQNO} = $seqno;
21     $self->{_mfhdh_CAPTION} = $caption;
22     $self->{_mfhdh_DESCR} = {};
23     $self->{_mfhdh_COPY} = undef;
24     $self->{_mfhdh_BREAK} = undef;
25     $self->{_mfhdh_NOTES} = {};
26     $self->{_mfhdh_COPYRIGHT} = [];
27
28     foreach my $subfield ($self->subfields) {
29         my ($key, $val) = @$subfield;
30
31         if (($caption && $caption->enumeration_is_chronology && $key =~ /[a-h]/) || $key =~ /[i-m]/) {
32             # Chronology
33             $self->{_mfhdh_SUBFIELDS}->{$key} = $val;
34         } elsif ($key =~ /[a-h]/) {
35             # Enumeration details of holdings
36             $self->{_mfhdh_SUBFIELDS}->{$key} = {HOLDINGS => $val,
37                                                  UNIT     => undef,};
38             $last_enum = $key;
39         } elsif ($key =~ /[i-m]/) {
40         } elsif ($key eq 'o') {
41             warn '$o specified prior to first enumeration'
42               unless defined($last_enum);
43             $self->{_mfhdh_SUBFIELDS}->{$last_enum}->{UNIT} = $val;
44             $last_enum = undef;
45         } elsif ($key =~ /[npq]/) {
46             $self->{_mfhdh_DESCR}->{$key} = $val;
47         } elsif ($key eq 's') {
48             push @{$self->{_mfhdh_COPYRIGHT}}, $val;
49         } elsif ($key eq 't') {
50             $self->{_mfhdh_COPY} = $val;
51         } elsif ($key eq 'w') {
52             carp "Unrecognized break indicator '$val'"
53               unless $val =~ /^[gn]$/;
54             $self->{_mfhdh_BREAK} = $val;
55         }
56     }
57
58     bless ($self, $class);
59     return $self;
60 }
61
62 sub seqno {
63     my $self = shift;
64
65     return $self->{_mfhdh_SEQNO};
66 }
67
68 sub caption {
69     my $self = shift;
70
71     return $self->{_mfhdh_CAPTION};
72 }
73
74 sub format_chron {
75     my $self = shift;
76     my $caption = $self->{_mfhdh_CAPTION};
77     my @keys;
78     my $str = '';
79     my %month = ( '01' => 'Jan.', '02' => 'Feb.', '03' => 'Mar.',
80                   '04' => 'Apr.', '05' => 'May ', '06' => 'Jun.',
81                   '07' => 'Jul.', '08' => 'Aug.', '09' => 'Sep.',
82                   '10' => 'Oct.', '11' => 'Nov.', '12' => 'Dec.',
83                   '21' => 'Spring', '22' => 'Summer',
84                   '23' => 'Autumn', '24' => 'Winter' );
85
86     @keys = @_;
87     foreach my $i (0 .. @keys) {
88         my $key = $keys[$i];
89         my $capstr;
90         my $chron;
91         my $sep;
92
93         last if !defined $caption->capstr($key);
94
95         $capstr = $caption->capstr($key);
96         if (substr($capstr,0,1) eq '(') {
97             # a caption enclosed in parentheses is not displayed
98             $capstr = '';
99         }
100
101         # If this is the second level of chronology, then it's
102         # likely to be a month or season, so we should use the
103         # string name rather than the number given.
104         if (($i == 1) && exists $month{$self->{_mfhdh_SUBFIELDS}->{$key}}) {
105             $chron = $month{$self->{_mfhdh_SUBFIELDS}->{$key}};
106         } else {
107             $chron = $self->{_mfhdh_SUBFIELDS}->{$key};
108         }
109
110
111         $str .= (($i == 0 || $str =~ /[. ]$/) ? '' : ':') . $capstr . $chron;
112     }
113
114     return $str;
115 }
116
117 sub format {
118     my $self = shift;
119     my $caption = $self->{_mfhdh_CAPTION};
120     my $str = '';
121
122     if ($caption->enumeration_is_chronology) {
123         # if issues are identified by chronology only, then the
124         # chronology data is stored in the enumeration subfields,
125         # so format those fields as if they were chronological.
126         $str = $self->format_chron('a'..'f');
127     } else {
128         # OK, there is enumeration data and maybe chronology
129         # data as well, format both parts appropriately
130
131         # Enumerations
132         foreach my $key ('a'..'f') {
133             my $capstr;
134             my $chron;
135             my $sep;
136
137             last if !defined $caption->capstr($key);
138
139             $capstr = $caption->capstr($key);
140             if (substr($capstr, 0, 1) eq '(') {
141                 # a caption enclosed in parentheses is not displayed
142                 $capstr = '';
143             }
144             $str .= ($key eq 'a' ? '' : ':') . $capstr . $self->{_mfhdh_SUBFIELDS}->{$key}->{HOLDINGS};
145         }
146
147         # Chronology
148         if (defined $caption->capstr('i')) {
149             $str .= '(';
150             $str .= $self->format_chron('i'..'l');
151             $str .= ')';
152         }
153
154         if ($caption->capstr('g')) {
155             # There's at least one level of alternative enumeration
156             $str .= '=';
157             foreach my $key ('g', 'h') {
158                 $str .= ($key eq 'g' ? '' : ':') . $caption->capstr($key) . $self->{_mfhdh_SUBFIELDS}->{$key}->{HOLDINGS};
159             }
160
161             # This assumes that alternative chronology is only ever
162             # provided if there is an alternative enumeration.
163             if ($caption->capstr('m')) {
164                 # Alternative Chronology
165                 $str .= '(';
166                 $str .= $caption->capstr('m') . $self->{_mfhdh_SUBFIELDS}->{m}->{HOLDINGS};
167                 $str .= ')';
168             }
169         }
170     }
171
172     # Public Note
173     $str .= ' '. $caption->capstr('z') if (defined $caption->capstr('z'));
174
175     # Breaks in the sequence
176     if (defined($self->{_mfhdh_BREAK})) {
177         if ($self->{_mfhdh_BREAK} eq 'n') {
178             $str .= ' non-gap break';
179         } elsif ($self->{_mfhdh_BREAK} eq 'g') {
180             $str .= ' gap';
181         } else {
182             warn "unrecognized break indicator '$self->{_mfhdh_BREAK}'";
183         }
184     }
185
186     return $str;
187 }
188
189
190 # next: Given a holding statement, return a hash containing the
191 # enumeration values for the next issues, whether we hold it or not
192 # Just pass through to Caption::next
193 #
194 sub next {
195     my $self = shift;
196     my $caption = $self->{_mfhdh_CAPTION};
197
198     return $caption->next($self);
199 }
200
201 # match($pat): check to see if $self matches the enumeration passed
202 # in as $pat. This is expected to be used in conjunction with the next()
203 # function defined above.
204 #
205 #
206 #
207 sub match {
208     my $self = shift;
209     my $pat = shift;
210     my $caption = $self->{_mfhdh_CAPTION};
211
212     foreach my $key ('a'..'f') {
213         my $nextkey;
214
215         ($nextkey = $key)++;
216         # If the next smaller enumeration exists, and is numbered
217         # continuously, then we don't need to check this one, because
218         # gaps in issue numbering matter, not changes in volume numbering
219         next if (exists $self->{_mfhdh_SUBFIELDS}->{$nextkey}
220                  && !$caption->capfield($nextkey)->{RESTART});
221
222         # If a subfield exists in $self but not in $pat, or vice versa
223         # or if the field has different values, then fail
224         if (exists($self->{_mfhdh_SUBFIELDS}->{$key}) != exists($pat->{$key})
225             || (exists $pat->{$key}
226                 && ($self->{_mfhdh_SUBFIELDS}->{$key}->{HOLDINGS} ne $pat->{$key}))) {
227             return 0;
228         }
229     }
230     return 1;
231 }
232
233
234 # Check that all the fields in a holdings statement are
235 # included in the corresponding caption.
236
237 sub validate {
238     my $self = shift;
239
240     foreach my $key (keys %{$self->{_mfhdh_SUBFIELDS}}) {
241         if (!($self->{_mfhdh_CAPTION}) && $self->{_mfhdh_CAPTION}->capfield($key)) {
242             return 0;
243         }
244     }
245     return 1;
246 }
247 1;