/[webpac2]/trunk/lib/WebPAC/Normalize.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/lib/WebPAC/Normalize.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 979 by dpavlin, Sat Nov 3 12:37:43 2007 UTC revision 1018 by dpavlin, Fri Nov 9 23:46:44 2007 UTC
# Line 1  Line 1 
1  package WebPAC::Normalize;  package WebPAC::Normalize;
2  use Exporter 'import';  use Exporter 'import';
3  @EXPORT = qw/  our @EXPORT = qw/
4          _set_rec _set_lookup          _set_ds _set_lookup
5          _set_load_row          _set_load_row
6          _get_ds _clean_ds          _get_ds _clean_ds
7          _debug          _debug
# Line 13  use Exporter 'import'; Line 13  use Exporter 'import';
13          marc_compose marc_leader marc_fixed          marc_compose marc_leader marc_fixed
14          marc_duplicate marc_remove marc_count          marc_duplicate marc_remove marc_count
15          marc_original_order          marc_original_order
16            marc_template
17    
18          rec1 rec2 rec          rec1 rec2 rec
19          frec          frec frec_eq frec_ne
20          regex prefix suffix surround          regex prefix suffix surround
21          first lookup join_with          first lookup join_with
22          save_into_lookup          save_into_lookup
# Line 24  use Exporter 'import'; Line 25  use Exporter 'import';
25    
26          get set          get set
27          count          count
28    
29  /;  /;
30    
31  use warnings;  use warnings;
# Line 37  use Carp qw/confess/; Line 39  use Carp qw/confess/;
39  # debugging warn(s)  # debugging warn(s)
40  my $debug = 0;  my $debug = 0;
41    
42    use WebPAC::Normalize::ISBN;
43    push @EXPORT, ( 'isbn_10', 'isbn_13' );
44    
45  =head1 NAME  =head1 NAME
46    
# Line 44  WebPAC::Normalize - describe normalisato Line 48  WebPAC::Normalize - describe normalisato
48    
49  =cut  =cut
50    
51  our $VERSION = '0.31';  our $VERSION = '0.34';
52    
53  =head1 SYNOPSIS  =head1 SYNOPSIS
54    
# Line 102  sub data_structure { Line 106  sub data_structure {
106          die "need row argument" unless ($arg->{row});          die "need row argument" unless ($arg->{row});
107          die "need normalisation argument" unless ($arg->{rules});          die "need normalisation argument" unless ($arg->{rules});
108    
         # FIXME load this conditionally  
 #       use WebPAC::Normalize::ISBN;  
   
         no strict 'subs';  
