Mercurial > repos > mahtabm > ensemb_rep_gvl
diff variant_effect_predictor/Bio/Root/Err.pm @ 0:2bc9b66ada89 draft default tip
Uploaded
author | mahtabm |
---|---|
date | Thu, 11 Apr 2013 06:29:17 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/variant_effect_predictor/Bio/Root/Err.pm Thu Apr 11 06:29:17 2013 -0400 @@ -0,0 +1,1138 @@ +#----------------------------------------------------------------------------- +# PACKAGE : Bio::Root::Err.pm +# AUTHOR : Steve Chervitz (sac@bioperl.org) +# CREATED : 22 July 1996 +# REVISION: $Id: Err.pm,v 1.15 2002/10/22 07:38:37 lapp Exp $ +# STATUS : Alpha +# +# For documentation, run this module through pod2html +# (preferably from Perl v5.004 or better). +# +# Copyright (c) 1996-8 Steve Chervitz. All Rights Reserved. +# This module is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. +# Retain this notice and note any modifications made. +#----------------------------------------------------------------------------- + +package Bio::Root::Err; +use strict; + +use Bio::Root::Global qw(:devel $CGI); +use Bio::Root::Vector (); +use Bio::Root::Object;# qw(:std); +use Exporter (); + +use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); +@ISA = qw( Bio::Root::Object Bio::Root::Vector Exporter ); +@EXPORT = qw(); +@EXPORT_OK = qw( %ERR_FIELDS @ERR_TYPES &format_stack_entry &throw &warning); +%EXPORT_TAGS = ( + data => [qw(%ERR_FIELDS @ERR_TYPES)], + std => [qw(&throw &warning)] + ); + +use vars qw($ID $VERSION); +$ID = 'Bio::Root::Err'; +$VERSION = 0.041; + +%Bio::Root::Err::ERR_FIELDS = (TYPE=>1, MSG=>1, NOTE=>1, CONTEXT=>1, + TECH=>1, STACK=>1 ); + +@Bio::Root::Err::ERR_TYPES = qw(WARNING EXCEPTION FATAL); + + +## MAIN POD DOCUMENTATION: + +=head1 NAME + +Bio::Root::Err - Exception class for Perl 5 objects + +=head1 SYNOPSIS + +=head2 Object Creation + +B<Bio::Root::Object.pm> is a wrapper for Bio::Root::Err.pm objects so clients +do not have to create these objects directly. Please see +B<Bio::Root::Object::throw()> as well as L<_initialize>() +for a more complete treatment +of how to create Bio::Root::Err.pm objects. + + use Bio::Root::Err; + + $err = Bio::Root::Err->new(-MSG =>"Bad data: $data", + -STACK =>[\caller(0), \caller(1), ...], + ); + + +To use the L<throw>() method directly: + + use Bio::Root::Err (:std); + + throw( $object_ref, 'Error message', 'additional note', 'technical note'); + +The C<$object_ref> argument should be a reference to a Bio::Root::Object.pm. + +See also L<the USAGE section | USAGE>. + +=head1 INSTALLATION + +This module is included with the central Bioperl distribution: + + http://bio.perl.org/Core/Latest + ftp://bio.perl.org/pub/DIST + +Follow the installation instructions included in the INSTALL file. + +=head1 DESCRIPTION + +A Bio::Root::Err.pm object encapsulates data and methods that facilitate +working with errors and exceptional conditions that arise in Perl objects. +There are no biological semantics in this module, as one may suspect from its +location in the Bio:: hierarchy. The location of this module serves to +separate it from the namespaces of other Perl Error modules. It also makes it +convenient for use by Bio:: objects. + +The motivation for having an error object is to allow +Perl 5 objects to deal with errors or exceptional conditions that +can arise during their construction or manipulation. For example: + + (1) A complex object can break in many ways. + (2) Tracking errors within a set of nested objects can be difficult. + (3) The way an error is reported should be context-sensitive: + a web-user needs different information than does the + software engineer. + +Bio::Root::Err.pm, along with B<Bio::Root::Object.pm>, attempt to make such +problems tractable. Please see the L<Bio::Root::Object> documentation for more +about my error handling philosophy. + +A B<Bio::Root::Err.pm> object is an example of a Vector-Object: This module +inherits both from B<Bio::Root::Object.pm> and B<Bio::Root::Vector.pm>. This +permits a single Err object to exist within a linked list of Err objects OR +alone. See the L<Bio::Root::Vector> documentation for more about Vector-Objects. + +B<The API for this module is not complete since the module is under development.> + +=head2 Other Exception Strategies + +Exception handling with Perl 5 objects is currently not as evolved as one +would like. The error handling used by B<Bio::Root::Object.pm> and Bio::Root::Err.pm +relies on Perl's built-in error/exception handling with eval/die, +which is not very object-aware. What I've attempted to do with these +modules is to make eval/die more object-savvy, as well as make Perl 5 +objects more eval/die-savvy (but the current strategy is basically a hack). + +It would be great if Perl could throw an object reference with die(). +This would permit more intelligent and easy to write exception handlers. +For now the Err.pm object is reconstructed from the output of L<string>(). + +There are some other third-party Exception classes such as +Torsten Ekedahl's B<Experimental::Exception.pm> or Ken Steven's Throwable.pm or +Graham Barr's Error.pm (see L<Other Exception Modules>). These modules +attempt to introduce a traditional "try-catch-throw" exception handling mechanism +into Perl. Future version of my modules (and perhaps Perl itself) may utilize one +of these. + +=head1 USAGE + +A demo script that illustrates working with Bio::Root::Err objects is +examples/root_object/error.pl. + + +=head1 DEPENDENCIES + +Bio::Root::Err.pm inherits from B<Bio::Root::Object.pm> and B<Bio::Root::Vector.pm>. + + +=head1 FEEDBACK + +=head2 Mailing Lists + +User feedback is an integral part of the evolution of this and other Bioperl modules. +Send your comments and suggestions preferably to one of the Bioperl mailing lists. +Your participation is much appreciated. + + bioperl-l@bioperl.org - General discussion + http://bioperl.org/MailList.shtml - About the mailing lists + +=head2 Reporting Bugs + +Report bugs to the Bioperl bug tracking system to help us keep track the bugs and +their resolution. Bug reports can be submitted via email or the web: + + bioperl-bugs@bio.perl.org + http://bugzilla.bioperl.org/ + +=head1 AUTHOR Steve Chervitz + +Email sac@bioperl.org + +See L<the FEEDBACK section | FEEDBACK> section for where to send bug reports and comments. + +=head1 VERSION + +Bio::Root::Err.pm, 0.041 + + +=head1 SEE ALSO + + Bio::Root::Object.pm - Core object + Bio::Root::Vector.pm - Vector object + Bio::Root::Global.pm - Manages global variables/constants + + http://bio.perl.org/Projects/modules.html - Online module documentation + http://bio.perl.org/ - Bioperl Project Homepage + +=head2 Other Exception Modules + + Experimental::Exception.pm - ftp://ftp.matematik.su.se/pub/teke/ + Error.pm - http://www.cpan.org/authors/id/GBARR/ + Throwable.pm - mailto:kstevens@globeandmail.ca + + http://genome-www.stanford.edu/perlOOP/exceptions.html + +=head1 ACKNOWLEDGEMENTS + +This module was developed under the auspices of the Saccharomyces Genome +Database: + http://genome-www.stanford.edu/Saccharomyces + +Other Bioperl developers contributed ideas including Ewan Birney, Ian Korf, +Chris Dagdigian, Georg Fuellen, and Steven Brenner. + +=head1 COPYRIGHT + +Copyright (c) 1996-8 Steve Chervitz. All Rights Reserved. +This module is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=head1 TODO + +=over 2 + +=item * Improve documentation. + +=item * Experiment with other Exception modules. + +=back + +=cut + +## END MAIN POD DOCUMENTATION' + +=head1 APPENDIX + +Methods beginning with a leading underscore are considered private +and are intended for internal use by this module. They are +B<not> considered part of the public interface and are described here +for documentation purposes only. + +=cut + + +######################################################## +# CONSTRUCTOR # +######################################################## + + +=head2 _initialize + + Usage : n/a; automatically called by Bio::Root::Object::new() + Purpose : Initializes key Bio::Root::Err.pm data. + Returns : String (the -MAKE constructor option.) + Argument : Named parameters passed from new() + : (PARAMETER TAGS CAN BE UPPER OR LOWER CASE). + : -MSG => basic description of the exception. + : -NOTE => additional note to indicate cause of exception + : or provide information about how to fix/report it + : -TECH => addition note with technical information + : of interest to developer. + : -STACK => array reference containing caller() data + : -TYPE => string, one of @Bio::Root::Err::ERR_TYPES + : (default = exception). + : -CONTEXT => array reference + : -OBJ => Err object to be cloned. + +See Also : B<Bio::Root::Object::_set_err()> + +=cut + +#---------------- +sub _initialize { +#---------------- + my( $self, @param ) = @_; + + my $make = $self->Bio::Root::Object::_initialize( @param ); + + my( $msg, $note, $tech, $stack, $type, $context, $obj) = + $self->_rearrange([qw(MSG NOTE TECH STACK TYPE CONTEXT OBJ)], @param); + + ## NOTE: Don't eval {} the construction process for Err objects. + + if($make =~ /clone/i) { + $self->_set_clone($obj); + } else { + if(!$self->_build_from_string($msg, $note, $tech)) { +# print "Failed to rebuild: msg = $msg";<STDIN>; + $self->set('msg', $msg ); + $self->_set_type( $type ); + $self->_set_context($context); + $self->_set_list_data('note', $note ); + $self->_set_list_data('tech', $tech ); + $self->_set_list_data('stack', $stack ); + } + $self->set_display(); + } + + $DEBUG and do{ print STDERR "---> Initialized Err (${\ref($self)}).\n\n"; + # $self->print(); + }; + $make; +} + +## +## Destructor: Not needed currently. Perhaps if and when Vector is used by delegation. +## + +##################################################################################### +## ACCESSORS ## +##################################################################################### + + + +=head2 _set_clone + + Usage : n/a; internal method used by _initialize() + Purpose : Copy all Bio::Root::Err.pm data members into a new object reference. + Argument : object ref for object to be cloned. + Comments : Does not cloning the vector since this method is + : typically used to extract a single Err object from its vector. + +=cut + +#--------------- +sub _set_clone { +#--------------- + my($self, $obj) = @_; + + ref($obj) || throw($self, "Can't clone $ID object: Not an object ref ($obj)"); + + $self->{'_type'} = $obj->{'_type'}; + $self->{'_msg'} = $obj->{'_msg'}; + $self->{'_note'} = $obj->{'_note'}; + $self->{'_tech'} = $obj->{'_tech'}; + $self->{'_stack'} = $obj->{'_stack'}; + $self->{'_context'} = $obj->{'_context'}; +# $self->clone_vector($obj); +} + + +=head2 _build_from_string + + Usage : n/a; called by _initialize() + Purpose : Re-create an Err.pm object from a string containing Err data. + Returns : boolean, (was the Err.pm object rebuilt?) + Argument : message, note, tech passed from _initialize() + : The message is examined to see if it contains a stringified error. + +See Also : L<_initialize>(), L<string>(), L<_has_err>() + +=cut + +#---------------------- +sub _build_from_string { +#---------------------- + my ($self, $msg, $note, $tech) = @_; + my @list = split "\n", $msg; + my ($mode,$line); + my $rebuilt = 0; + + # print "$ID: Attempting to build from string: $msg";<STDIN>; + + MEMBER: + foreach $line (@list) { + if($line =~ /^-+$/) { last MEMBER; } + if($line =~ /^-+ (\w+) -+$/) { $self->{'_type'} = $1; $rebuilt = 1; next MEMBER; } + if($line =~ /^MSG: *(\w.*)/) { my $msg = $1; + if($self->_has_err($msg)) { + die "Duplicate error."; + } + $self->{'_msg'} = $msg; + $mode = 'msg'; + next MEMBER; } + if($line =~ /^CONTEXT: *(\w.*)/) { push @{$self->{'_context'}}, $1; $mode = 'context'; next MEMBER; } + if($line =~ /^NOTE: *(\w.*)/) { push @{$self->{'_note'}}, $1; $mode = 'note'; next MEMBER; } + if($line =~ /^TECH: *(\w.*)/) { push @{$self->{'_tech'}}, $1; $mode = 'tech'; next MEMBER; } + if($line =~ /^STACK:/) { $mode = 'stack'; next MEMBER; } + next MEMBER if !$mode; + SWITCH: { + local $_ = $mode; + m/msg/ && do{ $self->{'_msg'} .= "$line\n"; last SWITCH; }; + m/note/ && do{ push @{$self->{'_note'}}, $line; last SWITCH; }; + m/context/ && do{ push @{$self->{'_context'}}, $line; last SWITCH; }; + m/tech/ && do{ push @{$self->{'_tech'}}, $line; last SWITCH; }; + m/stack/ && do{ push @{$self->{'_stack'}}, $line; last SWITCH; }; + next MEMBER; + } + } + if($rebuilt) { + ## Optionally add additional notes. + $self->_set_list_data('note', $note) if defined $note; + $self->_set_list_data('tech', $tech) if defined $tech; + } + + $rebuilt; +} + + +=head2 _has_err + + Usage : n/a; internal method called by _build_from_string() + Purpose : Deterimine if an Err has already been set to prevent duplicate Errs. + Returns : boolean + +See Also : L<_build_from_string>() + +=cut + +#------------- +sub _has_err { +#------------- + my ($self, $msg) = @_; + + $msg =~ s/^\s+//; + $msg =~ s/\s+$//; + + my $err = $self->first; + my ($existing_msg); + do { +# print "checking err object $self\n"; + $existing_msg = $err->msg; + $existing_msg =~ s/^\s+//; + $existing_msg =~ s/\s+$//; +# print " msg: $existing_msg";<STDIN>; + return 1 if $existing_msg eq $msg; + + } while($err = $err->next); + + 0; +} + + +=head2 _set_type + + Usage : n/a; internal method + Purpose : Sets the type of Err (warning, exception, fatal) + : Called by _initialize() + Argument : string + +=cut + +#---------------- +sub _set_type { +#---------------- + my( $self, $data ) = @_; + $data ||= 'EXCEPTION'; + +# printf "\n$ID: Setting type (%s) for err = %s\n", $data, $self->msg;<STDIN>; + + my (@type); + if( @type = grep /$data/i, @Bio::Root::Err::ERR_TYPES ) { + $self->{'_type'} = $type[0]; + } else { + $self->{'_type'} = 'EXCEPTION'; + } + +# print "type = $self->{'_type'} for $self";<STDIN>; +} + + + +=head2 _set_list_data + + Usage : n/a; internal method used by set(). + : $err->_set_list_data( $member, $data); + Purpose : For data members which are anonymous arrays: note, tech, stack, + : adds the given data to the list. + Arguments : $member = any of qw(note tech stack) + : $data = string + Comments : Splits $data on tab. Each item + : of the split is a new entry. + : To clobber the current data (unusual situation), you must first + : call set() with no data then call again with desired data. + +=cut + +#------------------- +sub _set_list_data { +#------------------- + my( $self, $member, $data ) = @_; + + # Sensitive to data member name changes. + $member = "_\l$member"; + +# $DEBUG && do {printf STDERR "\n$ID: Setting \"%s\" list data (%s)\n", $member, $data;<STDIN>; }; + + defined $self->{$member} and return $self->_add_list_data( $member, $data ); + + if( $data ) { + $self->{$member} = []; + if( $member =~ /stack/) { + foreach (@$data) { + push @{ $self->{$member}}, format_stack_entry(@$_); + } + } else { + my @entries = split "\t", $data; + foreach (@entries) { + next if /^$/; +# $DEBUG && do {print STDERR "adding $member: $_";<STDIN>;}; + push @{ $self->{$member}}, $_; + } + } + } else { + $self->{$member} = undef; + } +} + + +=head2 _set_context + + Usage : n/a; internal method used by set(). + Purpose : Sets the object containment context for the exception. + : (this is the hierarchy of objects in which the + : exception occurred.) + +=cut + +#------------------ +sub _set_context { +#------------------ + my($self, $aref) = @_; + + eval { + if (!ref $aref) { +# push @{$aref}, sprintf "object %s \"%s\"",ref($self->parent), $self->parent->name; + push @{$aref}, "UNKNOWN CONTEXT"; + } + }; + if($@) { push @{$aref}, 'undefined object'; } + + if($self->type eq 'EXCEPTION') { + $aref->[0] = "Exception thrown by \l$aref->[0]"; + } else { + $aref->[0] = "Error in \l$aref->[0]"; + } + + my $script = ($0 =~ /([\w\/\.]+)/, $1); + push @$aref, "SCRIPT: $script"; + + $self->{'_context'} = $aref; + +# print "$ID: _set_context():\n"; +# foreach(@$aref) { print " $_\n"; } +# <STDIN>; +} + + + +=head2 set + + Usage : $err->set( $member, $data ); + Purpose : General accessor for setting any Err.pm data member. + Example : $err->set('note', 'this is an additional note.'); + Returns : n/a + Argument : $member = string, any of qw(msg type note tech stack) + : $data = string + Throws : n/a + Comments : Note, tech, and stack items are appended to any existing + : notes, tech notes, and stack. + : There should be no need to mess with the stack. + +=cut + +#--------- +sub set { +#--------- + my( $self, $member, $data ) = @_; + + local $_ = "\u$member"; + SWITCH: { + /msg/i && do{ $self->{'_msg'} = (defined $data ? $data : 'Unknown error'); last SWITCH; }; + /type/i && do{ $self->_set_type( $data ); last SWITCH; }; + /note|tech|stack/i && do{ $self->_set_list_data( $member, $data); last SWITCH}; + warn "\n*** Invalid or unspecified Err data member: $member\n\n"; + } +} + + +=head2 msg + + Usage : $message = $err->msg; + Purpose : Get the main message associated with the exception. + Returns : String + Argument : optional string to be used as a delimiter. + +See Also : L<get>(), L<string>() + +=cut + + +#------- +sub msg { my($self,$delimiter) = @_; $self->get('msg',$delimiter); } +#------- + + +=head2 type + + Usage : $type = $err->type; + Purpose : Get the type of Err (warning, exception, fatal) + Returns : String + Argument : optional string to be used as a delimiter. + +See Also : L<get>(), L<string>() + +=cut + +#-------- +sub type { my($self,$delimiter) = @_; $self->get('type',$delimiter); } +#-------- + + +=head2 note + + Usage : $note = $err->note; + : $note = $err->note('<P>'); + Purpose : Get any general note associated with the exception. + Returns : String + Argument : optional string to be used as a delimiter. + +See Also : L<get>(), L<string>() + +=cut + +#--------- +sub note { my($self,$delimiter) = @_; $self->get('note',$delimiter); } +#--------- + + +=head2 tech + + Usage : $tech = $err->tech; + : $tech = $err->tech('<P>'); + Purpose : Get any technical note associate with the exception. + Returns : String + Argument : optional string to be used as a delimiter. + +See Also : L<get>(), L<string>() + +=cut + +#------------ +sub tech { my($self,$delimiter) = @_; $self->get('tech',$delimiter); } +#------------ + + + +=head2 stack + + Usage : $stack = $err->stack; + : $stack = $err->stack('<P>'); + Purpose : Get the call stack for the exception. + Returns : String + Argument : optional string to be used as a delimiter. + +See Also : L<get>(), L<string>() + +=cut + +#---------- +sub stack { my($self,$delimiter) = @_; $self->get('stack',$delimiter); } +#---------- + + + +=head2 context + + Usage : $context = $err->context; + : $context = $err->context('<P>'); + Purpose : Get the containment context of the object which generated the exception. + Returns : String + Argument : optional string to be used as a delimiter. + +See Also : L<get>(), L<string>() + +=cut + +#------------ +sub context { my($self,$delimiter) = @_; $self->get('context',$delimiter); } +#------------ + + + +=head2 get + + Usage : $err->get($member, $delimiter); + Purpose : Get specific data from the Err.pm object. + Returns : String in scalar context. + : Array in list context. + Argument : $member = any of qw(msg type note tech stack context) or combination. + : $delimiter = optional string to be used as a delimiter + : between member data. + +See Also : L<string>(), L<msg>(), L<note>(), L<tech>(), L<type>(), L<context>(), L<stack>() + +=cut + +#--------- +sub get { +#--------- + my( $self, $member, $delimiter ) = @_; + + my $outer_delim = $delimiter || "\n"; +# my $outer_delim = ($CGI ? "\n<P>" : $delimiter); ## Subtle bug here. + + my (@out); + local $_ = $member; + SWITCH: { + /type/i && do{ push (@out, $self->{'_type'},$outer_delim) }; +# /msg/i && do{ print "getting msg";<STDIN>; push (@out, (defined $self->{'_msg'} ? $self->{'_msg'} : ''),$outer_delim); print "msg: @out<---";<STDIN>; }; + /msg/i && do{ push (@out, (defined $self->{'_msg'} ? $self->{'_msg'} : ''),$outer_delim); }; + /note/i && do{ push (@out, $self->_get_list_data('note', $delimiter ),$outer_delim) }; + /tech/i && do{ push (@out, $self->_get_list_data('tech', $delimiter ),$outer_delim) }; + /stack/i && do{ push (@out, $self->_get_list_data('stack', $delimiter ),$outer_delim) }; + /context/i && do{ push (@out, $self->_get_list_data('context', $delimiter ),$outer_delim) }; + + ## CAN'T USE THE FOLLOWING FORM SINCE IT FAILS WHEN $member EQUALS 'msgnote'. +# /note|tech|stack/ && do{ push @out, $self->_get_list_data( $_, $delimiter ); }; + + last SWITCH; + $self->warn("Invalid or undefined Err data member ($member)."); + } +# $DEBUG && do{ print STDERR "OUTER DELIM = $outer_delim \nOUT: \n @out <---";<STDIN>;}; + wantarray ? @out : join('',@out); +} + + + +=head2 _get_list_data + + Usage : n/a; internal method used by get() + Purpose : Gets data for members which are list refs (note, tech, stack, context) + Returns : Array + Argument : ($member, $delimiter) + +See Also : L<get>() + +=cut + +#------------------- +sub _get_list_data { +#------------------- + my( $self, $member, $delimiter ) = @_; + $delimiter ||= "\t"; + # Sensitive to data member name changes. + $member = "_\l$member"; + return if !defined $self->{$member}; + join( $delimiter, @{$self->{$member}} ); +} + + + +=head2 get_all + + Usage : (same as get()) + Purpose : Get specific data from all errors in an Err.pm object. + Returns : Array in list context. + : String in scalar context. + Argument : (same as get()) + +See Also : L<get>() + +=cut + +#------------ +sub get_all { +#------------ + my( $self, $member, $delimiter ) = @_; + + if( $self->size() == 1) { + return $self->get( $member, $delimiter); + } else { + my $err = $self; + + ### Return data from multiple errors in a list. + if(wantarray) { + my @out; + do{ push @out, $err->get( $member); + } while($err = $err->prev()); + return @out; + + } else { + ### Return data from multiple errors in a string with each error's data + ### bracketed by a "Error #n\n" line and two delimiters. + my $out = ''; + if($err->size() == 1) { + $out = $err->get( $member, $delimiter); + } else { + do{ #$out .= "Error #${\$err->rank()}$delimiter"; + $out .= $err->get( $member, $delimiter); + $out .= $delimiter.$delimiter; + } while($err = $err->prev()); + } + return $out; + } + } +} + +##################################################################################### +## INSTANCE METHODS ## +##################################################################################### + + +=head2 _add_note + + Usage : n/a; internal method called by _add_list_data() + Purpose : adds a new note. + +See Also : L<_add_list_data>() + +=cut + +#--------------- +sub _add_note { +#--------------- + my( $self, $data ) = @_; + + if( defined $self->{'_note'} ) { + push @{ $self->{'_note'}}, $data; + } else { + $self->_set_list_data('note', $data ); + } +} + +#---------------------------------------------------------------------- +=head2 _add_tech() + + Usage : n/a; internal method called by _add_list_data() + Purpose : adds a new technical note. + +See Also : L<_add_list_data>() + +=cut + +#------------- +sub _add_tech { +#------------- + my( $self, $data ) = @_; + + if( defined $self->{'_tech'} ) { + push @{ $self->{'_tech'}}, $data; + } else { + $self->_set_list_data('Tech', $data ); + } +} + + +=head2 _add_list_data + + Usage : n/a; called by _set_list_data() + Purpose : adds a new note or tech note. + +See Also : L<_set_list_data>() + +=cut + +#-------------------- +sub _add_list_data { +#-------------------- + my( $self, $member, $data ) = @_; + + local $_ = $member; + SWITCH: { + /note/i && do{ $self->_add_note( $data ); }; + /tech/i && do{ $self->_add_tech( $data ); }; + } +} + + + +=head2 print + + Usage : $err->print; + Purpose : Prints Err data to STDOUT or a FileHandle. + Returns : Call to print + Argument : Named parameters for string() + Comments : Uses string() to get data. + +See Also : L<string>() + +=cut + +#----------- +sub print { +#----------- + my( $self, %param ) = @_; +# my $OUT = $self->parent->fh(); +# print $OUT $self->string(%param); + print $self->string(%param); +} + + +=head2 string + + Usage : $err->string( %named_parameters); + Purpose : Stringify the data contained in the Err.pm object. + Example : print STDERR $err->string; + Returns : String + Argument : Named parameters (optional) passed to + : Bio::Root::IOManager::set_display(). + +See Also : L<print>(), L<_build_from_string>(), B<Bio::Root::IOManager::set_display()> + +=cut + +#----------- +sub string { +#----------- + my( $self, @param ) = @_; + + my %param = @param; + $self->set_display( @param ); + my $show = $self->show; + my $out = $param{-BEEP} ? "\a" : ''; + + my $err = $param{-CURRENT} ? $self->last : $self->first; + +# my $err1 = $err; +# my $errL = $self->last; +# print "\n\nERR 1: ${\$err1->msg}"; +# print "\nERR L: ${\$errL->msg}";<STDIN>; + + my $numerate = $err->size() >1; + my $count = 0; + my ($title); + my $hasnote = defined $self->{'_note'}; + my $hastech = defined $self->{'_tech'}; + + while (ref $err) { + $count++; +# $out .= sprintf "\nERROR #%d:", $count; + + if(not $title = $err->{'_type'}) { + $err = $err->next(); + next; + } + if( $numerate) { + ## The rank data is a bit screwy at present. + $out .= sprintf "\n%s %s %s\n", '-'x 20, $title,'-'x 20; + } else { + $out .= sprintf "\n%s %s %s\n", '-'x20, $title,'-'x20; + } + $show =~ /msg|default/i and $out .= "MSG: " . $err->msg("\n"); + $show =~ /note|default/i and $hasnote and $out .= "NOTE: ".$err->note("\n"); + $show =~ /tech|default/i and $hastech and $out .= "TECH: ".$err->tech("\n"); + $show =~ /context|default/i and $out .= "CONTEXT: ".$err->context("\n"); + $show =~ /stack|default/i and $out .= "STACK: \n".$err->stack("\n"); + $out .= sprintf "%s%s%s\n",'-'x 20, '-'x (length($title)+2), '-'x 20; + +# print "$ID: string: cumulative err:\n$out\n";<STDIN>; + + $err = $err->next(); + } + + $out; +} + + + +=head2 is_fatal + + Usage : $err->is_fatal; + Purpose : Determine if the error is of type 'FATAL' + Returns : Boolean + Status : Experimental, Deprecated + +=cut + +#-------------- +sub is_fatal { my $self = shift; $self->{'_type'} eq 'FATAL'; } +#-------------- + +##################################################################################### +## CLASS METHODS ## +##################################################################################### + + +=head2 throw + + Usage : throw($object, [message], [note], [technical note]); + : This method is exported. + Purpose : Class method version of Bio::Root::Object::throw(). + Returns : die()s with the contents of the Err object in a string. + : If the global strictness is less than -1, die is not called and + : the error is printed to STDERR. + Argument : [0] = object throwing the error. + : [1] = optional message about the error. + : [2] = optional note about the error. + : [3] = optional technical note about the error. + Comments : The glogal verbosity level is not used. For verbosity-sensitive + : behavior, use Bio::Root::Object::throw(). + Status : Experimental + : This method is an alternative to Bio::Root::Object::throw() + : and is not as well developed or documented as that method. + +See Also : L<warning>(), B<Bio::Root::Object::throw()> B<Bio::Root::Global::strictness>() + +=cut + +#---------- +sub throw { +#---------- + my($obj, @param) = @_; + +# print "Throwing exception for object ${\ref $self} \"${\$self->name}\"\n"; + my $err = new Bio::Root::Err( + -MSG =>$param[0], + -NOTE =>$param[1], + -TECH =>$param[2], + -STACK =>scalar(Bio::Root::Object::stack_trace($obj,2)), + -CONTEXT =>Bio::Root::Object::containment($obj), + -TYPE =>'EXCEPTION', + # -PARENT =>$obj, + ); + + if(strictness() < -1) { + print STDERR $err->string(-BEEP=>1) unless verbosity() < 0; + } else { + die $err->string; + } + + 0; +} + + +=head2 warning + + Usage : warning($object, [message], [note], [technical note]); + : This method is exported. + Purpose : Class method version of Bio::Root::Object::warn(). + Returns : Prints the contents of the error to STDERR and returns false (0). + : If the global strictness() is > 1, warn() calls are converted + : into throw() calls. + Argument : [0] = object producing the warning. + : [1] = optional message about the error. + : [2] = optional note about the error. + : [3] = optional technical note about the error. + : + Comments : The glogal verbosity level is not used. For verbosity-sensitive + : behavior, use Bio::Root::Object::warn(). + Status : Experimental + : This method is an alternative to Bio::Root::Object::warn() + : and is not as well developed or documented as that method. + +See Also : L<throw>, B<Bio::Root::Object::warn()>, B<Bio::Root::Global::strictness()> + +=cut + +#----------- +sub warning { +#----------- + my($obj, @param) = @_; + +# print "Throwing exception for object ${\ref $self} \"${\$self->name}\"\n"; + my $err = new Bio::Root::Err( + -MSG =>$param[0], + -NOTE =>$param[1], + -TECH =>$param[2], + -STACK =>scalar(Bio::Root::Object::stack_trace($obj,2)), + -CONTEXT =>Bio::Root::Object::containment($obj), + -TYPE =>'WARNING', + # -PARENT =>$obj, + ); + + if(strictness() > 1) { + die $err->string; + + } else { + print STDERR $err->string(-BEEP=>1) unless $DONT_WARN; + } + + 0; +} + + +=head2 format_stack_entry + + Usage : &format_stack_entry(<class>,<file>,<line>,<class_method>,<has_args>,<wantarray>) + : This function is exported. + Purpose : Creates a single stack entry given a caller() list. + Argument : List of scalars (output of the caller() method). + Returns : String = class_method($line) + : e.g., Bio::Root::Object::name(1234) + +=cut + +#------------------------ +sub format_stack_entry { +#------------------------ + my( $class, $file, $line, $classmethod, $hasargs, $wantarray) = @_; + +# if($DEBUG) { +# print STDERR "format_stack_entry data:\n"; +# foreach(@_) {print STDERR "$_\n"; } <STDIN>; +# } + + $classmethod ||= 'unknown class/method'; + $line ||= 'unknown line'; + return "$classmethod($line)"; +} + +1; +__END__ + +##################################################################################### +# END OF CLASS # +##################################################################################### + +=head1 FOR DEVELOPERS ONLY + +=head2 Data Members + +Information about the various data members of this module is provided for those +wishing to modify or understand the code. Two things to bear in mind: + +=over 4 + +=item 1 Do NOT rely on these in any code outside of this module. + +All data members are prefixed with an underscore to signify that they are private. +Always use accessor methods. If the accessor doesn't exist or is inadequate, +create or modify an accessor (and let me know, too!). + +=item 2 This documentation may be incomplete and out of date. + +It is easy for this documentation to become obsolete as this module is still evolving. +Always double check this info and search for members not described here. + +=back + +An instance of Bio::Root::Err.pm is a blessed reference to a hash containing +all or some of the following fields: + + FIELD VALUE + ------------------------------------------------------------------------ + _type fatal | warning | exception (one of @Bio::Root::Err::ERR_TYPES). + + _msg Terse description: Main cause of error. + + _note List reference. Verbose description: probable cause & troubleshooting for user. + + _tech List reference. Technical notes of interest to programmer. + + _stack List reference. Stack trace: list of "class::method(line number)" strings. + + + +=cut + +1;