/[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 10 by dpavlin, Sat Jul 16 20:35:30 2005 UTC revision 1118 by dpavlin, Sun Oct 26 15:57:37 2008 UTC
# Line 1  Line 1 
1  package WebPAC::Normalize;  package WebPAC::Normalize;
2    use Exporter 'import';
3    our @EXPORT = qw/
4            _set_ds _set_lookup
5            _set_load_row
6            _get_ds _clean_ds
7            _debug
8            _pack_subfields_hash
9    
10            to
11            search_display search display sorted
12    
13            rec1 rec2 rec
14            frec frec_eq frec_ne
15            regex prefix suffix surround
16            first lookup join_with
17            save_into_lookup
18    
19            split_rec_on
20    
21            get set
22            count
23    
24    /;
25    
26  use warnings;  use warnings;
27  use strict;  use strict;
28    
29  =head1 NAME  #use base qw/WebPAC::Common/;
30    use Data::Dump qw/dump/;
31    use Carp qw/confess/;
32    
33    # debugging warn(s)
34    my $debug = 0;
35    _debug( $debug );
36    
37    # FIXME
38    use WebPAC::Normalize::ISBN;
39    push @EXPORT, ( 'isbn_10', 'isbn_13' );
40    
41    use WebPAC::Normalize::MARC;
42    push @EXPORT, ( qw/
43            marc marc_indicators marc_repeatable_subfield
44            marc_compose marc_leader marc_fixed
45            marc_duplicate marc_remove marc_count
46            marc_original_order
47            marc_template
48    /);
49    
50  WebPAC::Normalize - normalisation of source file  use Storable qw/dclone/;
51    
52  =head1 VERSION  =head1 NAME
53    
54  Version 0.01  WebPAC::Normalize - describe normalisaton rules using sets
55    
56  =cut  =cut
57    
58  our $VERSION = '0.01';  our $VERSION = '0.36';
59    
60  =head1 SYNOPSIS  =head1 SYNOPSIS
61    
62  This package contains code that could be helpful in implementing different  This module uses C<conf/normalize/*.pl> files to perform normalisation
63  normalisation front-ends.  from input records using perl functions which are specialized for set
64    processing.
65    
66    Sets are implemented as arrays, and normalisation file is valid perl, which
67    means that you check it's validity before running WebPAC using
68    C<perl -c normalize.pl>.
69    
70    Normalisation can generate multiple output normalized data. For now, supported output
71    types (on the left side of definition) are: C<search_display>, C<display>, C<search> and
72    C<marc>.
73    
74  =head1 FUNCTIONS  =head1 FUNCTIONS
75    
76  =head2 none_yet  Functions which start with C<_> are private and used by WebPAC internally.
77    All other functions are available for use within normalisation rules.
78    
79    =head2 data_structure
80    
81    Return data structure
82    
83      my $ds = WebPAC::Normalize::data_structure(
84            lookup => $lookup_hash,
85            row => $row,
86            rules => $normalize_pl_config,
87            marc_encoding => 'utf-8',
88            config => $config,
89            load_row_coderef => sub {
90                    my ($database,$input,$mfn) = @_;
91                    $store->load_row( database => $database, input => $input, id => $mfn );
92            },
93      );
94    
95    Options C<row>, C<rules> and C<log> are mandatory while all
96    other are optional.
97    
98    C<load_row_coderef> is closure only used when executing lookups, so they will
99    die if it's not defined.
100    
101    This function will B<die> if normalizastion can't be evaled.
102    
103    Since this function isn't exported you have to call it with
104    C<WebPAC::Normalize::data_structure>.
105    
106    =cut
107    
108    my $load_row_coderef;
109    
110    sub data_structure {
111            my $arg = {@_};
112    
113            die "need row argument" unless ($arg->{row});
114            die "need normalisation argument" unless ($arg->{rules});
115    
116            _set_lookup( $arg->{lookup} ) if defined($arg->{lookup});
117            _set_ds( $arg->{row} );
118            _set_config( $arg->{config} ) if defined($arg->{config});
119            _clean_ds( %{ $arg } );
120            $load_row_coderef = $arg->{load_row_coderef};
121    
122            no strict 'subs';
123            no warnings 'redefine';
124            eval "$arg->{rules};";
125            die "error evaling $arg->{rules}: $@\n" if ($@);
126    
127            return _get_ds();
128    }
129    
130    =head2 _set_ds
131    
132    Set current record hash
133    
134      _set_ds( $rec );
135    
136    =cut
137    
138    my $rec;
139    
140    sub _set_ds {
141            $rec = shift or die "no record hash";
142            $WebPAC::Normalize::MARC::rec = $rec;
143    }
144    
145    =head2
146    
147      my $rec = _get_rec();
148    
149    =cut
150    
151    sub _get_rec { $rec };
152    
153    =head2 _set_config
154    
155    Set current config hash
156    
157      _set_config( $config );
158    
159    Magic keys are:
160    
161    =over 4
162    
163    =item _
164    
165    Code of current database
166    
167    =item _mfn
168    
169    Current MFN
170    
171    =back
172    
173    =cut
174    
175    my $config;
176    
177    sub _set_config {
178            $config = shift;
179    }
180    
181    =head2 _get_ds
182    
183    Return hash formatted as data structure
184    
185      my $ds = _get_ds();
186    
187    =cut
188    
189    my $out;
190    
191    sub _get_ds {
192    #warn "## out = ",dump($out);
193            return $out;
194    }
195    
196    =head2 _clean_ds
197    
198    Clean data structure hash for next record
199    
200      _clean_ds();
201    
202    =cut
203    
204    sub _clean_ds {
205            my $a = {@_};
206            $out = undef;
207            WebPAC::Normalize::MARC::_clean();
208    }
209    
210    =head2 _set_lookup
211    
212    Set current lookup hash
213    
214      _set_lookup( $lookup );
215    
216    =cut
217    
218    my $lookup;
219    
220    sub _set_lookup {
221            $lookup = shift;
222    }
223    
224    =head2 _get_lookup
225    
226    Get current lookup hash
227    
228      my $lookup = _get_lookup();
229    
230    =cut
231    
232    sub _get_lookup {
233            return $lookup;
234    }
235    
236    =head2 _set_load_row
237    
238    Setup code reference which will return L<data_structure> from
239    L<WebPAC::Store>
240    
241      _set_load_row(sub {
242                    my ($database,$input,$mfn) = @_;
243                    $store->load_row( database => $database, input => $input, id => $mfn );
244      });
245    
246    =cut
247    
248    sub _set_load_row {
249            my $coderef = shift;
250            confess "argument isn't CODE" unless ref($coderef) eq 'CODE';
251    
252            $load_row_coderef = $coderef;
253    }
254    
255    =head2 _debug
256    
257    Change level of debug warnings
258    
259      _debug( 2 );
260    
261    =cut
262    
263    sub _debug {
264            my $l = shift;
265            return $debug unless defined($l);
266            warn "debug level $l",$/ if ($l > 0);
267            $debug = $l;
268            $WebPAC::Normalize::MARC::debug = $debug;
269    }
270    
271    =head1 Functions to create C<data_structure>
272    
273    Those functions generally have to first in your normalization file.
274    
275    =head2 to
276    
277    Generic way to set values for some name
278    
279      to('field-name', 'name-value' => rec('200','a') );
280    
281    There are many helpers defined below which might be easier to use.
282    
283    =cut
284    
285    sub to {
286            my $type = shift or confess "need type -- BUG?";
287            my $name = shift or confess "needs name as first argument";
288            my @o = grep { defined($_) && $_ ne '' } @_;
289            return unless (@o);
290            $out->{$name}->{$type} = \@o;
291    }
292    
293    =head2 search_display
294    
295    Define output for L<search> and L<display> at the same time
296    
297      search_display('Title', rec('200','a') );
298    
299    =cut
300    
301    sub search_display {
302            my $name = shift or die "search_display needs name as first argument";
303            my @o = grep { defined($_) && $_ ne '' } @_;
304            return unless (@o);
305            $out->{$name}->{search} = \@o;
306            $out->{$name}->{display} = \@o;
307    }
308    
309    =head2 tag
310    
311    Old name for L<search_display>, it will probably be removed at one point.
312    
313  =cut  =cut
314    
315  sub none_yet {  sub tag {
316            search_display( @_ );
317  }  }
318    
319  =head1 AUTHOR  =head2 display
320    
321    Define output just for I<display>
322    
323      @v = display('Title', rec('200','a') );
324    
325    =cut
326    
327  Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>  sub display { to( 'display', @_ ) }
328    
329  =head1 COPYRIGHT & LICENSE  =head2 search
330    
331  Copyright 2005 Dobrica Pavlinusic, All Rights Reserved.  Prepare values just for I<search>
332    
333  This program is free software; you can redistribute it and/or modify it    @v = search('Title', rec('200','a') );
 under the same terms as Perl itself.  
334    
335  =cut  =cut
336    
337  1; # End of WebPAC::DB  sub search { to( 'search', @_ ) }
338    
339    =head2 sorted
340    
341    Insert into lists which will be automatically sorted
342    
343     sorted('Title', rec('200','a') );
344    
345    =cut
346    
347    sub sorted { to( 'sorted', @_ ) }
348    
349    
350    =head1 Functions to extract data from input
351    
352    This function should be used inside functions to create C<data_structure> described
353    above.
354    
355    =head2 _pack_subfields_hash
356    
357     @subfields = _pack_subfields_hash( $h );
358     $subfields = _pack_subfields_hash( $h, 1 );
359    
360    Return each subfield value in array or pack them all together and return scalar
361    with subfields (denoted by C<^>) and values.
362    
363    =cut
364    
365    sub _pack_subfields_hash {
366    
367            warn "## _pack_subfields_hash( ",dump(@_), " )\n" if ($debug > 1);
368    
369            my ($hash,$include_subfields) = @_;
370    
371            # sanity and ease of use
372            return $hash if (ref($hash) ne 'HASH');
373    
374            my $h = dclone( $hash );
375    
376            if ( defined($h->{subfields}) ) {
377                    my $sfs = delete $h->{subfields} || die "no subfields?";
378                    my @out;
379                    while (@$sfs) {
380                            my $sf = shift @$sfs;
381                            push @out, '^' . $sf if ($include_subfields);
382                            my $o = shift @$sfs;
383                            if ($o == 0 && ref( $h->{$sf} ) ne 'ARRAY' ) {
384                                    # single element subfields are not arrays
385    #warn "====> $sf $o / $#$sfs ", dump( $sfs, $h->{$sf} ), "\n";
386    
387                                    push @out, $h->{$sf};
388                            } else {
389    #warn "====> $sf $o / $#$sfs ", dump( $sfs, $h->{$sf} ), "\n";
390                                    push @out, $h->{$sf}->[$o];
391                            }
392                    }
393                    if ($include_subfields) {
394                            return join('', @out);
395                    } else {
396                            return @out;
397                    }
398            } else {
399                    if ($include_subfields) {
400                            my $out = '';
401                            foreach my $sf (sort keys %$h) {
402                                    if (ref($h->{$sf}) eq 'ARRAY') {
403                                            $out .= '^' . $sf . join('^' . $sf, @{ $h->{$sf} });
404                                    } else {
405                                            $out .= '^' . $sf . $h->{$sf};
406                                    }
407                            }
408                            return $out;
409                    } else {
410                            # FIXME this should probably be in alphabetical order instead of hash order
411                            values %{$h};
412                    }
413            }
414    }
415    
416    =head2 rec1
417    
418    Return all values in some field
419    
420      @v = rec1('200')
421    
422    TODO: order of values is probably same as in source data, need to investigate that
423    
424    =cut
425    
426    sub rec1 {
427            my $f = shift;
428            warn "rec1($f) = ", dump( $rec->{$f} ), $/ if ($debug > 1);
429            return unless (defined($rec) && defined($rec->{$f}));
430            warn "rec1($f) = ", dump( $rec->{$f} ), $/ if ($debug > 1);
431            if (ref($rec->{$f}) eq 'ARRAY') {
432                    my @out;
433                    foreach my $h ( @{ $rec->{$f} } ) {
434                            if (ref($h) eq 'HASH') {
435                                    push @out, ( _pack_subfields_hash( $h ) );
436                            } else {
437                                    push @out, $h;
438                            }
439                    }
440                    return @out;
441            } elsif( defined($rec->{$f}) ) {
442                    return $rec->{$f};
443            }
444    }
445    
446    =head2 rec2
447    
448    Return all values in specific field and subfield
449    
450      @v = rec2('200','a')
451    
452    =cut
453    
454    sub rec2 {
455            my $f = shift;
456            return unless (defined($rec && $rec->{$f}));
457            my $sf = shift;
458            warn "rec2($f,$sf) = ", dump( $rec->{$f} ), $/ if ($debug > 1);
459            return map {
460                    if (ref($_->{$sf}) eq 'ARRAY') {
461                            @{ $_->{$sf} };
462                    } else {
463                            $_->{$sf};
464                    }
465            } grep { ref($_) eq 'HASH' && defined $_->{$sf} } @{ $rec->{$f} };
466    }
467    
468    =head2 rec
469    
470    syntaxtic sugar for
471    
472      @v = rec('200')
473      @v = rec('200','a')
474    
475    If rec() returns just single value, it will
476    return scalar, not array.
477    
478    =cut
479    
480    sub rec {
481            my @out;
482            if ($#_ == 0) {
483                    @out = rec1(@_);
484            } elsif ($#_ == 1) {
485                    @out = rec2(@_);
486            }
487            if ($#out == 0 && ! wantarray) {
488                    return $out[0];
489            } elsif (@out) {
490                    return @out;
491            } else {
492                    return '';
493            }
494    }
495    
496    =head2 frec
497    
498    Returns first value from field
499    
500      $v = frec('200');
501      $v = frec('200','a');
502    
503    =cut
504    
505    sub frec {
506            my @out = rec(@_);
507            warn "rec(",dump(@_),") has more than one return value, ignoring\n" if $#out > 0;
508            return shift @out;
509    }
510    
511    =head2 frec_eq
512    
513    =head2 frec_ne
514    
515    Check if first values from two fields are same or different
516    
517      if ( frec_eq( 900 => 'a', 910 => 'c' ) ) {
518            # values are same
519      } else {
520        # values are different
521      }
522    
523    Strictly speaking C<frec_eq> and C<frec_ne> wouldn't be needed if you
524    could write something like:
525    
526      if ( frec( '900','a' ) eq frec( '910','c' ) ) {
527            # yada tada
528      }
529    
530    but you can't since our parser L<WebPAC::Parser> will remove all whitespaces
531    in order to parse text and create invalid function C<eqfrec>.
532    
533    =cut
534    
535    sub frec_eq {
536            my ( $f1,$sf1, $f2, $sf2 ) = @_;
537            return (rec( $f1, $sf1 ))[0] eq (rec( $f2, $sf2 ))[0];
538    }
539    
540    sub frec_ne {
541            return ! frec_eq( @_ );
542    }
543    
544    =head2 regex
545    
546    Apply regex to some or all values
547    
548      @v = regex( 's/foo/bar/g', @v );
549    
550    =cut
551    
552    sub regex {
553            my $r = shift;
554            my @out;
555            #warn "r: $r\n", dump(\@_);
556            foreach my $t (@_) {
557                    next unless ($t);
558                    eval "\$t =~ $r";
559                    push @out, $t if ($t && $t ne '');
560            }
561            return @out;
562    }
563    
564    =head2 prefix
565    
566    Prefix all values with a string
567    
568      @v = prefix( 'my_', @v );
569    
570    =cut
571    
572    sub prefix {
573            my $p = shift;
574            return @_ unless defined( $p );
575            return map { $p . $_ } grep { defined($_) } @_;
576    }
577    
578    =head2 suffix
579    
580    suffix all values with a string
581    
582      @v = suffix( '_my', @v );
583    
584    =cut
585    
586    sub suffix {
587            my $s = shift;
588            return @_ unless defined( $s );
589            return map { $_ . $s } grep { defined($_) } @_;
590    }
591    
592    =head2 surround
593    
594    surround all values with a two strings
595    
596      @v = surround( 'prefix_', '_suffix', @v );
597    
598    =cut
599    
600    sub surround {
601            my $p = shift;
602            my $s = shift;
603            $p = '' unless defined( $p );
604            $s = '' unless defined( $s );
605            return map { $p . $_ . $s } grep { defined($_) } @_;
606    }
607    
608    =head2 first
609    
610    Return first element
611    
612      $v = first( @v );
613    
614    =cut
615    
616    sub first {
617            my $r = shift;
618            return $r;
619    }
620    
621    =head2 lookup
622    
623    Consult lookup hashes for some value
624    
625      @v = lookup(
626            sub {
627                    'ffkk/peri/mfn'.rec('000')
628            },
629            'ffkk','peri','200-a-200-e',
630            sub {
631                    first(rec(200,'a')).' '.first(rec('200','e'))
632            }
633      );
634    
635    Code like above will be B<automatically generated> using L<WebPAC::Parse> from
636    normal lookup definition in C<conf/lookup/something.pl> which looks like:
637    
638      lookup(
639            # which results to return from record recorded in lookup
640            sub { 'ffkk/peri/mfn' . rec('000') },
641            # from which database and input
642            'ffkk','peri',
643            # such that following values match
644            sub { first(rec(200,'a')) . ' ' . first(rec('200','e')) },
645            # if this part is missing, we will try to match same fields
646            # from lookup record and current one, or you can override
647            # which records to use from current record using
648            sub { rec('900','x') . ' ' . rec('900','y') },
649      )
650    
651    You can think about this lookup as SQL (if that helps):
652    
653      select
654            sub { what }
655      from
656            database, input
657      where
658        sub { filter from lookuped record }
659      having
660        sub { optional filter on current record }
661    
662    Easy as pie, right?
663    
664    =cut
665    
666    sub lookup {
667            my ($what, $database, $input, $key, $having) = @_;
668    
669            confess "lookup needs 5 arguments: what, database, input, key, having\n" unless ($#_ == 4);
670    
671            warn "## lookup ($database, $input, $key)", $/ if ($debug > 1);
672            return unless (defined($lookup->{$database}->{$input}->{$key}));
673    
674            confess "lookup really need load_row_coderef added to data_structure\n" unless ($load_row_coderef);
675    
676            my $mfns;
677            my @having = $having->();
678    
679            warn "## having = ", dump( @having ) if ($debug > 2);
680    
681            foreach my $h ( @having ) {
682                    if (defined($lookup->{$database}->{$input}->{$key}->{$h})) {
683                            warn "lookup for $database/$input/$key/$h return ",dump($lookup->{$database}->{$input}->{$key}->{$h}),"\n" if ($debug);
684                            $mfns->{$_}++ foreach keys %{ $lookup->{$database}->{$input}->{$key}->{$h} };
685                    }
686            }
687    
688            return unless ($mfns);
689    
690            my @mfns = sort keys %$mfns;
691    
692            warn "# lookup loading $database/$input/$key mfn ", join(",",@mfns)," having ",dump(@having),"\n" if ($debug);
693    
694            my $old_rec = $rec;
695            my @out;
696    
697            foreach my $mfn (@mfns) {
698                    $rec = $load_row_coderef->( $database, $input, $mfn );
699    
700                    warn "got $database/$input/$mfn = ", dump($rec), $/ if ($debug);
701    
702                    my @vals = $what->();
703    
704                    push @out, ( @vals );
705    
706                    warn "lookup for mfn $mfn returned ", dump(@vals), $/ if ($debug);
707            }
708    
709    #       if (ref($lookup->{$k}) eq 'ARRAY') {
710    #               return @{ $lookup->{$k} };
711    #       } else {
712    #               return $lookup->{$k};
713    #       }
714    
715            $rec = $old_rec;
716    
717            warn "## lookup returns = ", dump(@out), $/ if ($debug);
718    
719            if ($#out == 0) {
720                    return $out[0];
721            } else {
722                    return @out;
723            }
724    }
725    
726    =head2 save_into_lookup
727    
728    Save value into lookup. It associates current database, input
729    and specific keys with one or more values which will be
730    associated over MFN.
731    
732    MFN will be extracted from first occurence current of field 000
733    in current record, or if it doesn't exist from L<_set_config> C<_mfn>.
734    
735      my $nr = save_into_lookup($database,$input,$key,sub {
736            # code which produce one or more values
737      });
738    
739    It returns number of items saved.
740    
741    This function shouldn't be called directly, it's called from code created by
742    L<WebPAC::Parser>.
743    
744    =cut
745    
746    sub save_into_lookup {
747            my ($database,$input,$key,$coderef) = @_;
748            die "save_into_lookup needs database" unless defined($database);
749            die "save_into_lookup needs input" unless defined($input);
750            die "save_into_lookup needs key" unless defined($key);
751            die "save_into_lookup needs CODE" unless ( defined($coderef) && ref($coderef) eq 'CODE' );
752    
753            warn "## save_into_lookup rec = ", dump($rec), " config = ", dump($config), $/ if ($debug > 2);
754    
755            my $mfn =
756                    defined($rec->{'000'}->[0])     ?       $rec->{'000'}->[0]      :
757                    defined($config->{_mfn})        ?       $config->{_mfn}         :
758                                                                                    die "mfn not defined or zero";
759    
760            my $nr = 0;
761    
762            foreach my $v ( $coderef->() ) {
763                    $lookup->{$database}->{$input}->{$key}->{$v}->{$mfn}++;
764                    warn "# saved lookup $database/$input/$key [$v] $mfn\n" if ($debug > 1);
765                    $nr++;
766            }
767    
768            return $nr;
769    }
770    
771    =head2 config
772    
773    Consult config values stored in C<config.yml>
774    
775      # return database code (key under databases in yaml)
776      $database_code = config();    # use _ from hash
777      $database_name = config('name');
778      $database_input_name = config('input name');
779    
780    Up to three levels are supported.
781    
782    =cut
783    
784    sub config {
785            return unless ($config);
786    
787            my $p = shift;
788    
789            $p ||= '';
790    
791            my $v;
792    
793            warn "### getting config($p)\n" if ($debug > 1);
794    
795            my @p = split(/\s+/,$p);
796            if ($#p < 0) {
797                    $v = $config->{ '_' };  # special, database code
798            } else {
799    
800                    my $c = dclone( $config );
801    
802                    foreach my $k (@p) {
803                            warn "### k: $k c = ",dump($c),$/ if ($debug > 1);
804                            if (ref($c) eq 'ARRAY') {
805                                    $c = shift @$c;
806                                    warn "config($p) taking first occurence of '$k', probably not what you wanted!\n";
807                                    last;
808                            }
809    
810                            if (! defined($c->{$k}) ) {
811                                    $c = undef;
812                                    last;
813                            } else {
814                                    $c = $c->{$k};
815                            }
816                    }
817                    $v = $c if ($c);
818    
819            }
820    
821            warn "## config( '$p' ) = ",dump( $v ),$/ if ($v && $debug);
822            warn "config( '$p' ) is empty\n" if (! $v);
823    
824            return $v;
825    }
826    
827    =head2 id
828    
829    Returns unique id of this record
830    
831      $id = id();
832    
833    Returns C<42/2> for 2nd occurence of MFN 42.
834    
835    =cut
836    
837    sub id {
838            my $mfn = $config->{_mfn} || die "no _mfn in config data";
839            return $mfn . ( WebPAC::Normalize::MARC::_created_marc_records() || '' );
840    }
841    
842    =head2 join_with
843    
844    Joins walues with some delimiter
845    
846      $v = join_with(", ", @v);
847    
848    =cut
849    
850    sub join_with {
851            my $d = shift;
852            warn "### join_with('$d',",dump(@_),")\n" if ($debug > 2);
853            my $v = join($d, grep { defined($_) && $_ ne '' } @_);
854            return '' unless defined($v);
855            return $v;
856    }
857    
858    =head2 split_rec_on
859    
860    Split record subfield on some regex and take one of parts out
861    
862      $a_before_semi_column =
863            split_rec_on('200','a', /\s*;\s*/, $part);
864    
865    C<$part> is optional number of element. First element is
866    B<1>, not 0!
867    
868    If there is no C<$part> parameter or C<$part> is 0, this function will
869    return all values produced by splitting.
870    
871    =cut
872    
873    sub split_rec_on {
874            die "split_rec_on need (fld,sf,regex[,part]" if ($#_ < 2);
875    
876            my ($fld, $sf, $regex, $part) = @_;
877            warn "### regex ", ref($regex), $regex, $/ if ($debug > 2);
878    
879            my @r = rec( $fld, $sf );
880            my $v = shift @r;
881            warn "### first rec($fld,$sf) = ",dump($v),$/ if ($debug > 2);
882    
883            return '' if ( ! defined($v) || $v =~ /^\s*$/);
884    
885            my @s = split( $regex, $v );
886            warn "## split_rec_on($fld,$sf,$regex,$part) = ",dump(@s),$/ if ($debug > 1);
887            if ($part && $part > 0) {
888                    return $s[ $part - 1 ];
889            } else {
890                    return @s;
891            }
892    }
893    
894    my $hash;
895    
896    =head2 set
897    
898      set( key => 'value' );
899    
900    =cut
901    
902    sub set {
903            my ($k,$v) = @_;
904            warn "## set ( $k => ", dump($v), " )", $/ if ( $debug );
905            $hash->{$k} = $v;
906    };
907    
908    =head2 get
909    
910      get( 'key' );
911    
912    =cut
913    
914    sub get {
915            my $k = shift || return;
916            my $v = $hash->{$k};
917            warn "## get $k = ", dump( $v ), $/ if ( $debug );
918            return $v;
919    }
920    
921    =head2 count
922    
923      if ( count( @result ) == 1 ) {
924            # do something if only 1 result is there
925      }
926    
927    =cut
928    
929    sub count {
930            warn "## count ",dump(@_),$/ if ( $debug );
931            return @_ . '';
932    }
933    
934    # END
935    1;

Legend:
Removed from v.10  
changed lines
  Added in v.1118

  ViewVC Help
Powered by ViewVC 1.1.26