1 package C4::Heading::MARC21;
3 # Copyright (C) 2008 LibLime
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
31 use C4::Heading::MARC21;
35 This is an internal helper class used by
36 C<C4::Heading> to parse headings data from
37 MARC21 records. Object of this type
38 do not carry data, instead, they only
41 =head1 DATA STRUCTURES
43 FIXME - this should be moved to a configuration file.
45 =head2 bib_heading_fields
49 my $bib_heading_fields = {
51 auth_type => 'PERSO_NAME',
52 subfields => 'abcdfghjklmnopqrst',
56 auth_type => 'CORPO_NAME',
57 subfields => 'abcdfghklmnoprst',
61 auth_type => 'MEETI_NAME',
62 subfields => 'acdefghklnpqst',
66 auth_type => 'UNIF_TITLE',
67 subfields => 'adfghklmnoprst',
71 auth_type => 'NAME_EVENT',
72 subfields => 'acdgvxyz68',
76 auth_type => 'CHRON_TERM',
77 subfields => 'abvxyz68',
81 auth_type => 'TOPIC_TERM',
82 subfields => 'abgvxyz68',
86 auth_type => 'GEOGR_NAME',
87 subfields => 'avxyz68',
91 auth_type => 'GENRE/FORM',
92 subfields => 'abvxyz68',
96 auth_type => 'MED_PERFRM',
101 auth_type => 'TOPIC_TERM',
102 subfields => 'vxyz68'
105 auth_type => 'GEOGR_NAME',
106 subfields => 'vxyz68'
109 auth_type => 'CHRON_TERM',
110 subfields => 'vxyz68'
113 auth_type => 'GENRE/FORM',
114 subfields => 'vxyz68'
116 '440' => { auth_type => 'UNIF_TITLE', subfields => 'anp', series => 1 },
118 auth_type => 'PERSO_NAME',
119 subfields => 'abcdfghjklmnopqrstvxyz',
123 auth_type => 'CORPO_NAME',
124 subfields => 'abcdfghklmnoprstvxyz',
128 auth_type => 'MEETI_NAME',
129 subfields => 'acdefghklnpqstvxyz',
133 auth_type => 'UNIF_TITLE',
134 subfields => 'adfghklmnoprstvxyz',
137 '648' => { auth_type => 'CHRON_TERM', subfields => 'avxyz', subject => 1 },
138 '650' => { auth_type => 'TOPIC_TERM', subfields => 'abvxyz', subject => 1 },
139 '651' => { auth_type => 'GEOGR_NAME', subfields => 'avxyz', subject => 1 },
140 '655' => { auth_type => 'GENRE/FORM', subfields => 'avxyz', subject => 1 },
141 '690' => { auth_type => 'TOPIC_TERM', subfields => 'abvxyz', subject => 1 },
142 '691' => { auth_type => 'GEOGR_NAME', subfields => 'avxyz', subject => 1 },
143 '696' => { auth_type => 'PERSO_NAME', subfields => 'abcdfghjklmnopqrst' },
144 '697' => { auth_type => 'CORPO_NAME', subfields => 'abcdfghklmnoprst' },
145 '698' => { auth_type => 'MEETI_NAME', subfields => 'acdfghjklnpqst' },
146 '699' => { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst' },
147 '700' => { auth_type => 'PERSO_NAME', subfields => 'abcdfghjklmnopqrst' },
148 '710' => { auth_type => 'CORPO_NAME', subfields => 'abcdfghklmnoprst' },
149 '711' => { auth_type => 'MEETI_NAME', subfields => 'acdefghklnpqst' },
150 '730' => { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst' },
152 auth_type => 'PERSO_NAME',
153 subfields => 'abcdfghjklmnopqrst',
157 auth_type => 'CORPO_NAME',
158 subfields => 'abcdfghklmnoprst',
162 { auth_type => 'MEETI_NAME', subfields => 'acdefghklnpqst', series => 1 },
164 { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst', series => 1 },
167 my $auth_heading_fields = {
169 auth_type => 'PERSO_NAME',
170 subfields => 'abcdfghjklmnopqrstvxyz68',
174 auth_type => 'CORPO_NAME',
175 subfields => 'abcdfghklmnoprstvxyz68',
179 auth_type => 'MEETI_NAME',
180 subfields => 'acdefghklnpqstvxyz68',
184 auth_type => 'UNIF_TITLE',
185 subfields => 'adfghklmnoprstvxyz68',
189 auth_type => 'NAME_EVENT',
190 subfields => 'acdgvxyz68',
194 auth_type => 'CHRON_TERM',
195 subfields => 'abvxyz68',
199 auth_type => 'TOPIC_TERM',
200 subfields => 'abgvxyz68',
204 auth_type => 'GEOG_NAME',
205 subfields => 'avxyz68',
209 auth_type => 'GENRE/FORM',
210 subfields => 'abvxyz68',
214 auth_type => 'MED_PERFRM',
219 auth_type => 'TOPIC_TERM',
220 subfields => 'vxyz68',
223 auth_type => 'GEOGR_NAME',
224 subfields => 'vxyz68',
227 auth_type => 'CHRON_TERM',
228 subfields => 'vxyz68',
231 auth_type => 'GENRE/FORM',
232 subfields => 'vxyz68',
242 'x' => 'generalsubdiv',
243 'y' => 'chronologicalsubdiv',
244 'z' => 'geographicsubdiv',
251 my $marc_handler = C4::Heading::MARC21->new();
257 return bless {}, $class;
260 =head2 valid_heading_tag
264 sub valid_heading_tag {
267 my $frameworkcode = shift;
269 my $heading_fields = $auth ? { %$auth_heading_fields } : { %$bib_heading_fields };
271 if ( exists $heading_fields->{$tag} ) {
280 =head2 valid_heading_subfield
284 sub valid_heading_subfield {
287 my $subfield = shift;
290 my $heading_fields = $auth ? { %$auth_heading_fields } : { %$bib_heading_fields };
292 if ( exists $heading_fields->{$tag} ) {
293 return 1 if ($heading_fields->{$tag}->{subfields} =~ /$subfield/);
298 =head2 get_valid_bib_heading_subfields
302 sub get_valid_bib_heading_subfields {
306 return $bib_heading_fields->{$tag}->{subfields} // undef;
309 =head2 get_auth_heading_subfields_to_report
313 sub get_auth_heading_subfields_to_report {
317 my $subfields = $auth_heading_fields->{$tag}->{subfields} // '';
318 $subfields =~ s/[68]//;
324 Given a field and an indicator to specify if it is an authority field or biblio field we return
325 the correct type, thesauarus, search form, and display form of the heading.
334 my $tag = $field->tag;
335 my $heading_fields = $auth ? { %$auth_heading_fields } : { %$bib_heading_fields };
337 my $field_info = $heading_fields->{$tag};
338 my $auth_type = $field_info->{'auth_type'};
341 ? _get_subject_thesaurus($field)
342 : undef; # We can't know the thesaurus for non-subject fields
344 _get_search_heading( $field, $field_info->{'subfields'} );
345 my $display_heading =
346 _get_display_heading( $field, $field_info->{'subfields'} );
348 return ( $auth_type, $thesaurus, $search_heading, $display_heading,
352 =head1 INTERNAL FUNCTIONS
354 =head2 _get_subject_thesaurus
358 sub _get_subject_thesaurus {
360 my $ind2 = $field->indicator(2);
362 # NOTE: sears and aat do not appear
363 # here as they do not have indicator values
364 # though the 008 in the authority records
365 # do have values for them
367 my $thesaurus = "notdefined";
368 if ( $ind2 eq '0' ) {
371 elsif ( $ind2 eq '1' ) {
374 elsif ( $ind2 eq '2' ) {
377 elsif ( $ind2 eq '3' ) {
380 elsif ( $ind2 eq '4' ) {
381 $thesaurus = "notspecified";
383 elsif ( $ind2 eq '5' ) {
386 elsif ( $ind2 eq '6' ) {
389 elsif ( $ind2 eq '7' ) {
390 my $sf2 = $field->subfield('2');
391 $thesaurus = $sf2 if defined($sf2);
397 =head2 _get_search_heading
401 sub _get_search_heading {
403 my $subfields = shift;
406 my @subfields = $field->subfields();
408 for ( my $i = 0 ; $i <= $#subfields ; $i++ ) {
409 my $code = $subfields[$i]->[0];
410 my $code_re = quotemeta $code;
411 my $value = $subfields[$i]->[1];
412 $value =~ s/[\s]*[-,.:=;!%\/]*[\s]*$//;
413 next unless $subfields =~ qr/$code_re/;
419 if ( exists $subdivisions{$code} ) {
420 $heading .= " $subdivisions{$code} $value";
423 $heading .= " $value";
428 # remove characters that are part of CCL syntax
429 $heading =~ s/[)(=]//g;
434 =head2 _get_display_heading
438 sub _get_display_heading {
440 my $subfields = shift;
443 my @subfields = $field->subfields();
445 for ( my $i = 0 ; $i <= $#subfields ; $i++ ) {
446 my $code = $subfields[$i]->[0];
447 my $code_re = quotemeta $code;
448 my $value = $subfields[$i]->[1];
449 next unless $subfields =~ qr/$code_re/;
455 if ( exists $subdivisions{$code} ) {
456 $heading .= "--$value";
459 $heading .= " $value";
466 # Additional limiters that we aren't using:
467 # if ($self->{'subject_added_entry'}) {
468 # $limiters .= " AND Heading-use-subject-added-entry=a";
470 # if ($self->{'series_added_entry'}) {
471 # $limiters .= " AND Heading-use-series-added-entry=a";
473 # if (not $self->{'subject_added_entry'} and not $self->{'series_added_entry'}) {
474 # $limiters .= " AND Heading-use-main-or-added-entry=a"
479 Koha Development Team <http://koha-community.org/>
481 Galen Charlton <galen.charlton@liblime.com>