| File: | C4/Heading/MARC21.pm |
| Coverage: | 13.0% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package C4::Heading::MARC21; | |||||
| 2 | ||||||
| 3 | # Copyright (C) 2008 LibLime | |||||
| 4 | # | |||||
| 5 | # This file is part of Koha. | |||||
| 6 | # | |||||
| 7 | # Koha is free software; you can redistribute it and/or modify it under the | |||||
| 8 | # terms of the GNU General Public License as published by the Free Software | |||||
| 9 | # Foundation; either version 2 of the License, or (at your option) any later | |||||
| 10 | # version. | |||||
| 11 | # | |||||
| 12 | # Koha is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| 15 | # | |||||
| 16 | # You should have received a copy of the GNU General Public License along | |||||
| 17 | # with Koha; if not, write to the Free Software Foundation, Inc., | |||||
| 18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||||
| 19 | ||||||
| 20 | 1 1 1 | 280 2 22 | use strict; | |||
| 21 | 1 1 1 | 4 2 31 | use warnings; | |||
| 22 | 1 1 1 | 4 2 41 | use MARC::Record; | |||
| 23 | 1 1 1 | 4 27 1125 | use MARC::Field; | |||
| 24 | ||||||
| 25 | our $VERSION = 3.00; | |||||
| 26 | ||||||
| 27 - 49 | =head1 NAME C4::Heading::MARC21 =head1 SYNOPSIS use C4::Heading::MARC21; =head1 DESCRIPTION This is an internal helper class used by C<C4::Heading> to parse headings data from MARC21 records. Object of this type do not carry data, instead, they only dispatch functions. =head1 DATA STRUCTURES FIXME - this should be moved to a configuration file. =head2 bib_heading_fields =cut | |||||
| 50 | ||||||
| 51 | my $bib_heading_fields = { | |||||
| 52 | '100' => { | |||||
| 53 | auth_type => 'PERSO_NAME', | |||||
| 54 | subfields => 'abcdfghjklmnopqrst', | |||||
| 55 | main_entry => 1 | |||||
| 56 | }, | |||||
| 57 | '110' => { | |||||
| 58 | auth_type => 'CORPO_NAME', | |||||
| 59 | subfields => 'abcdfghklmnoprst', | |||||
| 60 | main_entry => 1 | |||||
| 61 | }, | |||||
| 62 | '111' => { | |||||
| 63 | auth_type => 'MEETI_NAME', | |||||
| 64 | subfields => 'acdfghjklnpqst', | |||||
| 65 | main_entry => 1 | |||||
| 66 | }, | |||||
| 67 | '130' => { | |||||
| 68 | auth_type => 'UNIF_TITLE', | |||||
| 69 | subfields => 'adfghklmnoprst', | |||||
| 70 | main_entry => 1 | |||||
| 71 | }, | |||||
| 72 | '440' => { auth_type => 'UNIF_TITLE', subfields => 'anp', series => 1 }, | |||||
| 73 | '600' => { | |||||
| 74 | auth_type => 'PERSO_NAME', | |||||
| 75 | subfields => 'abcdfghjklmnopqrstvxyz', | |||||
| 76 | subject => 1 | |||||
| 77 | }, | |||||
| 78 | '610' => { | |||||
| 79 | auth_type => 'CORPO_NAME', | |||||
| 80 | subfields => 'abcdfghklmnoprstvxyz', | |||||
| 81 | subject => 1 | |||||
| 82 | }, | |||||
| 83 | '611' => { | |||||
| 84 | auth_type => 'MEETI_NAME', | |||||
| 85 | subfields => 'acdfghjklnpqstvxyz', | |||||
| 86 | subject => 1 | |||||
| 87 | }, | |||||
| 88 | '630' => { | |||||
| 89 | auth_type => 'UNIF_TITLE', | |||||
| 90 | subfields => 'adfghklmnoprstvxyz', | |||||
| 91 | subject => 1 | |||||
| 92 | }, | |||||
| 93 | '648' => { auth_type => 'CHRON_TERM', subfields => 'avxyz', subject => 1 }, | |||||
| 94 | '650' => { auth_type => 'TOPIC_TERM', subfields => 'abvxyz', subject => 1 }, | |||||
| 95 | '651' => { auth_type => 'GEOGR_NAME', subfields => 'avxyz', subject => 1 }, | |||||
| 96 | '655' => { auth_type => 'GENRE/FORM', subfields => 'avxyz', subject => 1 }, | |||||
| 97 | '700' => { auth_type => 'PERSO_NAME', subfields => 'abcdfghjklmnopqrst' }, | |||||
| 98 | '710' => { auth_type => 'CORPO_NAME', subfields => 'abcdfghklmnoprst' }, | |||||
| 99 | '711' => { auth_type => 'MEETI_NAME', subfields => 'acdfghjklnpqst' }, | |||||
| 100 | '730' => { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst' }, | |||||
| 101 | '800' => { | |||||
| 102 | auth_type => 'PERSO_NAME', | |||||
| 103 | subfields => 'abcdfghjklmnopqrst', | |||||
| 104 | series => 1 | |||||
| 105 | }, | |||||
| 106 | '810' => { | |||||
| 107 | auth_type => 'CORPO_NAME', | |||||
| 108 | subfields => 'abcdfghklmnoprst', | |||||
| 109 | series => 1 | |||||
| 110 | }, | |||||
| 111 | '811' => | |||||
| 112 | { auth_type => 'MEETI_NAME', subfields => 'acdfghjklnpqst', series => 1 }, | |||||
| 113 | '830' => | |||||
| 114 | { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst', series => 1 }, | |||||
| 115 | }; | |||||
| 116 | ||||||
| 117 - 119 | =head2 subdivisions =cut | |||||
| 120 | ||||||
| 121 | my %subdivisions = ( | |||||
| 122 | 'v' => 'formsubdiv', | |||||
| 123 | 'x' => 'generalsubdiv', | |||||
| 124 | 'y' => 'chronologicalsubdiv', | |||||
| 125 | 'z' => 'geographicsubdiv', | |||||
| 126 | ); | |||||
| 127 | ||||||
| 128 - 134 | =head1 METHODS =head2 new my $marc_handler = C4::Heading::MARC21->new(); =cut | |||||
| 135 | ||||||
| 136 | sub new { | |||||
| 137 | 0 | my $class = shift; | ||||
| 138 | 0 | return bless {}, $class; | ||||
| 139 | } | |||||
| 140 | ||||||
| 141 - 143 | =head2 valid_bib_heading_tag =cut | |||||
| 144 | ||||||
| 145 | sub valid_bib_heading_tag { | |||||
| 146 | 0 | my $self = shift; | ||||
| 147 | 0 | my $tag = shift; | ||||
| 148 | 0 | my $frameworkcode = shift; | ||||
| 149 | ||||||
| 150 | 0 | if ( exists $bib_heading_fields->{$tag} ) { | ||||
| 151 | 0 | return 1; | ||||
| 152 | } | |||||
| 153 | else { | |||||
| 154 | 0 | return 0; | ||||
| 155 | } | |||||
| 156 | ||||||
| 157 | } | |||||
| 158 | ||||||
| 159 - 161 | =head2 parse_heading =cut | |||||
| 162 | ||||||
| 163 | sub parse_heading { | |||||
| 164 | 0 | my $self = shift; | ||||
| 165 | 0 | my $field = shift; | ||||
| 166 | ||||||
| 167 | 0 | my $tag = $field->tag; | ||||
| 168 | 0 | my $field_info = $bib_heading_fields->{$tag}; | ||||
| 169 | ||||||
| 170 | 0 | my $auth_type = $field_info->{'auth_type'}; | ||||
| 171 | 0 | my $thesaurus = | ||||
| 172 | $tag =~ m/6../ | |||||
| 173 | ? _get_subject_thesaurus($field) | |||||
| 174 | : "lcsh"; # use 'lcsh' for names, UT, etc. | |||||
| 175 | 0 | my $search_heading = | ||||
| 176 | _get_search_heading( $field, $field_info->{'subfields'} ); | |||||
| 177 | 0 | my $display_heading = | ||||
| 178 | _get_display_heading( $field, $field_info->{'subfields'} ); | |||||
| 179 | ||||||
| 180 | 0 | return ( $auth_type, $thesaurus, $search_heading, $display_heading, | ||||
| 181 | 'exact' ); | |||||
| 182 | } | |||||
| 183 | ||||||
| 184 - 188 | =head1 INTERNAL FUNCTIONS =head2 _get_subject_thesaurus =cut | |||||
| 189 | ||||||
| 190 | sub _get_subject_thesaurus { | |||||
| 191 | 0 | my $field = shift; | ||||
| 192 | 0 | my $ind2 = $field->indicator(2); | ||||
| 193 | ||||||
| 194 | 0 | my $thesaurus = "notdefined"; | ||||
| 195 | 0 | if ( $ind2 eq '0' ) { | ||||
| 196 | 0 | $thesaurus = "lcsh"; | ||||
| 197 | } | |||||
| 198 | elsif ( $ind2 eq '1' ) { | |||||
| 199 | 0 | $thesaurus = "lcac"; | ||||
| 200 | } | |||||
| 201 | elsif ( $ind2 eq '2' ) { | |||||
| 202 | 0 | $thesaurus = "mesh"; | ||||
| 203 | } | |||||
| 204 | elsif ( $ind2 eq '3' ) { | |||||
| 205 | 0 | $thesaurus = "nal"; | ||||
| 206 | } | |||||
| 207 | elsif ( $ind2 eq '4' ) { | |||||
| 208 | 0 | $thesaurus = "notspecified"; | ||||
| 209 | } | |||||
| 210 | elsif ( $ind2 eq '5' ) { | |||||
| 211 | 0 | $thesaurus = "cash"; | ||||
| 212 | } | |||||
| 213 | elsif ( $ind2 eq '6' ) { | |||||
| 214 | 0 | $thesaurus = "rvm"; | ||||
| 215 | } | |||||
| 216 | elsif ( $ind2 eq '7' ) { | |||||
| 217 | 0 | my $sf2 = $field->subfield('2'); | ||||
| 218 | 0 | $thesaurus = $sf2 if defined($sf2); | ||||
| 219 | } | |||||
| 220 | ||||||
| 221 | 0 | return $thesaurus; | ||||
| 222 | } | |||||
| 223 | ||||||
| 224 - 226 | =head2 _get_search_heading =cut | |||||
| 227 | ||||||
| 228 | sub _get_search_heading { | |||||
| 229 | 0 | my $field = shift; | ||||
| 230 | 0 | my $subfields = shift; | ||||
| 231 | ||||||
| 232 | 0 | my $heading = ""; | ||||
| 233 | 0 | my @subfields = $field->subfields(); | ||||
| 234 | 0 | my $first = 1; | ||||
| 235 | for ( my $i = 0 ; $i <= $#subfields ; $i++ ) { | |||||
| 236 | 0 | my $code = $subfields[$i]->[0]; | ||||
| 237 | 0 | my $code_re = quotemeta $code; | ||||
| 238 | 0 | my $value = $subfields[$i]->[1]; | ||||
| 239 | 0 | $value =~ s/[-,.:=;!%\/]$//; | ||||
| 240 | 0 | next unless $subfields =~ qr/$code_re/; | ||||
| 241 | 0 | if ($first) { | ||||
| 242 | 0 | $first = 0; | ||||
| 243 | 0 | $heading = $value; | ||||
| 244 | } | |||||
| 245 | else { | |||||
| 246 | 0 | if ( exists $subdivisions{$code} ) { | ||||
| 247 | 0 | $heading .= " $subdivisions{$code} $value"; | ||||
| 248 | } | |||||
| 249 | else { | |||||
| 250 | 0 | $heading .= " $value"; | ||||
| 251 | } | |||||
| 252 | } | |||||
| 253 | 0 | } | ||||
| 254 | ||||||
| 255 | # remove characters that are part of CCL syntax | |||||
| 256 | 0 | $heading =~ s/[)(=]//g; | ||||
| 257 | ||||||
| 258 | 0 | return $heading; | ||||
| 259 | } | |||||
| 260 | ||||||
| 261 - 263 | =head2 _get_display_heading =cut | |||||
| 264 | ||||||
| 265 | sub _get_display_heading { | |||||
| 266 | 0 | my $field = shift; | ||||
| 267 | 0 | my $subfields = shift; | ||||
| 268 | ||||||
| 269 | 0 | my $heading = ""; | ||||
| 270 | 0 | my @subfields = $field->subfields(); | ||||
| 271 | 0 | my $first = 1; | ||||
| 272 | for ( my $i = 0 ; $i <= $#subfields ; $i++ ) { | |||||
| 273 | 0 | my $code = $subfields[$i]->[0]; | ||||
| 274 | 0 | my $code_re = quotemeta $code; | ||||
| 275 | 0 | my $value = $subfields[$i]->[1]; | ||||
| 276 | 0 | next unless $subfields =~ qr/$code_re/; | ||||
| 277 | 0 | if ($first) { | ||||
| 278 | 0 | $first = 0; | ||||
| 279 | 0 | $heading = $value; | ||||
| 280 | } | |||||
| 281 | else { | |||||
| 282 | 0 | if ( exists $subdivisions{$code} ) { | ||||
| 283 | 0 | $heading .= "--$value"; | ||||
| 284 | } | |||||
| 285 | else { | |||||
| 286 | 0 | $heading .= " $value"; | ||||
| 287 | } | |||||
| 288 | } | |||||
| 289 | 0 | } | ||||
| 290 | 0 | return $heading; | ||||
| 291 | } | |||||
| 292 | ||||||
| 293 | # Additional limiters that we aren't using: | |||||
| 294 | # if ($self->{'subject_added_entry'}) { | |||||
| 295 | # $limiters .= " AND Heading-use-subject-added-entry=a"; | |||||
| 296 | # } | |||||
| 297 | # if ($self->{'series_added_entry'}) { | |||||
| 298 | # $limiters .= " AND Heading-use-series-added-entry=a"; | |||||
| 299 | # } | |||||
| 300 | # if (not $self->{'subject_added_entry'} and not $self->{'series_added_entry'}) { | |||||
| 301 | # $limiters .= " AND Heading-use-main-or-added-entry=a" | |||||
| 302 | # } | |||||
| 303 | ||||||
| 304 - 310 | =head1 AUTHOR Koha Development Team <http://koha-community.org/> Galen Charlton <galen.charlton@liblime.com> =cut | |||||
| 311 | ||||||
| 312 | 1; | |||||