109          _set_lookup( $arg->{lookup} ) if defined($arg->{lookup});          _set_lookup( $arg->{lookup} ) if defined($arg->{lookup});
110          _set_rec( $arg->{row} );          _set_ds( $arg->{row} );
111          _set_config( $arg->{config} ) if defined($arg->{config});          _set_config( $arg->{config} ) if defined($arg->{config});
112          _clean_ds( %{ $arg } );          _clean_ds( %{ $arg } );
113          $load_row_coderef = $arg->{load_row_coderef};          $load_row_coderef = $arg->{load_row_coderef};
114    
115          eval "$arg->{rules}";          no strict 'subs';
116            no warnings 'redefine';
117            eval "$arg->{rules};";
118          die "error evaling $arg->{rules}: $@\n" if ($@);          die "error evaling $arg->{rules}: $@\n" if ($@);
119    
120          return _get_ds();          return _get_ds();
121  }  }
122    
123  =head2 _set_rec  =head2 _set_ds
124    
125  Set current record hash  Set current record hash
126    
127    _set_rec( $rec );    _set_ds( $rec );
128    
129  =cut  =cut
130    
131  my $rec;  my $rec;
132    
133  sub _set_rec {  sub _set_ds {
134          $rec = shift or die "no record hash";          $rec = shift or die "no record hash";
135  }  }
136    
# Line 172  my ($out, $marc_record, $marc_encoding, Line 174  my ($out, $marc_record, $marc_encoding,
174  my ($marc_record_offset, $marc_fetch_offset) = (0, 0);  my ($marc_record_offset, $marc_fetch_offset) = (0, 0);
175    
176  sub _get_ds {  sub _get_ds {
177    #warn "## out = ",dump($out);
 warn "## out = ",dump($out);  
   
178          return $out;          return $out;
179  }  }
180    
# Line 815  sub marc_original_order { Line 815  sub marc_original_order {
815          return unless defined($rec->{$from});          return unless defined($rec->{$from});
816    
817          my $r = $rec->{$from};          my $r = $rec->{$from};
818          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');
819    
820          my ($i1,$i2) = defined($marc_indicators->{$to}) ? @{ $marc_indicators->{$to} } : (' ',' ');          my ($i1,$i2) = defined($marc_indicators->{$to}) ? @{ $marc_indicators->{$to} } : (' ',' ');
821          warn "## marc_original_order($to,$from) source = ", dump( $r ),$/ if ($debug > 1);          warn "## marc_original_order($to,$from) source = ", dump( $r ),$/ if ($debug > 1);
# Line 860  sub marc_original_order { Line 860  sub marc_original_order {
860          warn "## marc_record = ", dump( $marc_record ),$/ if ($debug > 1);          warn "## marc_record = ", dump( $marc_record ),$/ if ($debug > 1);
861  }  }
862    
863    =head2 marc_template
864    
865    =cut
866    
867    sub marc_template {
868            my $args = {@_};
869            warn "## marc_template(",dump($args),")";
870    
871            foreach ( qw/subfields_rename marc_template/ ) {
872    #               warn "ref($_) = ",ref($args->{$_});
873                    die "$_ not ARRAY" if ref($args->{$_}) ne 'ARRAY';
874            }
875    
876            my $r = $rec->{ $args->{from} } || return;
877            die "record field ", $args->{from}, " isn't array ",dump( $rec ) unless (ref($r) eq 'ARRAY');
878    
879            my @subfields_rename = @{ $args->{subfields_rename} };
880    #       warn "### subfields_rename [$#subfields_rename] = ",dump( @subfields_rename );
881    
882            confess "need mapping in pairs for subfields_rename"
883                    if $#subfields_rename % 2 != 1;
884            
885            my ( $subfields_rename, $from_subfields, $to_subfields );
886            while ( my ( $from, $to ) = splice(@subfields_rename, 0, 2) ) {
887                    my ( $f, $t ) = (
888                            $from_subfields->{ $from }++,
889                            $to_subfields->{ $to }++
890                    );
891                    $subfields_rename->{ $from }->[ $f ] = [ $to => $t ];
892            }
893            warn "### subfields_rename = ",dump( $subfields_rename ),$/;
894            warn "### from_subfields = ", dump( $from_subfields ),$/;
895            warn "### to_subfields = ", dump( $to_subfields ),$/;
896    
897            my $fields_re = join('|', keys %$to_subfields );
898    
899            my $pos_templates;
900            my $count;
901            my @marc_order;
902            my $marc_template_order;
903            my $fill_in;
904            my @marc_out;
905    
906            foreach my $template ( @{ $args->{marc_template} } ) {
907                    $count = {};
908                    @marc_order = ();
909                    sub my_count {
910                            my $sf = shift;
911                            my $nr = $count->{$sf}++;
912                            push @marc_order, [ $sf, $nr ];
913                            return $sf . $nr;
914                    }
915                    my $pos_template = $template;
916                    $pos_template =~ s/($fields_re)/my_count($1)/ge;
917                    my $count_key = dump( $count );
918                    warn "### template: |$template| -> |$pos_template| count = $count_key marc_order = ",dump( @marc_order ),$/;
919                    $pos_templates->{ $count_key } = $pos_template;
920                    $marc_template_order->{ $pos_template } = [ @marc_order ];
921            }
922            warn "### from ",dump( $args->{marc_template} ), " created ", dump( $pos_templates ), " and ", dump( $marc_template_order );
923    
924            my $m;
925    
926            foreach my $r ( @{ $rec->{ $args->{from} } } ) {
927    
928                    my $i1 = $r->{i1} || ' ';
929                    my $i2 = $r->{i2} || ' ';
930                    $m = [ $args->{to}, $i1, $i2 ];
931    
932                    warn "### r = ",dump( $r );
933    
934                    my ( $new_r, $from_count, $to_count );
935                    foreach my $sf ( keys %{$r} ) {
936                            # skip everything which isn't one char subfield (e.g. 'subfields')
937                            next unless $sf =~ m/^\w$/;
938                            my $nr = $from_count->{$sf}++;
939                            my $rename_to = $subfields_rename->{ $sf } ||
940                                    die "can't find subfield rename for $sf/$nr in ", dump( $subfields_rename );
941                            warn "### rename $sf/$nr to ", dump( $rename_to->[$nr] ), $/;
942                            my ( $to_sf, $to_nr ) = @{ $rename_to->[$nr] };
943                            $new_r->{ $to_sf }->[ $to_nr ] = [ $sf => $nr ];
944    
945                            $to_count->{ $to_sf }++;
946                    }
947    
948                    warn "### new_r = ",dump( $new_r );
949    
950                    my $from_count_key = dump( $to_count );
951    
952                    warn "### from_count = ",dump( $from_count ), $/;
953                    warn "### to_count   = ",dump( $to_count ), $/;
954    
955                    my $template = $pos_templates->{ $from_count_key } ||
956                            die "I don't have template for:\n$from_count_key\n## available templates\n", dump( $pos_templates );
957    
958                    warn "### selected template: |$template|\n";
959    
960                    $fill_in = {};
961    
962                    foreach my $sf ( split(/\|/, $template ) ) {
963                            sub fill_in {
964                                    my ( $r, $sf, $nr ) = @_;
965                                    my ( $from_sf, $from_nr ) = @{ $new_r->{ $sf }->[ $nr ] };
966                                    my $v = $r->{ $from_sf }; # || die "no $from_sf/$from_nr";
967                                    warn "#### fill_in( $sf, $nr ) = $from_sf/$from_nr >>>> ",dump( $v ), $/;
968                                    if ( ref( $v ) eq 'ARRAY' ) {
969                                            $fill_in->{$sf}->[$nr] = $v->[$from_nr];
970                                            return $v->[$from_nr];
971                                    } elsif ( $from_nr == 0 ) {
972                                            $fill_in->{$sf}->[$nr] = $v;
973                                            return $v;
974                                    } else {
975                                            die "requested subfield $from_sf/$from_nr but it's ",dump( $v );
976                                    }
977                            }
978                            warn "#### $sf <<<< $fields_re\n";
979                            $sf =~ s/($fields_re)(\d+)/fill_in($r,$1,$2)/ge;
980                            warn "#### >>>> $sf with fill_in = ",dump( $fill_in ),$/;
981                    }
982    
983                    warn "## template: |$template|\n## marc_template_order = ",dump( $marc_template_order );
984    
985                    foreach my $sf ( @{ $marc_template_order->{$template} } ) {
986                            my ( $sf, $nr ) = @$sf;
987                            my $v = $fill_in->{$sf}->[$nr] || die "can't find fill_in $sf/$nr";
988                            warn "++ $sf/$nr |$v|\n";
989                            push @$m, ( $sf, $v );
990                    }
991    
992                    warn "#### >>>> created marc: ", dump( $m );
993    
994                    push @marc_out, $m;
995            }
996    
997            warn "### marc_template produced: ",dump( @marc_out );
998    
999            foreach my $marc ( @marc_out ) {
1000                    warn "+++ ",dump( $marc );
1001                    push @{ $marc_record->[ $marc_record_offset ] }, $marc;
1002            }
1003    }
1004    
1005  =head2 marc_count  =head2 marc_count
1006    
1007  Return number of MARC records created using L</marc_duplicate>.  Return number of MARC records created using L</marc_duplicate>.
# Line 1001  return scalar, not array. Line 1143  return scalar, not array.
1143    
1144  =cut  =cut
1145    
 sub frec {  
         my @out = rec(@_);  
         warn "rec(",dump(@_),") has more than one return value, ignoring\n" if $#out > 0;  
         return shift @out;  
 }  
   
