--- trunk2/lib/WebPAC.pm 2004/06/16 11:31:42 354 +++ trunk2/lib/WebPAC.pm 2004/06/16 16:50:30 362 @@ -4,6 +4,8 @@ use Text::Iconv; use Config::IniFiles; +use Data::Dumper; + =head1 NAME WebPAC - base class for WebPAC @@ -129,6 +131,8 @@ my $maxmfn = OpenIsis::maxRowid( $isis_db ) || 1; + $maxmfn = $self->{limit_mfn} if ($self->{limit_mfn}); + # read database for (my $mfn = 1; $mfn <= $maxmfn; $mfn++) { @@ -156,30 +160,105 @@ } # create lookup + my $rec = $self->{'data'}->{$mfn}; + $self->create_lookup($rec, @{$arg->{'lookup'}}); - foreach my $i (@{$arg->{lookup}}) { - my $rec = $self->{'data'}->{$mfn}; - if ($i->{'eval'}) { - my $eval = $self->fill_in($rec,$i->{'eval'}); - my $key = $self->fill_in($rec,$i->{'key'}); - my @val = $self->fill_in($rec,$i->{'val'}); - if ($key && @val && eval $eval) { - push @{$self->{'lookup'}->{$key}}, @val; - } - } else { - my $key = $self->fill_in($rec,$i->{'key'}); - my @val = $self->fill_in($rec,$i->{'val'}); - if ($key && @val) { - push @{$self->{'lookup'}->{$key}}, @val; - } - } - } } + $self->{'current_mfn'} = 1; + # store max mfn and return it. return $self->{'max_mfn'} = $maxmfn; } +=head2 fetch_rec + +Fetch next record from database. It will also display progress bar (once +it's implemented, that is). + + my $rec = $webpac->fetch_rec; + +=cut + +sub fetch_rec { + my $self = shift; + + my $mfn = $self->{'current_mfn'}++ || confess "it seems that you didn't load database!"; + + if ($mfn > $self->{'max_mfn'}) { + $self->{'current_mfn'} = $self->{'max_mfn'}; + return; + } + + return $self->{'data'}->{$mfn}; +} + +=head2 create_lookup + +Create lookup from record using lookup definition. + +=cut + +sub create_lookup { + my $self = shift; + + my $rec = shift || confess "need record to create lookup"; + confess("need HASH as first argument!") if ($rec !~ /HASH/o); + + foreach my $i (@_) { + if ($i->{'eval'}) { + my $eval = $self->fill_in($rec,$i->{'eval'}); + my $key = $self->fill_in($rec,$i->{'key'}); + my @val = $self->fill_in($rec,$i->{'val'}); + if ($key && @val && eval $eval) { + push @{$self->{'lookup'}->{$key}}, @val; + } + } else { + my $key = $self->fill_in($rec,$i->{'key'}); + my @val = $self->fill_in($rec,$i->{'val'}); + if ($key && @val) { + push @{$self->{'lookup'}->{$key}}, @val; + } + } + } +} + +=head2 get_data + +Returns value from record. + + $self->get_data(\$rec,$f,$sf,$i,\$found); + +Arguments are: +record reference C<$rec>, +field C<$f>, +optional subfiled C<$sf>, +index for repeatable values C<$i>. + +Optinal variable C<$found> will be incremeted if thre +is field. + +Returns value or empty string. + +=cut + +sub get_data { + my $self = shift; + + my ($rec,$f,$sf,$i,$found) = @_; + if ($$rec->{$f}) { + if ($sf && $$rec->{$f}->[$i]->{$sf}) { + $$found++ if (defined($$found)); + return $$rec->{$f}->[$i]->{$sf}; + } elsif ($$rec->{$f}->[$i]) { + $$found++ if (defined($$found)); + return $$rec->{$f}->[$i]; + } + } else { + return ''; + } +} + =head2 fill_in Workhourse of all: takes record from in-memory structure of database and @@ -209,39 +288,22 @@ my $i = shift || 0; # FIXME remove for speedup? - if ($rec !~ /HASH/o) { - confess("need HASH as first argument!"); - } + confess("need HASH as first argument!") if ($rec !~ /HASH/o); my $found = 0; - # get field with subfield - sub get_sf { - my ($found,$rec,$f,$sf,$i) = @_; - if ($$rec->{$f} && $$rec->{$f}->[$i]->{$sf}) { - $$found++; - return $$rec->{$f}->[$i]->{$sf}; - } else { - return ''; - } - } - - # get field (without subfield) - sub get_nosf { - my ($found,$rec,$f,$i) = @_; - if ($$rec->{$f} && $$rec->{$f}->[$i]) { - $$found++; - return $$rec->{$f}->[$i]; - } else { - return ''; - } - } + my $eval_code; + # remove eval{...} from beginning + $eval_code = $1 if ($format =~ s/^eval{([^}]+)}//s); # do actual replacement of placeholders - $format =~ s/v(\d+)\^(\w)/get_sf(\$found,\$rec,$1,$2,$i)/ges; - $format =~ s/v(\d+)/get_nosf(\$found,\$rec,$1,$i)/ges; + $format =~ s/v(\d+)(?:\^(\w))*/$self->get_data(\$rec,$1,$2,$i,\$found)/ges; if ($found) { + if ($eval_code) { + my $eval = $self->fill_in($rec,$eval_code,$i); + return if (! eval $eval); + } # do we have lookups? if ($format =~ /\[[^\[\]]+\]/o) { return $self->lookup($format); @@ -255,10 +317,12 @@ =head2 lookup -This function will perform lookups on format supplied to it. +Perform lookups on format supplied to it. my $txt = $self->lookup('[v900]'); +Lookups can be nested (like C<[d:[a:[v900]]]>). + =cut sub lookup { @@ -295,4 +359,64 @@ } } +=head2 parse + +Perform smart parsing of string, skipping delimiters for fields which aren't +defined. It can also eval code in format starting with C and +return output or nothing depending on eval code. + + $webpac->parse($rec,'eval{"v901^a" eq "Deskriptor"}descriptor: v250^a', $i); + +=cut + +sub parse { + my $self = shift; + + my ($rec, $format, $i) = @_; + + confess("need HASH as first argument!") if ($rec !~ /HASH/o); + + $i = 0 if (! $i); + + my @out; + + my $eval_code; + # remove eval{...} from beginning + $eval_code = $1 if ($format =~ s/^eval{([^}]+)}//s); + + my $prefix; + my $all_found=0; + +#print "## $format\n"; + while ($format =~ s/^(.*?)v(\d+)(?:\^(\w))*//s) { +#print "## [ $1 | $2 | $3 ] $format\n"; + + my $del = $1 || ''; + $prefix ||= $del if ($all_found == 0); + + my $found = 0; + my $tmp = $self->get_data(\$rec,$2,$3,$i,\$found); + + if ($found) { + push @out, $del; + push @out, $tmp; + $all_found += $found; + } + } + + return if (! $all_found); + + my $out = join('',@out) . $format; + + # add prefix if not there + $out = $prefix . $out if ($out !~ m/^\Q$prefix\E/); + + if ($eval_code) { + my $eval = $self->fill_in($rec,$eval_code,$i); + return if (! eval $eval); + } + + return $out; +} + 1;