File Coverage

blib/lib/Astro/Bibcode.pm
Criterion Covered Total %
statement 178 204 87.2
branch 64 104 61.5
condition 7 12 58.3
subroutine 27 29 93.1
pod 14 14 100.0
total 290 363 79.8


line stmt bran cond sub pod time code
1             package Astro::Bibcode;
2              
3             =head1 NAME
4              
5             Astro::Bibcode - Parse standardised astronomical journal bibcode
6              
7             =head1 SYNOPSIS
8              
9             use Astro::Bibcode;
10             $bib = new Astro::Bibcode( '2002MNRAS.336...14J' );
11              
12             print $bib->journal(),"\n";
13             print $bib->volume(),"\n";
14             print $bib->year(),"\n";
15              
16             =head1 DESCRIPTION
17              
18             This module parses a standardised astronomical journal bibcode (see
19             references at end of this documentation) and allows the individual
20             parts to be extracted.
21              
22             =cut
23              
24 1     1   2976 use 5.006;
  1         6  
  1         55  
25 1     1   6 use strict;
  1         3  
  1         44  
26 1     1   14 use warnings;
  1         2  
  1         32  
27 1     1   5 use warnings::register;
  1         1  
  1         124  
28 1     1   5 use Carp;
  1         1  
  1         75  
29              
30 1     1   4 use vars qw/ $VERSION /;
  1         1  
  1         2295  
