--- trunk/lib/WebPAC/Normalize.pm 2007/09/06 19:12:15 889 +++ trunk/lib/WebPAC/Normalize.pm 2007/11/10 11:11:16 1021 @@ -1,19 +1,22 @@ package WebPAC::Normalize; use Exporter 'import'; -@EXPORT = qw/ - _set_rec _set_lookup +our @EXPORT = qw/ + _set_ds _set_lookup _set_load_row _get_ds _clean_ds _debug _pack_subfields_hash - tag search display + search_display search display sorted + marc marc_indicators marc_repeatable_subfield marc_compose marc_leader marc_fixed marc_duplicate marc_remove marc_count marc_original_order + marc_template rec1 rec2 rec + frec frec_eq frec_ne regex prefix suffix surround first lookup join_with save_into_lookup @@ -22,6 +25,7 @@ get set count + /; use warnings; @@ -35,18 +39,20 @@ # debugging warn(s) my $debug = 0; +# FIXME +use WebPAC::Normalize::ISBN; +push @EXPORT, ( 'isbn_10', 'isbn_13' ); + +use WebPAC::Normalize::MARC; +push @EXPORT, ( 'marc_template' ); =head1 NAME WebPAC::Normalize - describe normalisaton rules using sets -=head1 VERSION - -Version 0.29 - =cut -our $VERSION = '0.29'; +our $VERSION = '0.35'; =head1 SYNOPSIS @@ -59,7 +65,7 @@ C. Normalisation can generate multiple output normalized data. For now, supported output -types (on the left side of definition) are: C, C, C and +types (on the left side of definition) are: C, C, C and C. =head1 FUNCTIONS @@ -78,7 +84,7 @@ marc_encoding => 'utf-8', config => $config, load_row_coderef => sub { - my ($database,$input,$mfn) = shift; + my ($database,$input,$mfn) = @_; $store->load_row( database => $database, input => $input, id => $mfn ); }, ); @@ -104,33 +110,42 @@ die "need row argument" unless ($arg->{row}); die "need normalisation argument" unless ($arg->{rules}); - no strict 'subs'; _set_lookup( $arg->{lookup} ) if defined($arg->{lookup}); - _set_rec( $arg->{row} ); + _set_ds( $arg->{row} ); _set_config( $arg->{config} ) if defined($arg->{config}); _clean_ds( %{ $arg } ); $load_row_coderef = $arg->{load_row_coderef}; - eval "$arg->{rules}"; + no strict 'subs'; + no warnings 'redefine'; + eval "$arg->{rules};"; die "error evaling $arg->{rules}: $@\n" if ($@); return _get_ds(); } -=head2 _set_rec +=head2 _set_ds Set current record hash - _set_rec( $rec ); + _set_ds( $rec ); =cut my $rec; -sub _set_rec { +sub _set_ds { $rec = shift or die "no record hash"; } +=head2 + + my $rec = _get_rec(); + +=cut + +sub _get_rec { $rec }; + =head2 _set_config Set current config hash @@ -171,6 +186,7 @@ my ($marc_record_offset, $marc_fetch_offset) = (0, 0); sub _get_ds { +#warn "## out = ",dump($out); return $out; } @@ -442,40 +458,51 @@ Those functions generally have to first in your normalization file. -=head2 tag +=head2 search_display -Define new tag for I and I. +Define output for L and L at the same time - tag('Title', rec('200','a') ); + search_display('Title', rec('200','a') ); =cut -sub tag { - my $name = shift or die "tag needs name as first argument"; +sub search_display { + my $name = shift or die "search_display needs name as first argument"; my @o = grep { defined($_) && $_ ne '' } @_; return unless (@o); - $out->{$name}->{tag} = $name; $out->{$name}->{search} = \@o; $out->{$name}->{display} = \@o; } +=head2 tag + +Old name for L, but supported + +=cut + +sub tag { + search_display( @_ ); +} + =head2 display -Define tag just for I +Define output just for I @v = display('Title', rec('200','a') ); =cut -sub display { - my $name = shift or die "display needs name as first argument"; +sub _field { + my $type = shift or confess "need type -- BUG?"; + my $name = shift or confess "needs name as first argument"; my @o = grep { defined($_) && $_ ne '' } @_; return unless (@o); - $out->{$name}->{tag} = $name; - $out->{$name}->{display} = \@o; + $out->{$name}->{$type} = \@o; } +sub display { _field( 'display', @_ ) } + =head2 search Prepare values just for I @@ -484,13 +511,18 @@ =cut -sub search { - my $name = shift or die "search needs name as first argument"; - my @o = grep { defined($_) && $_ ne '' } @_; - return unless (@o); - $out->{$name}->{tag} = $name; - $out->{$name}->{search} = \@o; -} +sub search { _field( 'search', @_ ) } + +=head2 sorted + +Insert into lists which will be automatically sorted + + sorted('Title', rec('200','a') ); + +=cut + +sub sorted { _field( 'sorted', @_ ) } + =head2 marc_leader @@ -795,7 +827,7 @@ return unless defined($rec->{$from}); my $r = $rec->{$from}; - die "record field $from isn't array\n" unless (ref($r) eq 'ARRAY'); + die "record field $from isn't array ",dump( $rec ) unless (ref($r) eq 'ARRAY'); my ($i1,$i2) = defined($marc_indicators->{$to}) ? @{ $marc_indicators->{$to} } : (' ',' '); warn "## marc_original_order($to,$from) source = ", dump( $r ),$/ if ($debug > 1); @@ -840,6 +872,7 @@ warn "## marc_record = ", dump( $marc_record ),$/ if ($debug > 1); } + =head2 marc_count Return number of MARC records created using L. @@ -852,6 +885,17 @@ return $#{ $marc_record }; } +=head2 _marc_push + + _marc_push( $marc ); + +=cut + +sub _marc_push { + my $marc = shift || die "no marc?"; + push @{ $marc_record->[ $marc_record_offset ] }, $marc; +} + =head1 Functions to extract data from input @@ -997,6 +1041,54 @@ } } +=head2 frec + +Returns first value from field + + $v = frec('200'); + $v = frec('200','a'); + +=cut + +sub frec { + my @out = rec(@_); + warn "rec(",dump(@_),") has more than one return value, ignoring\n" if $#out > 0; + return shift @out; +} + +=head2 frec_eq + +=head2 frec_ne + +Check if first values from two fields are same or different + + if ( frec_eq( 900 => 'a', 910 => 'c' ) ) { + # values are same + } else { + # values are different + } + +Strictly speaking C and C wouldn't be needed if you +could write something like: + + if ( frec( '900','a' ) eq frec( '910','c' ) ) { + # yada tada + } + +but you can't since our parser L will remove all whitespaces +in order to parse text and create invalid function C. + +=cut + +sub frec_eq { + my ( $f1,$sf1, $f2, $sf2 ) = @_; + return (rec( $f1, $sf1 ))[0] eq (rec( $f2, $sf2 ))[0]; +} + +sub frec_ne { + return ! frec_eq( @_ ); +} + =head2 regex Apply regex to some or all values @@ -1232,7 +1324,6 @@ $database_code = config(); # use _ from hash $database_name = config('name'); $database_input_name = config('input name'); - $tag = config('input normalize tag'); Up to three levels are supported.