1146  sub rec {  sub rec {
1147          my @out;          my @out;
1148          if ($#_ == 0) {          if ($#_ == 0) {
# Line 1023  sub rec { Line 1159  sub rec {
1159          }          }
1160  }  }
1161    
1162    =head2 frec
1163    
1164    Returns first value from field
1165    
1166      $v = frec('200');
1167      $v = frec('200','a');
1168    
1169    =cut
1170    
1171    sub frec {
1172            my @out = rec(@_);
1173            warn "rec(",dump(@_),") has more than one return value, ignoring\n" if $#out > 0;
1174            return shift @out;
1175    }
1176    
1177    =head2 frec_eq
1178    
1179    =head2 frec_ne
1180    
1181    Check if first values from two fields are same or different
1182    
1183      if ( frec_eq( 900 => 'a', 910 => 'c' ) ) {
1184            # values are same
1185      } else {
1186        # values are different
1187      }
1188    
1189    Strictly speaking C<frec_eq> and C<frec_ne> wouldn't be needed if you
1190    could write something like:
1191    
1192      if ( frec( '900','a' ) eq frec( '910','c' ) ) {
1193            # yada tada
1194      }
1195    
1196    but you can't since our parser L<WebPAC::Parser> will remove all whitespaces
1197    in order to parse text and create invalid function C<eqfrec>.
1198    
1199    =cut
1200    
1201    sub frec_eq {
1202            my ( $f1,$sf1, $f2, $sf2 ) = @_;
1203            return (rec( $f1, $sf1 ))[0] eq (rec( $f2, $sf2 ))[0];
1204    }
1205    
1206    sub frec_ne {
1207            return ! frec_eq( @_ );
1208    }
1209    
1210  =head2 regex  =head2 regex
1211    
1212  Apply regex to some or all values  Apply regex to some or all values

Legend:
Removed from v.979  
changed lines
  Added in v.1018

  ViewVC Help
Powered by ViewVC 1.1.26