31             $VERSION = sprintf("%d.%03d", q$Revision: 0.3 $ =~ /(\d+)\.(\d+)/);
32              
33             # Some lookup tables
34              
35             # Standard Classification codes
36             my %CLASS = (
37             B => 'textbook',
38             C => 'catalog',
39             M => 'digited version',
40             P => 'preprint',
41             R => 'report or conference proceedings',
42             T => 'thesis',
43             U => 'unpublished',
44             );
45              
46             # Note that ADS seems to use the following classifications:
47             # conf Conference
48             # book Book
49             # work Workshop
50             # symp Symposium
51             # rept Reports
52             # meet Meeting
53             my %CLASS_ADS = (
54             proc => 'conference proceeding', # Alias for "conf"
55             book => 'book',
56             work => 'workshop',
57             conf => 'conference proceeding',
58             symp => 'symposium',
59             rept => 'report',
60             meet => 'meeting',
61             );
62              
63             # These are populated dynamically as required
64              
65             # Normal standardised Journal lookup
66             my %JOURNALS;
67              
68             # ADS conference proceedings lookup
69             my %CONF_ADS;
70              
71              
72             =head1 METHODS
73              
74             =head2 Constructor
75              
76             =over 4
77              
78             =item B
79              
80             Create a new C object. This constructor
81             can be called in a number of ways.
82              
83             If a single argument is provided it is assumed to be a bibcode.
84             This code will be parsed, if the parse fails the object will not
85             be created.
86              
87             $bib = new Astro::Bibcode( '1995MNRAS.276.1024J' );
88              
89             THE REST OF THIS SECTION IS PROPOSED INTERFACE AND IS NOT IMPLEMENTED
90              
91             If it is called without arguments an empty object will be
92             created. Further calls to the C method or the individual
93             components will be required to configure the object.
94              
95             $bib = new Astro::Bibcode;
96              
97              
98             If a series of hash arguments are provided, the object will
99             be configured by calling the individual accessors in turn.
100              
101             $bib = new Astro::Bibcode( journalcode => 'ApJ',
102             year => 2002,
103             );
104              
105             NOTE THAT BIBCODE CREATION IS NOT YET IMPLEMENTED
106              
107             =cut
108              
109             sub new {
110 1     1 1 337 my $proto = shift;
111 1   33     9 my $class = ref($proto) || $proto;
112              
113             # Create object
114 1         6 my $bib = bless {
115             BIBCODE => undef,
116             YEAR => undef,
117             JOURNALCODE => undef,
118             CLASSFLAG => undef,
119             VOLUME => undef,
120             MISC => undef,
121             PAGE => undef,
122             INITIAL => undef,
123             CONFCODE => undef,
124             }, $class;
125              
126 1 50       5 if (@_) {
127             # if we have one code it's a bibcode
128 0 0       0 if (scalar(@_) == 1) {
129 0         0 my $retval = $bib->bibcode( $_[0] );
130              
131             # if bibcode method returned undef (error in parse)
132             # set the object to undef to indicate error
133 0 0       0 $bib = undef unless defined $retval;
134             } else {
135 0         0 my %args = @_;
136              
137             # loop over known important methods
138 0         0 for my $k (qw| year journalcode classflag volume page initial misc |) {
139 0 0       0 $bib->$k($args{$k}) if exists $args{$k};
140             }
141              
142             }
143              
144             }
145              
146 1         3 return $bib;
147             }
148              
149             =back
150              
151             =head2 Accessor Methods
152              
153             =over 4
154              
155             =item B
156              
157             Returns the bibcode associated with this object. It will be generated
158             from the other object attributes if undefined (which it will be after
159             something in the object has changed).
160              
161             $bib->bibcode( '1998adass...7..216J' );
162             $code = $bib->bibcode;
163              
164             Can return undef if the bibcode did not pass verification (see
165             C).
166              
167             =cut
168              
169             sub bibcode {
170 35     35 1 389 my $self = shift;
171 35 100       64 if (@_) {
172 5         8 my $code = shift;
173             # Verify and store
174 5         12 my %parts = $self->verify_bibcode( $code );
175              
176             # if we did not get any result; store undef and return
177 5 50       549 if (!keys %parts) {
178 0         0 $self->{BIBCODE} = undef;
179 0         0 return;
180             }
181              
182             # We did get some data. Configure the rest of the object
183             # to match. Note that we do not go through the accessors
184             # since they may well be configured to clear the bibcode
185             # if they are modified and we would end up with recursion
186 5         12 $self->{YEAR} = $parts{year};
187 5         7 $self->{VOLUME} = $parts{volume};
188 5         9 $self->{JOURNALCODE} = $parts{journalcode};
189 5         6 $self->{CLASSFLAG} = $parts{classflag};
190 5         6 $self->{MISC} = $parts{misc};
191 5         6 $self->{PAGE} = $parts{page};
192 5         8 $self->{INITIAL} = $parts{initial};
193              
194 5         10 $self->{BIBCODE} = $self->verify_bibcode( $code );
195              
196 5         17 return $self->{BIBCODE};
197             } else {
198             # if no bibcode is defined, attempt to generate one from the object
199 30 50       58 if (! defined $self->{BIBCODE} ) {
200 0         0 $self->_construct_bibcode();
201             }
202             }
203 30         51 return $self->{BIBCODE};
204             }
205              
206             =item B
207              
208             Year of publication.
209              
210             $year = $bib->year;
211              
212             =cut
213              
214             sub year {
215 15     15 1 1520 my $self = shift;
216 15         40 return $self->{YEAR};
217             }
218              
219             =item B
220              
221             The Journal code associated with this bib code.
222              
223             For the current list of journal codes see:
224              
225             http://simbad.u-strasbg.fr/simjnl.pl
226              
227             See the C method in order to translate this code to a full
228             journal name.
229              
230             $jcode = $bib->journalcode;
231              
232             =cut
233              
234             sub journalcode {
235 25     25 1 1341 my $self = shift;
236 25         62 return $self->{JOURNALCODE};
237             }
238              
239              
240             =item B
241              
242             Classification flag of this bib code.
243             Current allowed values are:
244              
245             B textbook
246             C catalog
247             M digited version
248             P preprint
249             R report or conference proceedings
250             T thesis
251             U unpublished
252              
253             and also from ADS:
254              
255             book => 'book'
256             work => 'workshop'
257             conf => 'conference proceeding'
258             symp => 'symposium'
259             rept => 'report'
260             meet => 'meeting'
261              
262             Note that a null string is used to indicate a periodical.
263              
264             $code = $bib->classflag;
265              
266             See the C method for the translation.
267              
268             =cut
269              
270             sub classflag {
271 15     15 1 17 my $self = shift;
272 15         36 return $self->{CLASSFLAG};
273             }
274              
275             =item B
276              
277             Volume number.
278              
279             =cut
280              
281             sub volume {
282 9     9 1 580 my $self = shift;
283 9         22 return $self->{VOLUME};
284             }
285              
286             =item B
287              
288             Value of the miscellaneous field "M" used to remove ambiguity.
289              
290             =cut
291              
292             sub misc {
293 0     0 1 0 my $self = shift;
294 0         0 return $self->{MISC};
295             }
296              
297             =item B
298              
299             Page number.
300              
301             =cut
302              
303             sub page {
304 11     11 1 746 my $self = shift;
305 11         27 return $self->{PAGE};
306             }
307              
308             =item B
309              
310             Either the first initial of the first author's last name,
311             or ":" for no author. Also can be "%" to indicate that some
312             of the other fields may be invalid.
313              
314             =cut
315              
316             sub initial {
317 8     8 1 1145 my $self = shift;
318 8         25 return $self->{INITIAL};
319             }
320              
321             =back
322              
323             =head2 General Methods
324              
325             =over 4
326              
327             =item B
328              
329             Retrieve the full journal name.
330              
331             $journal = $bib->journal;
332              
333             Returns the code if the code can not be translated.
334              
335             Does try to recognize ADS conference codes.
336              
337             =cut
338              
339             sub journal {
340 15     15 1 601 my $self = shift;
341 15         22 my $jcode = $self->journalcode; # Journal lookup
342 15         24 my $confcode = $self->confcode; # Conference lookup
343              
344             # first time through, populate the journal lookup
345 15 50       27 $self->_populate_journals() unless keys %JOURNALS;
346              
347             # Is it in the journal list?
348 15 100       31 if (exists $JOURNALS{$jcode}) {
    50          
349             # Straight journal lookup
350 10         21 return $JOURNALS{$jcode};
351             } elsif (defined $confcode) {
352             # It is a conference
353 5         15 return $CONF_ADS{$confcode};
354             } else {
355             # do not know
356 0         0 return $jcode;
357             }
358             }
359              
360             =item B
361              
362             Retrieve the full name associated with the classification flag.
363              
364             $class = $bib->class;
365              
366             Returns undef if no name can be translated.
367              
368             =cut
369              
370             sub class {
371 15     15 1 1322 my $self = shift;
372 15         31 my $flag = $self->classflag;
373              
374             # in some cases a "periodical" style bibcode can actually be associated
375             # with a conference. Check this by looking to see if confcode is true
376 15         26 my $confcode = $self->confcode;
377              
378             # if confcode is defined but flag is not, we are really a recurring "conf"
379 15 100 100     60 return "recurring conference" if defined $confcode && !$flag;
380              
381             # Sometimes a blank classflag simply means that ADS is lying...
382             # rather than it being a "periodical"
383 12 100       24 if (!length($flag)) {
384 6         15 my $journal = $self->journal;
385 6 100       17 if ($journal =~ /thesi/i) {
386             # it is really a thesis
387 3         16 return "thesis";
388             } else {
389             # no hint - use periodical
390 3         11 return "periodical";
391             }
392             }
393              
394 6 50       21 if (exists $CLASS{$flag}) {
    50          
395 0         0 return $CLASS{$flag};
396             } elsif (exists $CLASS_ADS{$flag}) {
397 6         25 return $CLASS_ADS{$flag};
398             }
399 0         0 return undef;
400             }
401              
402             =item B
403              
404             Returns the ADS conference code associated with this bibcode.
405             Returns undef if this bibcode is not associated with a conference.
406              
407             $confcode = $bib->confcode;
408              
409             In some cases (eg 2000immm.proc...77G), a "proc" classification
410             is used when the ADS standard seems to imply "conf" instead.
411             This is taken into account when returning the confcode.
412              
413             =cut
414              
415             sub confcode {
416 30     30 1 28 my $self = shift;
417 30         49 my $bibcode = $self->bibcode(); # For ADS conference proceedings translation
418              
419             # Force read of DATA segment
420 30 100       63 $self->_populate_journals unless keys %CONF_ADS;
421              
422 30         23 my $confcode;
423 30 100       113 if (exists $CONF_ADS{substr($bibcode,0,13)}) {
    50          
    100          
424             # Now try an exact ADS match with the first 13 characters
425             # This gives us the journal code
426 10         18 $confcode = substr($bibcode,0,13);
427              
428             } elsif (exists $CONF_ADS{substr($bibcode,4,9)}) {
429             # try ADS conference lookup without the year prefix
430 0         0 $confcode = substr($bibcode,4,9);
431              
432             } elsif ($bibcode =~ /proc/) {
433             # if we have a .proc see whether .conf matches anywhere
434 4         5 my $c = $bibcode;
435 4         10 $c =~ s/proc/conf/;
436 4 50       12 if (exists $CONF_ADS{substr($c,0,13)}) {
437 4         8 $confcode = substr($c,0,13);
438             }
439             }
440              
441 30         49 return $confcode;
442             }
443              
444             =item B
445              
446             Return a multi-line summary string describing the bibcode status.
447              
448             $text = $bib->summary;
449              
450             =cut
451              
452             sub summary {
453 5     5 1 1434 my $self = shift;
454 5         8 my $str = '';
455              
456 5         14 my @keys = qw/ class journal year volume page /;
457              
458             # Find the max length of the key
459 5         4 my $max = 0;
460 5         8 for (@keys) {
461 25 100       49 $max = length($_) if length($_) > $max;
462             }
463              
464 5         7 for my $m (@keys) {
465 25         45 my $data = $self->$m();
466 25         80 $str .= sprintf("%-".$max."s : %s\n", ucfirst($m), $data);
467             }
468 5         17 return $str;
469             }
470              
471             =item B
472              
473             Given a bibcode, return false if the bibcode does not seem to be
474             valid (e.g. it is the wrong lenght, first 4 characters are not digits),
475             returns the bibcode in scalar context.
476              
477             $ok = $bib->verify_bibcode( '1999adass...8...11E' );
478              
479             In list context returns a hash consisting of the constituent (untranslated)
480             parts of the bib code.
481              
482             %parts = $bib->verify_bibcode( '1998SPIE.3357..548J' );
483              
484             Since ADS is prone to replacing & with & in Journal codes due to
485             HTML transport, this routine will reverse this.
486              
487             Note that in some special cases a bibcode can be specified such
488             that it is known not to match all the rules (last character is a '%').
489             In such cases only the length of the bicode is checked.
490              
491             =cut
492              
493             sub verify_bibcode {
494 10     10 1 10 my $self = shift;
495 10         10 my $bibcode = shift;
496 10 50       18 return unless defined $bibcode;
497              
498             # Fix HTML-ification
499 10         16 $bibcode =~ s/&/&/;
500              
501             # Check length
502 10 50       19 return unless length($bibcode) == 19;
503              
504             # Rather than one enormous pattern match, split the string
505             # into fixed length chunks
506 10         15 my $yyyy = substr($bibcode,0,4);
507 10         13 my $jjjjj= substr($bibcode,4,5);
508 10         11 my $vvvv = substr($bibcode,9,4);
509 10         11 my $m = substr($bibcode,13,1);
510 10         11 my $pppp = substr($bibcode,14,4);
511 10         10 my $a = substr($bibcode,18,1);
512              
513             # Verify each component and store in hash
514 10         12 my %parts;
515              
516             # Note that ADS conference proceeding extensions are still valid bibcodes
517 10         16 $parts{year} = $self->_verify_year( $yyyy );
518 10         22 $parts{journalcode} = $self->_verify_journalcode( $jjjjj );
519              
520 10         19 my ($class, $vol) = $self->_verify_volume( $vvvv );
521 10         17 $parts{volume} = $vol;
522 10         15 $parts{classflag} = $class;
523              
524 10         18 $parts{misc} = $self->_verify_misc( $m );
525 10         20 $parts{page} = $self->_verify_page( $pppp );
526 10         17 $parts{initial} = $self->_verify_initial( $a );
527              
528              
529             # Ordinarily we would return if any of the values in the hash
530             # are undef. There is a special case if $a is "%" since this
531             # indicates that some of them may not match. In this case
532             # we do what we can.
533              
534 10 50       18 if ($a ne "%") {
535 10         19 for my $v (values %parts) {
536 70 50       108 return unless defined $v;
537             }
538             }
539              
540             # Return the answer
541 10 100       17 if (!wantarray) {
542 5         18 return $bibcode;
543             } else {
544 5         35 return %parts;
545             }
546             }
547              
548             =back
549              
550             =begin PRIVATE__METHODS
551              
552             Internal routines which may change and should not be used in external
553             classes.
554              
555             These are methods, although there is no expectation that subclasses
556             will be required.
557              
558             =over 4
559              
560             =item B<_construct_bibcode>
561              
562             =cut
563              
564             sub _construct_bibcode {
565 0     0   0 my $self = shift;
566              
567 0         0 Carp::confess "Bibcode construction is not yet implemented. It may be hard.";
568              
569             }
570              
571             =item B<_verify_year>
572              
573             Check the year looks okay, return false if it does not, the year
574             if it looks okay.
575              
576             =cut
577              
578             sub _verify_year {
579 10     10   10 my $self = shift;
580 10         11 my $year = shift;
581 10 50       37 return (($year =~ /^\d{4}$/) ? $year : () );
582             }
583              
584             =item B<_verify_journalcode>
585              
586             Check that the journal code looks okay. Returns the code if okay,
587             false otherwise.
588              
589             Does not check to see if the journal code can be translated.
590              
591             Trailing dots are removed from the input string.
592              
593             =cut
594              
595             sub _verify_journalcode {
596 10     10   12 my $self = shift;
597 10         12 my $jcode = shift;
598              
599             # Clean the string
600 10         16 $jcode = _clean_string($jcode, 'L');
601              
602             # Just make sure we have A-Z and &
603 10 50       41 return ( ( $jcode =~ /^[A-Za-z&]+$/) ? $jcode : () );
604             }
605              
606             =item B<_verify_volume>
607              
608             Check that the volume and class are okay.
609              
610             In scalar context returns the verified string (with leading
611             dots removed).
612              
613             ($class, $volume) = $bib->_verify_volume( $v );
614             $v = $bib->_verify_volume($v);
615              
616             In list context returns two values. First is the classification
617             flag (blank string for a periodical), second is the volume number
618             (leasing zeroes removed).
619              
620             Note that since ADS does not seem to use the classification
621             code as presented in the reference documentation, this is a bit
622             of a hack (eg a Thesis would be expected to have class = T but
623             instead simply uses PhDT in the journal name and not the university).
624              
625             This means that a blank volume and class are okay and the
626             class needs to be hacked in higher up.
627              
628             =cut
629              
630             sub _verify_volume {
631 10     10   11 my $self = shift;
632 10         10 my $vol = shift;
633              
634             # Second character is important so we need to get that before
635             # cleaning
636 10         14 my $second = substr($vol,1,1);
637              
638              
639             # Clean the string
640 10         13 $vol = _clean_string( $vol, 'R' );
641              
642             # empty is okay [need to guess later on]
643 10 50       22 return (wantarray ? ('', '') : $vol) unless $vol;
    100          
644              
645             # Get standard classification codes
646 8         24 my $classes = join( "", keys %CLASS);
647              
648             # Get adass codes and form a pattern match string
649 8         24 my $adsmatch = join("|",keys %CLASS_ADS);
650              
651             # Either we are all numbers
652 8 100       171 if ($vol =~ /^\d+$/) {
    50          
    50          
    50          
653             # periodical. Test calling context
654 4 50       11 return (wantarray ? ('',$vol) : $vol );
655             } elsif ($vol =~ /([$classes])(\d\d)$/) {
656             # We are a classification other than a published journal
657             # with multi-volume
658 0         0 my $c = $1;
659 0         0 my $num = $2;
660             # strip leading zero
661 0         0 $num =~ s/^0+//g;
662              
663             # return the result (checking for context)
664 0 0       0 return (wantarray ? ($c, $num) : $vol);
665              
666             } elsif ($second =~ /^([$classes])$/) {
667 0         0 my $class = $1;
668 0 0       0 return (wantarray ? ($class, '') : $vol );
669             } elsif ($vol =~ /^($adsmatch)$/) {
670 4 50       21 return (wantarray ? ($1, '') : $vol);
671             }
672             # bad code
673 0         0 return;
674             }
675              
676             =item B<_verify_misc>
677              
678             Verify the misc field which is used to break ambiguity.
679              
680             L letter section in periodical
681             p pink MNRAS pages
682             a-z issue number in same volume
683             A-K issue designations within same volume
684             Q-Z articles on same page
685             A-Z For theses, first initial of author
686             E "ephemeral". These are temporary bibcodes
687             submitted prior to publication [ADS-specific]
688              
689             Fundamentally, any letter matches or a ".".
690              
691             To be truly accurate the verification requires the
692             journal name and classification flag.
693              
694             =cut
695              
696             sub _verify_misc {
697 10     10   9 my $self = shift;
698 10         8 my $m = shift;
699              
700             # a . is fine
701 10 50       51 return "" if $m eq ".";
702              
703             # Now pattern match
704 0 0       0 return ( ($m =~ /^[A-Za-z]$/) ? $m : ());
705             }
706              
707              
708             =item B<_verify_page>
709              
710             Verifies the page number. Returns the page number with leading "."
711             removed. Returns false on error.
712              
713             =cut
714              
715             sub _verify_page {
716 10     10   9 my $self = shift;
717 10         13 my $page = shift;
718 10         14 $page = _clean_string( $page, 'R');
719 10 50       39 return (($page =~ /^\d+$/) ? $page : () );
720             }
721              
722             =item B<_verify_initial>
723              
724             Check that the initial is valid. In addition to letters,
725             ':' indicates that there is no author, '%' indicates that
726             the code may be dodgy.
727              
728             =cut
729              
730             sub _verify_initial {
731 10     10   10 my $self = shift;
732 10         10 my $i = shift;
733 10 50       32 return ( ($i =~ /^[A-Za-z:%]$/) ? $i : () );
734             }
735              
736             =item B<_populate_journals>
737              
738             Populate the internal journal code to journal name lookup table.
739              
740             Also populates the ADS conference proceedings table.
741              
742             =cut
743              
744             sub _populate_journals {
745 1     1   2 my $self = shift;
746              
747             # Buffer for concatenating journals that go over a single line
748 1         1 my $jbuff = '';
749              
750             # Current journal code in "scope"
751 1         2 my $current;
752              
753             # Read from data handle
754 1         6 while (my $line = ) {
755 1238 50       2097 next if $line =~ /^\#/;
756              
757             # This means we are at the end of the journals
758 1238 100       1835 last if $line =~ /^=cut/;
759              
760             # Code is first 7 characters
761 1237         1326 my $code = substr($line,0,7);
762 1237         2780 $code =~ s/\s+$//;
763              
764             # Get the translation. Remove newline. remove trailing and leading space
765 1237         1668 my $fullname = substr($line,7);
766 1237         1324 chomp($fullname);
767 1237         2492 $fullname =~ s/^\s+//;
768 1237         2626 $fullname =~ s/\s+$//;
769              
770             # Do we have a code? If yes, clear previous buffer
771 1237 100       2075 if (length($code)) {
772             # Update the new current value
773 918         925 my $old = $current;
774 918         851 $current = $code;
775              
776             # if we have a previous entry, store it and reset the buffers
777 918 100 66     3776 $JOURNALS{$old} = $jbuff if ($old && $jbuff);
778 918         1003 $jbuff = '';
779              
780             }
781              
782             # Append to buffer, making sure we have a space if concatenating
783 1237 100       1760 $jbuff .= " " if $jbuff;
784 1237         3581 $jbuff .= $fullname;
785              
786             }
787              
788             # Leftover
789 1 50 33     9 $JOURNALS{$current} = $jbuff if ($current && $jbuff);
790              
791             # Now try to populate the ADS lookup (if we have it in DATA
792             # ADS bibcode is first 13 characters
793 1         4 while (my $line = ) {
794 4226 50       6940 next if $line =~ /^\#/;
795 4226 100       6224 next if length($line) < 14;
796 4225         4416 my $bcode = substr($line,0,13);
797 4225         5713 my $conf = substr($line,14);
798 4225         3743 chomp($conf);
799 4225         9806 $conf =~ s/^\s+//;
800 4225         16467 $CONF_ADS{$bcode} = $conf;
801             }
802              
803 1         6 return;
804             }
805              
806             =back
807              
808             =end PRIVATE__METHODS
809              
810             =cut
811              
812             # Really really private helper subs
813              
814             # This subroutine cleans the supplied bibcode substring
815             # Remove "spaces" from the string (ie ".")
816              
817             # Arg 1: The substring
818             # Arg 2: Justification for the string "L" or "R"
819              
820             sub _clean_string {
821 30     30   30 my $str = shift;
822 30         31 my $j = uc(shift);
823              
824 30 100       61 if ($j eq 'L') {
    50          
825 10         30 $str =~ s/\.+$//g;
826             } elsif ($j eq 'R') {
827 20         38 $str =~ s/^\.+//g;
828             } else {
829 0         0 croak "Internal error: Justification string was '$j' not L or R";
830             }
831 30         52 return $str;
832             }
833              
834              
835              
836             =head1 REFERENCES
837              
838             Details on the bibcode standard can be obtained from
839              
840             http://cdsweb.u-strasbg.fr/simbad/refcode.html
841              
842             A complete description of the reference coding has been published as a
843             chapter of the book "Information & On-Line Data in Astronomy", 1995,
844             D. Egret and M. A. Albrecht (Eds), Kluwer Acad. Publ.
845              
846             ADS seems to use non-standard bibcodes for meetings and conferences:
847              
848             http://adsabs.harvard.edu/abs_doc/conferences.html
849              
850             ADS Journal codes are here:
851              
852             http://adsabs.harvard.edu/abs_doc/all_journals.html
853              
854             but are not currently used.
855              
856             =head1 NOTES
857              
858             Currently the lookup tables for the journal translation and ADS conference
859             proceedings are embedded in the module. There is no facility for triggering
860             a remote update from the referenced web sites or for easily updating a
861             configuration file as new codes are issued. This will probably change in
862             future releases.
863              
864             =head1 AUTHOR
865              
866             Tim Jenness Etjenness@cpan.orgE
867              
868             =head1 COPYRIGHT
869              
870             Copyright (C) 2004 Tim Jenness and the Particle Physics and
871             Astronomy Research Council.
872              
873             This program is free software; you can redistribute it and/or modify it under
874             the terms of the GNU General Public License as published by the Free Software
875             Foundation; either version 2 of the License, or (at your option) any later
876             version.
877              
878             This program is distributed in the hope that it will be useful,but WITHOUT ANY
879             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
880             PARTICULAR PURPOSE. See the GNU General Public License for more details.
881              
882             You should have received a copy of the GNU General Public License along with
883             this program; if not, write to the Free Software Foundation, Inc., 59 Temple
884             Place,Suite 330, Boston, MA 02111-1307, USA
885              
886             =head1 SEE ALSO
887              
888             L
889              
890             =cut
891              
892             1;
893              
894             # Note that some entries have been added that were not found on
895             # the CDS list but were found in some papers on ADS
896             #
897             # OLEB
898             #
899             __DATA__