# This module is part of , and is released # under the terms of the GPL version 2, or any later version. See the # file README and COPYING for more information. # Copyright 2003 by Don Armstrong . # $Id$ package Reference; =head1 NAME Reference -- Reference superclass =head1 SYNOPSIS =head1 DESCRIPTION =head1 BUGS None known. =cut use strict; use vars qw($VERSION $REVISION $DEBUG); use Carp; BEGIN{ $REVISION = '0.01'; ($REVISION) = q$LastChangedRevision$ =~ /\$LastChangedRevision:\s+([^\s+])/; $DEBUG = 0 unless defined $DEBUG; } our $AUTOLOAD; =head2 new my $reference = new Reference; Creates a new reference object =cut sub new{ my $class = shift; $class = ref $class if ref $class; my $self = {}; bless $self, $class; $self->_init; return $self; } =head2 ref_fields @$self->{ref_fields}{$self->ref_fields} = (1) x $self->ref_fields; Returns the fields that this reference knows how to deal with (or that should be dealt with using ref_fields). This default implementation returns an empty list, and as such should be overriden by all Reference::Type subclasses. =cut sub ref_fields{ my $self = shift; return (); } =head2 ref_field $reference->ref_field('author',['John Q. Smith', 'Randal P. Swag']); Sets the reference field to the passed value (if any) and returns the new value. This function is called through AUTOLOAD using the $reference->field() syntax. Returns the new setting of passed field. Scalar fieldname, and an optional scalar, arrayref, or hashref to set reference field. =cut sub ref_field($$;$){ my ($self,$field_name,$field_value) = @_; if ($self->{ref_fields}->{lc($field_name)}) { # Check to make sure that only 3 arguments are passed to # avoid triggering on the Params::Variable style of calling. # XXX We should check explicitly for this. [See Author.pm] if (defined $field_value and scalar(@_) == 3) { $self->{reference}->{lc($field_name)} = $field_value; } return $self->{reference}->{lc($field_name)}; } carp "Invalid field name $field_name"; } =head2 AUTOLOAD Dispatches calls to $reference->fieldname to $reference->ref_field('fieldname'). XXX I really wish there was a way to tell perl that we don't want to XXX handle a call to AUTOLOAD. =cut sub AUTOLOAD{ my $function = $AUTOLOAD; ($function) = $function =~ /\:?([^\:]+)$/; my $self = shift; if (ref $self and $self->{ref_fields}->{lc($function)}) { # slap $self and $function into @_. unshift @_, ($self,$function); goto &ref_field; } else { croak "Undefined subroutine $function"; } } =head2 can $obj->can('METHOD'); Class::Modular->can('METHOD'); Replaces UNIVERSAL's can method so that handled methods are reported correctly. Calls UNIVERSAL::can in the places where we don't know anything it doesn't. Returns a coderef to the method if the method is supported, undef otherwise. =cut sub can{ my ($self,$method,$vars) = @_; my $universal_can = UNIVERSAL::can($self,$method); if ($universal_can){ return $universal_can; } elsif (ref $self and exists $self->{ref_fields}->{lc($method)}) { # If there is no other method for dealing with this method, # and we would normally autoload it, create an anonymous sub # to deal with it appropriately. return sub{my $self = shift; return $self->ref_field($method,@_);}; } else { return undef; } } =head2 _init $self->_init =cut sub _init($){ my $self = shift; # ref_fields is used by AUTOLOAD to know when it's ok to set a # particular field my @ref_fields = $self->ref_fields; @{$self->{ref_fields}}{@ref_fields} = (1) x scalar @ref_fields; } # From http://www.ecst.csuchico.edu/~jacobsd/bib/formats/ # * BibTeX # * INSPEC # * MARC [MARC::Record] # * Melvyl [Uses MARC] # * RIS # * MedLine # * ISI Focus On # * EMBL # * BIDS # * ProCite # * EndNote # * Computing Archives # * Uniform Resource Citation # * RFC 1807 (replaces RFC 1357) # * Other formats 1; __END__