]> git.donarmstrong.com Git - reference.git/blob - .svn/pristine/37/37d13632d4e1cc746576c92bb4d7055db21f8082.svn-base
Import original source of Reference 0-Reference
[reference.git] / .svn / pristine / 37 / 37d13632d4e1cc746576c92bb4d7055db21f8082.svn-base
1 # This module is part of da_reference, and is released under the terms
2 # of the GPL version 2, or any later version, at your option. See the
3 # file README and COPYING for more information.
4 # Copyright 2004 by Don Armstrong <don@donarmstrong.com>.
5 # $Id$
6
7 package Reference::Output::Bibtex;
8
9 =head1 NAME
10
11 Reference::Output::Bibtex -- Output references in BibTeX format
12
13 =head1 SYNOPSIS
14
15      print bibtex($reference);
16
17 Returns a reference formatted in bibtex format.
18
19 =head1 DESCRIPTION
20
21 Knows how to handle the reference-> bibtex field mapping for many
22 reference types, but overridden types may need to provide their own
23 mapping.
24
25
26 =head1 BUGS
27
28 None known.
29
30 =cut
31
32
33 use strict;
34 use vars qw($REVISION $DEBUG @EXPORT @EXPORT_OK %EXPORT_TAGS);
35
36 use base qw(Exporter);
37
38 BEGIN{
39      ($REVISION) = q$LastChangedRevision$ =~ /\$LastChangedRevision:\s+([^\s+])/;
40      $DEBUG = 0 unless defined $DEBUG;
41
42      @EXPORT = qw(bibtex);
43      @EXPORT_OK = qw();
44      %EXPORT_TAGS = (output => [qw(bibtex)],
45                     );
46      Exporter::export_ok_tags(qw(output));
47      $EXPORT_TAGS{all} = [@EXPORT_OK];
48
49 }
50
51 # Assigned and discussed at the end of this file
52 my %bibtex_mapping;
53
54 use Carp;
55 use Params::Validate qw(:types validate_with);
56 use Text::Wrap;
57
58
59 =head2 bibtex
60
61      print bibtex $reference;
62      %bibtex = bibtex $reference;
63      print bibtex($reference,mapping=>{...})
64
65 In scalar context, returns a formatted bibtex entry, suitable for
66 printing. In list context, returns a hash of key, value pairs which
67 can be used to print a formatted bibtex entry.
68
69 You can also pass an optional mapping to be used for making the bibtex
70 entry. See B<bibtex_mapping> for the details.
71
72 The mappings are obeyed in the following order, the first taking
73 precedence over the last.
74
75 =over
76
77 =item Passed mapping
78
79 =item Object's bibtex_mapping
80
81 =item Internal bibtex_mapping (%Reference::Output::Bibtex::bibtex_mapping)
82
83 =back
84
85 Returns a SCALAR bibtex reference in scalar context, a HASH bibtex
86 reference in list context
87
88 =cut
89
90 sub bibtex{
91      my $reference = shift;
92
93      # Parse options if any
94      my %param = validate_with(params => \@_,
95                                spec   => {mapping => {type     => HASHREF,
96                                                       optional => 1,
97                                                      },
98                                          },
99                               );
100
101      my $mapping = undef;
102
103      # Use our mapping by default if it exists
104      $mapping = $bibtex_mapping{lc($reference->{type})} if exists $bibtex_mapping{lc($reference->{type})};
105      # Override that with the module's mapping
106      $mapping = $reference->{bibtex_mapping} if exists $reference->{bibtex_mapping};
107      # Finally, override everything with passed mapping
108      $mapping = $param{mapping} if exists $param{mapping};
109
110      if (not defined $mapping) {
111           carp "This reference type doesn't support bibtex output.";
112           return undef;
113      }
114
115      my %bibtex_entry;
116      foreach my $bibtex_field (keys %{$mapping->{mapping}}) {
117           my $params = [];
118           if (ref $bibtex_field) {
119                $params = $$bibtex_field{params} if exists $$bibtex_field{params};
120                $bibtex_field = $$bibtex_field{field};
121           }
122           my $function = $reference->can($mapping->{mapping}->{$bibtex_field});
123           next unless $function;
124           $bibtex_entry{$bibtex_field} = &{$function}($reference,output=>'bibtex',@$params);
125           # dereference the entries if necessesary.
126           next unless wantarray;
127           # Make new copies of the entries if necessary so we can
128           # mogrify to our hearts content.
129           if (ref($bibtex_entry{$bibtex_field}) eq 'HASH') {
130                $bibtex_entry{$bibtex_field} = {%{$bibtex_entry{$bibtex_field}}};
131           }
132           elsif (ref($bibtex_entry{$bibtex_field}) eq 'ARRAY') {
133                $bibtex_entry{$bibtex_field} = [@{$bibtex_entry{$bibtex_field}}];
134           }
135      }
136      # Return the entries in hash form if desired.
137      return %bibtex_entry if wantarray;
138      # Ok, stich the bibtex entry together...
139      my $bibtex_entry;
140      $bibtex_entry = '@'.$mapping->{order}[0].'{'.$bibtex_entry{$mapping->{order}[0]}.",\n";
141      foreach my $bibtex_field (@{$mapping->{order}}[1..$#{$mapping->{order}}]) {
142           next unless defined $bibtex_entry{$bibtex_field};
143           if (ref $bibtex_entry{$bibtex_field} eq 'ARRAY') {
144                if (ref $mapping->{mapping}{$bibtex_field}) {
145                     if (exists $mapping->{mapping}{$bibtex_field}{code}) {
146                          local $_ = $bibtex_entry{$bibtex_field};
147                          eval $mapping->{mapping}{$bibtex_field}{code};
148                          carp "Error while executing code to assemble bibtex entry: $@" if $@;
149                     }
150                     elsif (exists $mapping->{mapping}{$bibtex_field}{join}) {
151                          $bibtex_entry{$bibtex_field} = join($mapping->{mapping}{$bibtex_field}{join},
152                                                              @{$bibtex_entry{$bibtex_field}});
153                     }
154                     else {
155                          carp "$bibtex_field is an ARRAYREF, joining using commas";
156                          $bibtex_entry{$bibtex_field} = join(', ', @{$bibtex_entry{$bibtex_field}});
157                     }
158                }
159                else {
160                     carp "$bibtex_field is an ARRAYREF, joining using commas";
161                     $bibtex_entry{$bibtex_field} = join(', ', @{$bibtex_entry{$bibtex_field}});
162                }
163           }
164           my $entry = $bibtex_entry{$bibtex_field};
165           $entry =~ s/%/\\%/g;
166           $bibtex_entry .= wrap(' ' x 4,' ' x 8 . ' ' x length($bibtex_field),"$bibtex_field = {".$entry."},\n");
167      }
168      $bibtex_entry .= "}\n";
169      return $bibtex_entry;
170 }
171
172 =head2 bibtex_mapping
173
174       $Reference::Output::Bibtex::bibtex_mapping{Article} =
175         {mapping => {author   => {field  => 'author',
176                                   join   => ' and ',
177                                   params => [],
178                                  },
179                      volume   => 'volume',
180                      Articlce => 'name',
181                      foo      => 'bar',
182                     },
183          order => [qw(name author volume foo)],
184         };
185
186 This variable holds the mapping to bibtex output.
187
188 Each type of reference has its own keys. Currently the following types
189 are supported by the Bibtex output method:
190
191 =over
192
193 =item article
194
195 =item collection
196
197 =item book
198
199 =back
200
201 If you wish to add support for your own custom reference type, you
202 merely need to add a bibtex_mapping element to your class's hashref,
203 or add to this variable. [Preferbly the former, as the latter should
204 only be used by the end user.]
205
206 The mapping key in the reference type hashref is a hashref containing
207 key value pairs according to the following metric:
208
209 =over
210
211 =item If the mapping key value is not a reference, the value is used
212 as the name function to call via C<$reference->field>. [In the example
213 above, the volume mapping is built by a call to
214 C<$reference->volume>].
215
216 =item If the mapping key value is a hashref, the hashref contains two
217 keys. The C<field> key contains the name of the function to call. The
218 C<params> key contains the parameters
219
220 =back
221
222 The order key in the reference type hashref is an arrayref which
223 defines the order in which keys are listed in the BibTeX
224 output. Values in the arrayref should be the keys of the mapping
225 hashref. [The first value listed is the type of reference/reference
226 name pair.]
227
228
229 =cut
230
231
232 %bibtex_mapping =
233 (article => {mapping => {Article  => 'name',
234                          author   => 'author',
235                          title    => 'title',
236                          journal  => 'journal',
237                          year     => 'year',
238                          key      => 'keywords',
239                          volume   => 'volume',
240                          number   => 'number',
241                          pages    => 'pages',
242                          month    => 'month',
243                          abstract => 'abstract',
244                          pmid     => 'pmid',
245                          mlid     => 'medline_id',
246                          doi      => 'doi',
247                          html     => 'html',
248                          pdf      => 'pdf',
249                         },
250              order   => [qw(Article author title journal
251                             year key volume number pages
252                             month abstract pmid mlid doi
253                             html pdf),
254                         ],
255             },
256  book    => {mapping => {Book     => 'name',
257                          author   => 'author',
258                          title    => 'title',
259                          year     => 'year',
260                          key      => 'keywords',
261                          volume   => 'volume',
262                          number   => 'number',
263                          pages    => 'pages',
264                          month    => 'month',
265                          abstract => 'abstract',
266                          doi      => 'doi',
267                          # html   => 'html',
268                          # pdf    => 'pdf',
269                         },
270              order   => [qw(Article author title journal
271                             year key volume number pages
272                             month abstract doi html pdf),
273                         ],
274             },
275 );
276
277
278
279 1;
280
281
282 __END__
283
284
285
286
287
288