# XML::Template::Exception
#
# Copyright (c) 2002 Jonathan A. Waxman <jowaxman@bbl.med.upenn.edu>
# All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.


package XML::Template::Exception;


use strict;


=pod

=head1 NAME

XML::Template::Exception - XML::Template exception handling class.

=head1 SYNOPSIS

use XML::Template::Exception;

my $exception = XML::Template::Exception->new ('ERRORTYPE',
                                               'This is the error info.');
my $type = $exception->type;
my $info = $exception->info;
if ($exception->isa ('DB')) {
  ...
}

=head1 DESCRIPTION

This modules provides a class for handing exceptions.  Typically 
exceptions are raised in code generated by Element modules.  For instance, 
here is some exception handling code from the DB Element module:

  \$result = \$db->select (Table    => \$tables,
                         Where      => \$where);
  die XML::Template::Exception->new ('DB', \$db->error ()) if defined \$db->error ();

=head1 CONSTRUCTOR

The constructor takes two parameters.  The first is the error type which a
short identifier.  The type may contain dotted components (e.g. 'foo',
'foo.bar', 'foo.bar.baz'), so that exception types are hierarchical.  
That is, 'foo.bar' would be a specific type of the more general 'foo'
type.  If no type is given, the type is set to 'Undefined'.  The second
parameter is the text that describes the exception.

The constructor returns a blessed array containg the exception type and 
info.

=cut

sub new {
  my $proto = shift;
  my ($type, $info) = @_;

  $type = 'Undefined' if ! defined $type;

  my $class = ref ($proto) || $proto;
  return bless ([$type, $info], $class);
}

=head2 isa

  if ($exception->isa ('foo.bar')) {
    ...
  }

This method returns 1 if the Exception is of the given type.  The given
type is matched against each full type in the type hierarchy as well as
each child in the hierarchy.  So, for instance, if the exception type is
C<foo.bar>, C<$exception->isa ('foo.bar')>, C<$exception->isa ('foo')>,
and C<$exception->isa ('bar')> will all return 1.

=cut

sub isa {
  my $self = shift;
  my $type = shift;

  my $etype = $self->[0];
  while ($etype) {
    $etype =~ /([^\.]*$)/;
    return 1 if $type eq $etype || $type eq $1;

    $etype =~ s/\.?[^\.]*$//;
  }

  return 0;
}

=head2 type

  my $type = $exception->type;

This method returns the exception type.

=cut

sub type {
  my $self = shift;

  return $self->[0];
}

=head2 info

  my $info = $exception->info;

This method returns the info associated with the exception.

=cut

sub info {
  my $self = shift;

  return $self->[1];
}


1;


__END__

=pod

=head1 AUTHOR

Jonathan Waxman
jowaxman@bbl.med.upenn.edu

=head1 COPYRIGHT

Copyright (c) 2002 Jonathan A. Waxman
All rights reserved.

This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

=cut
