1 package Bio
::Root
::Root
;
5 use Scalar
::Util
qw(blessed reftype);
6 use base
2.18 qw(Bio::Root::RootI);
10 Bio::Root::Root - implementation of Bio::Root::RootI interface
14 # Any Bioperl-compliant object is a RootI compliant object
16 # Here's how to throw and catch an exception using the eval-based syntax.
18 $obj->throw("This is an exception");
21 $obj->throw("This is catching an exception");
25 print "Caught exception";
30 # Alternatively, using the new typed exception syntax in the throw() call:
32 $obj->throw( -class => 'Bio::Root::BadParameter',
33 -text => "Can not open file $file",
36 # Want to see debug() outputs for this object
38 my $obj = Bio::Object->new(-verbose=>1);
40 my $obj = Bio::Object->new(%args);
43 # Print debug messages which honour current verbosity setting
45 $obj->debug("Boring output only to be seen if verbose > 0\n");
49 my $clone = $obj->clone;
53 This is a hashref-based implementation of the Bio::Root::RootI
54 interface. Most Bioperl objects should inherit from this.
56 See the documentation for L<Bio::Root::RootI> for most of the methods
57 implemented by this module. Only overridden methods are described
60 =head2 Throwing Exceptions
62 One of the functionalities that L<Bio::Root::RootI> provides is the
63 ability to L<throw>() exceptions with pretty stack traces. Bio::Root::Root
64 enhances this with the ability to use L<Error> (available from CPAN)
65 if it has also been installed.
67 If L<Error> has been installed, L<throw>() will use it. This causes an
68 Error.pm-derived object to be thrown. This can be caught within a
69 C<catch{}> block, from which you can extract useful bits of
70 information. If L<Error> is not installed, it will use the
71 L<Bio::Root::RootI>-based exception throwing facilty.
73 =head2 Typed Exception Syntax
75 The typed exception syntax of L<throw>() has the advantage of plainly
76 indicating the nature of the trouble, since the name of the class
77 is included in the title of the exception output.
79 To take advantage of this capability, you must specify arguments
80 as named parameters in the L<throw>() call. Here are the parameters:
86 name of the class of the exception.
87 This should be one of the classes defined in L<Bio::Root::Exception>,
88 or a custom error of yours that extends one of the exceptions
89 defined in L<Bio::Root::Exception>.
93 a sensible message for the exception
97 the value causing the exception or $!, if appropriate.
101 Note that Bio::Root::Exception does not need to be imported into
102 your module (or script) namespace in order to throw exceptions
103 via Bio::Root::Root::throw(), since Bio::Root::Root imports it.
105 =head2 Try-Catch-Finally Support
107 In addition to using an eval{} block to handle exceptions, you can
108 also use a try-catch-finally block structure if L<Error> has been
109 installed in your system (available from CPAN). See the documentation
110 for Error for more details.
112 Here's an example. See the L<Bio::Root::Exception> module for
113 other pre-defined exception types:
117 open $IN, '<', $file or $obj->throw( -class => 'Bio::Root::FileOpenException',
118 -text => "Cannot read file '$file'",
121 catch Bio::Root::BadParameter with {
122 my $err = shift; # get the Error object
123 # Perform specific exception handling code for the FileOpenException
125 catch Bio::Root::Exception with {
126 my $err = shift; # get the Error object
127 # Perform general exception handling code for any Bioperl exception.
130 # A catch-all for any other type of exception
133 # Any code that you want to execute regardless of whether or not
134 # an exception occurred.
136 # the ending semicolon is essential!
138 =head1 AUTHOR Steve Chervitz
140 Ewan Birney, Lincoln Stein
144 our ($DEBUG, $ID, $VERBOSITY, $ERRORLOADED, $CLONE_CLASS);
147 $ID = 'Bio::Root::Root';
152 # Check whether or not Error.pm is available.
154 # $main::DONT_USE_ERROR is intended for testing purposes and also
155 # when you don't want to use the Error module, even if it is installed.
156 # Just put a INIT { $DONT_USE_ERROR = 1; } at the top of your script.
157 if( not $main::DONT_USE_ERROR
) {
158 if ( eval "require Error; 1;" ) {
159 import Error
qw(:try);
160 require Bio
::Root
::Exception
;
162 $Error::Debug
= 1; # enable verbose stack trace
165 if( !$ERRORLOADED ) {
166 require Carp
; import Carp
qw( confess );
170 for my $class (qw(Clone Storable)) {
171 eval "require $class; 1;";
173 $CLONE_CLASS = $class;
174 if ($class eq 'Clone') {
175 *Bio
::Root
::Root
::_dclone
= sub {shift; return Clone
::clone
(shift)};
177 *Bio
::Root
::Root
::_dclone
= sub {
179 local $Storable::Deparse
= 1;
180 local $Storable::Eval
= 1;
181 return Storable
::dclone
(shift);
187 if (!defined $CLONE_CLASS) {
188 *Bio
::Root
::Root
::_dclone
= sub {
189 my ($self, $orig, $level) = @_;
190 my $class = Scalar
::Util
::blessed
($orig) || '';
191 my $reftype = Scalar
::Util
::reftype
($orig) || '';
195 } elsif ($reftype eq "ARRAY") {
196 $data = [map $self->_dclone($_), @
$orig];
197 } elsif ($reftype eq "HASH") {
198 $data = { map { $_ => $self->_dclone($orig->{$_}) } keys %$orig };
199 } elsif ($reftype eq 'CODE') { # nothing, maybe shallow copy?
200 $self->throw("Code reference cloning not supported; install Clone or Storable from CPAN");
201 } else { $self->throw("What type is $_?")}
209 $main::DONT_USE_ERROR
; # so that perl -w won't warn "used only once"
214 Purpose : generic instantiation function can be overridden if
215 special needs of a module cannot be done in _initialize
220 # my ($class, %param) = @_;
223 bless $self, ref($class) || $class;
226 # if the number of arguments is odd but at least 3, we'll give
227 # it a try to find -verbose
230 ## See "Comments" above regarding use of _rearrange().
231 $self->verbose($param{'-VERBOSE'} || $param{'-verbose'});
240 Usage : my $clone = $obj->clone();
242 my $clone = $obj->clone( -start => 110 );
243 Function: Deep recursion copying of any object via Storable dclone()
244 Returns : A cloned object.
245 Args : Any named parameters provided will be set on the new object.
246 Unnamed parameters are ignored.
247 Comments: Where possible, faster clone methods are used, in order:
248 Clone::Fast::clone(), Clone::clone(), Storable::dclone. If neither
249 is present, a pure perl fallback (not very well tested) is used
250 instead. Storable dclone() cannot clone CODE references. Therefore,
251 any CODE reference in your original object will remain, but will not
252 exist in the cloned object. This should not be used for anything
253 other than cloning of simple objects. Developers of subclasses are
254 encouraged to override this method with one of their own.
259 my ($orig, %named_params) = @_;
261 __PACKAGE__
->throw("Can't call clone() as a class method") unless
262 ref $orig && $orig->isa('Bio::Root::Root');
264 # Can't dclone CODE references...
265 # Should we shallow copy these? Should be harmless for these specific
268 my %put_these_back = (
269 _root_cleanup_methods
=> $orig->{'_root_cleanup_methods'},
271 delete $orig->{_root_cleanup_methods
};
273 # call the proper clone method, set lazily above
274 my $clone = __PACKAGE__
->_dclone($orig);
276 $orig->{_root_cleanup_methods
} = $put_these_back{_root_cleanup_methods
};
278 foreach my $key (grep { /^-/ } keys %named_params) {
281 if ($clone->can($method)) {
282 $clone->$method($named_params{$key})
284 $orig->warn("Parameter $method is not a method for ".ref($clone));
293 Usage : my $clone = $obj->_dclone($ref);
295 my $clone = $obj->_dclone($ref);
296 Function: Returns a copy of the object passed to it (a deep clone)
297 Returns : clone of passed argument
299 NOTE : This differs from clone significantly in that it does not clone
300 self, but the data passed to it. This code may need to be optimized
301 or overridden as needed.
302 Comments: This is set in the BEGIN block to take advantage of optimized
303 cloning methods if Clone or Storable is present, falling back to a
304 pure perl kludge. May be moved into a set of modules if the need
305 arises. At the moment, code ref cloning is not supported.
312 Usage : $self->verbose(1)
313 Function: Sets verbose level for how ->warn behaves
315 0 = standard, small warning
316 1 = warning with stack trace
317 2 = warning becomes throw
318 Returns : The current verbosity setting (integer between -1 to 2)
325 my ($self,$value) = @_;
326 # allow one to set global verbosity flag
327 return $DEBUG if $DEBUG;
328 return $VERBOSITY unless ref $self;
330 if (defined $value || ! defined $self->{'_root_verbose'}) {
331 $self->{'_root_verbose'} = $value || 0;
333 return $self->{'_root_verbose'};
336 =head2 _register_for_cleanup
340 sub _register_for_cleanup
{
341 my ($self,$method) = @_;
343 if(! exists($self->{'_root_cleanup_methods'})) {
344 $self->{'_root_cleanup_methods'} = [];
346 push(@
{$self->{'_root_cleanup_methods'}},$method);
350 =head2 _unregister_for_cleanup
354 sub _unregister_for_cleanup
{
355 my ($self,$method) = @_;
356 my @methods = grep {$_ ne $method} $self->_cleanup_methods;
357 $self->{'_root_cleanup_methods'} = \
@methods;
360 =head2 _cleanup_methods
364 sub _cleanup_methods
{
366 return unless ref $self && $self->isa('HASH');
367 my $methods = $self->{'_root_cleanup_methods'} or return;
374 Usage : $obj->throw("throwing exception message");
376 $obj->throw( -class => 'Bio::Root::Exception',
377 -text => "throwing exception message",
378 -value => $bad_value );
379 Function: Throws an exception, which, if not caught with an eval or
380 a try block will provide a nice stack trace to STDERR
382 If Error.pm is installed, and if a -class parameter is
383 provided, Error::throw will be used, throwing an error
384 of the type specified by -class.
385 If Error.pm is installed and no -class parameter is provided
386 (i.e., a simple string is given), A Bio::Root::Exception
389 Args : A string giving a descriptive error message, optional
391 '-class' a string for the name of a class that derives
392 from Error.pm, such as any of the exceptions
393 defined in Bio::Root::Exception.
394 Default class: Bio::Root::Exception
395 '-text' a string giving a descriptive error message
396 '-value' the value causing the exception, or $! (optional)
398 Thus, if only a string argument is given, and Error.pm is available,
399 this is equivalent to the arguments:
401 -class => Bio::Root::Exception
402 Comments : If Error.pm is installed, and you don't want to use it
403 for some reason, you can block the use of Error.pm by
404 Bio::Root::Root::throw() by defining a scalar named
405 $main::DONT_USE_ERROR (define it in your main script
406 and you don't need the main:: part) and setting it to
407 a true value; you must do this within a BEGIN subroutine.
412 my ($self, @args) = @_;
414 my ($text, $class, $value) = $self->_rearrange( [qw(TEXT
417 $text ||= $args[0] if @args == 1;
420 # Enable re-throwing of Error objects.
421 # If the error is not derived from Bio::Root::Exception,
422 # we can't guarantee that the Error's value was set properly
423 # and, ipso facto, that it will be catchable from an eval{}.
424 # But chances are, if you're re-throwing non-Bio::Root::Exceptions,
425 # you're probably using Error::try(), not eval{}.
426 # TODO: Fix the MSG: line of the re-thrown error. Has an extra line
427 # containing the '----- EXCEPTION -----' banner.
429 if( $args[0]->isa('Error')) {
430 my $class = ref $args[0];
431 $class->throw( @args );
434 my $text .= "\nWARNING: Attempt to throw a non-Error.pm object: " . ref$args[0];
435 my $class = "Bio::Root::Exception";
436 $class->throw( '-text' => $text, '-value' => $args[0] );
440 $class ||= "Bio::Root::Exception";
443 if( @args % 2 == 0 && $args[0] =~ /^-/ ) {
445 $args{-text
} = $text;
446 $args{-object
} = $self;
449 $class->throw( scalar keys %args > 0 ?
%args : @args ); # (%args || @args) puts %args in scalar context!
454 $class = ': '.$class if $class;
455 my $std = $self->stack_trace_dump();
456 my $title = "------------- EXCEPTION$class -------------";
457 my $footer = ('-' x CORE
::length($title))."\n";
460 die "\n$title\n", "MSG: $text\n", $std, $footer, "\n";
467 Usage : $obj->debug("This is debugging output");
468 Function: Prints a debugging message when verbose is > 0
470 Args : message string(s) to print to STDERR
475 my ($self, @msgs) = @_;
477 # using CORE::warn doesn't give correct backtrace information; we want the
478 # line from the previous call in the call stack, not this call (similar to
479 # cluck). For now, just add a stack trace dump and simple comment under the
480 # correct conditions.
481 if (defined $self->verbose && $self->verbose > 0) {
482 if (!@msgs || $msgs[-1] !~ /\n$/) {
483 push @msgs, "Debugging comment:" if !@msgs;
484 push @msgs, sprintf("%s %s:%s", @
{($self->stack_trace)[2]}[3,1,2])."\n";
493 Usage : $self->_load_module("Bio::SeqIO::genbank");
494 Function: Loads up (like use) the specified module at run time on demand.
496 Returns : TRUE on success. Throws an exception upon failure.
497 Args : The module to load (_without_ the trailing .pm).
502 my ($self, $name) = @_;
503 my ($module, $load, $m);
504 $module = "_<$name.pm";
505 return 1 if $main::{$module};
507 # untaint operation for safe web-based running (modified after
508 # a fix by Lincoln) HL
509 if ($name !~ /^([\w:]+)$/) {
510 $self->throw("$name is an illegal perl package name");
516 my $io = Bio
::Root
::IO
->new();
517 # catfile comes from IO
518 $load = $io->catfile((split(/::/,$load)));
523 $self->throw("Failed to load module $name. ".$@
);
534 my @cleanup_methods = $self->_cleanup_methods or return;
535 for my $method (@cleanup_methods) {