# --*-Perl-*-- # $Id: Bibtex.pm 10 2004-11-02 22:14:09Z tandler $ # package Biblio::Bibtex; use strict; use English; =head1 package BiblioBibtex; read/write bibtex databases =cut # for debug: #use Data::Dumper; BEGIN { use vars qw($Revision $VERSION); my $major = 1; q$Revision: 10 $ =~ /: (\d+)/; my ($minor) = ($1); $VERSION = "$major." . ($minor<10 ? '0' : '') . $minor; } # superclass #use YYYY; #use vars qw(@ISA); #@ISA = qw(YYYY); # used modules use FileHandle; # module variables #use vars qw(mmmm); # bibtex type names my @type_names = qw/ article book booklet inproceedings inbook incollection inproceedings article manual masterthesis misc phdthesis proceedings techreport unpublished misc misc misc misc misc phdthesis /; my %entry_names = ( 'RepType' => 'Type', 'Annote' => 'BibNote', ### currently ... 'Type' => 'pbibType', 'Category' => 'Category', 'PaperID' => 'CiteKey', 'Identifier' => 'pbibSOCiteKey', ); # # # constructor # # sub new { my $self = shift; my $bib = { 'papers' => {}, 'shortcuts' => {}, # shortcut strings defined by style or bib 'preamble' => '', # tex-preamble }; my $class = ref($self) || $self; return bless $bib, $class; } # # # destructor # # #sub DESTROY ($) { # my $self = shift; #} # # # access methods # # sub filename { my $self = shift; return $self->{'filename'}; } # # # paper access methods # # sub papers { my $self = shift; return $self->{'papers'}; } sub paper { my ($self, $id) = @_; return $self->papers()->{$id}; } sub addPaper { my $self = shift; return $self->addPapers(@_); } sub addPapers { my $self = shift; my $id; my $p; foreach $p (@_) { $id = $p->{'PaperID'}; if( defined($id) ) { # print STDERR ($self->paper($id) ? "overwrite" : "add"), " paper $id\n"; print STDERR "overwrite paper $id\n" if( $self->paper($id) ); $self->papers()->{$id} = $p; } else { print STDERR "WARNING: no paper ID specified in @{$p}!\n" } } } # # # query paper methods # # sub getPaperIDs { # return all paper IDs my $self = shift; return keys(%{$self->papers()}); } sub queryPapers ($, $, $, $) { # query papers, look in $queryFields for $pattern my $self = shift; my ($pattern, $queryFields, $resultFields, $ignoreCase) = @_; $ignoreCase = 1 if not defined($ignoreCase); $pattern = lc($pattern) if($ignoreCase); $resultFields = $self->allPaperFields() unless defined($resultFields); $queryFields = $resultFields if not defined($queryFields); my $sql = 'SELECT ' . join(', ', map(quoteField($_), @{$resultFields})) . ' FROM "biblio" WHERE ' . join(' OR ', map('(' . quoteField($_, $ignoreCase) . " LIKE '$pattern')", @{$queryFields})); print "$sql\n"; my $papers = $self->query($sql) or die "$DBI::errstr\nSelect failed for $sql\n"; return $self->papersArrayToHash($resultFields, $papers); } sub queryPaperWithId ($, $) { my ($self, $id) = @_; my $resultFields = $self->allPaperFields(); my $sql = 'SELECT ' . join(', ', map(quoteField($_, 0), @{$resultFields})) . ' FROM "biblio" WHERE ' . quoteField("PaperID") . " = '$id'"; print "$sql\n"; my $papers = $self->query($sql) or die "$DBI::errstr\nSelect failed for $sql\n"; return $self->papersArrayToHash($resultFields, $papers)->[0]; } # # # shortcut access methods # # sub shortcuts { my $self = shift; return $self->{'shortcuts'}; } sub replaceShortcuts { # look in $text and replace all shortcuts my ($self, $text) = @_; my $shortcuts = $self->shortcuts(); my $pattern = join("|", map( /:$/ ? "$_.*" : $_, (keys(%{$shortcuts})))); #print $pattern; $text =~ s/\{($pattern)\}/ expandShortcut($shortcuts, $1) /ge; return $text; } sub expandShortcut { my ($shortcuts, $text) = @_; my @pars = split(/:/, $text); my $k = shift @pars; if( @pars ) { $k = "$k:"; } my $v = $shortcuts->{$k}; $v =~ s/%(\d)/ @pars[$1-1] /ge; return $v; # return $shortcuts->{$text}; } #sub updateShortcuts { # my ($self) = @_; # delete $self->{'shortcuts'}; #} # # # save methods # # sub write { my ($self, $filename) = @_; $filename = $self->filename() unless defined($filename); return unless defined($filename); my $fh = new FileHandle("> $filename"); if( not defined($fh) ) { print STDERR "Can't open $filename for writing.\n"; return; } print STDERR "write bibtex db to $filename\n"; $self->writeHeader($fh); $self->writePapers($fh); $fh->close(); } sub writeHeader { my ($self, $fh) = @_; print $fh "%% bibtex database, written by pbib\n\n"; } sub writePapers { my ($self, $fh) = @_; my @ids = $self->getPaperIDs(); my $type; my $paper; my $p; foreach $p (sort(@ids)) { $paper = $self->paper($p); $type = typename($paper->{'Type'}); print $fh "\@$type \{$p,\n"; my $e; foreach $e (sort(keys(%{$paper}))) { if( defined($paper->{$e}) ) { print $fh " ", $self->quoteEntry($e), " = ", $self->quoteValue($paper->{$e}), ",\n"; } } print $fh "\}\n\n"; } } sub quoteEntry { my ($self, $entry) = @_; # I guess, I'm using bibtex names!? if( exists($entry_names{$entry}) ) { $entry = $entry_names{$entry}; } return lc($entry); } sub quoteValue { my ($self, $text) = @_; # not quite advanced yet ... return "\"$text\""; } # # # class methods # # sub typename { my $type = shift; return "misc" if( not defined($type) ); return "misc" if( $type < 0 || $type >= scalar(@type_names) ); return @type_names[$type]; } 1; # # $Log: Bibtex.pm,v $ # Revision 1.2 2002/06/03 11:40:08 Diss # fixed bug in package name # # Revision 1.1 2002/03/24 18:54:25 Diss # simple package to write bibtex databases # # Revision 1.2 2002/03/22 17:31:02 Diss # small changes # # Revision 1.1 2002/03/18 11:15:47 Diss # major additions: replace [] refs, generate bibliography using [{}], ... #