# 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 <don@donarmstrong.com>.
# $Id: Reference.pm 44 2013-09-10 00:37:13Z don $

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: 44 $ =~ /\$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";
     }
}

# do nothing
sub DESTROY {

}


=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__






