1 package Bio
::Root
::Root
;
4 use Bio
::Root
::Version
;
5 use Scalar
::Util
qw(blessed reftype);
6 use base
qw(Bio::Root::RootI);
8 our $VERSION = eval "$VERSION";
12 # Any Bioperl-compliant object is a RootI compliant object
14 # Here's how to throw and catch an exception using the eval-based syntax.
16 $obj->throw("This is an exception");
19 $obj->throw("This is catching an exception");
23 print "Caught exception";
28 # Alternatively, using the new typed exception syntax in the throw() call:
30 $obj->throw( -class => 'Bio::Root::BadParameter',
31 -text => "Can not open file $file",
34 # Want to see debug() outputs for this object
36 my $obj = Bio::Object->new(-verbose=>1);
38 my $obj = Bio::Object->new(%args);
41 # Print debug messages which honour current verbosity setting
43 $obj->debug("Boring output only to be seen if verbose > 0\n");
47 my $clone = $obj->clone;
51 This is a hashref-based implementation of the Bio::Root::RootI
52 interface. Most Bioperl objects should inherit from this.
54 See the documentation for L<Bio::Root::RootI> for most of the methods
55 implemented by this module. Only overridden methods are described
58 =head2 Throwing Exceptions
60 One of the functionalities that L<Bio::Root::RootI> provides is the
61 ability to L<throw>() exceptions with pretty stack traces. Bio::Root::Root
62 enhances this with the ability to use L<Error> (available from CPAN)
63 if it has also been installed.
65 If L<Error> has been installed, L<throw>() will use it. This causes an
66 Error.pm-derived object to be thrown. This can be caught within a
67 C<catch{}> block, from which you can extract useful bits of
68 information. If L<Error> is not installed, it will use the
69 L<Bio::Root::RootI>-based exception throwing facilty.
71 =head2 Typed Exception Syntax
73 The typed exception syntax of L<throw>() has the advantage of plainly
74 indicating the nature of the trouble, since the name of the class
75 is included in the title of the exception output.
77 To take advantage of this capability, you must specify arguments
78 as named parameters in the L<throw>() call. Here are the parameters:
84 name of the class of the exception.
85 This should be one of the classes defined in L<Bio::Root::Exception>,
86 or a custom error of yours that extends one of the exceptions
87 defined in L<Bio::Root::Exception>.
91 a sensible message for the exception
95 the value causing the exception or $!, if appropriate.
99 Note that Bio::Root::Exception does not need to be imported into
100 your module (or script) namespace in order to throw exceptions
101 via Bio::Root::Root::throw(), since Bio::Root::Root imports it.
103 =head2 Try-Catch-Finally Support
105 In addition to using an eval{} block to handle exceptions, you can
106 also use a try-catch-finally block structure if L<Error> has been
107 installed in your system (available from CPAN). See the documentation
108 for Error for more details.
110 Here's an example. See the L<Bio::Root::Exception> module for
111 other pre-defined exception types:
115 open $IN, '<', $file or $obj->throw( -class => 'Bio::Root::FileOpenException',
116 -text => "Cannot read file '$file'",
119 catch Bio::Root::BadParameter with {
120 my $err = shift; # get the Error object
121 # Perform specific exception handling code for the FileOpenException
123 catch Bio::Root::Exception with {
124 my $err = shift; # get the Error object
125 # Perform general exception handling code for any Bioperl exception.
128 # A catch-all for any other type of exception
131 # Any code that you want to execute regardless of whether or not
132 # an exception occurred.
134 # the ending semicolon is essential!
136 =head1 AUTHOR Steve Chervitz
138 Ewan Birney, Lincoln Stein
142 our ($DEBUG, $ID, $VERBOSITY, $ERRORLOADED, $CLONE_CLASS);
145 $ID = 'Bio::Root::Root';
150 # Check whether or not Error.pm is available.
152 # $main::DONT_USE_ERROR is intended for testing purposes and also
153 # when you don't want to use the Error module, even if it is installed.
154 # Just put a INIT { $DONT_USE_ERROR = 1; } at the top of your script.
155 if( not $main::DONT_USE_ERROR
) {
156 if ( eval "require Error; 1;" ) {
157 import Error
qw(:try);
158 require Bio
::Root
::Exception
;
160 $Error::Debug
= 1; # enable verbose stack trace
163 if( !$ERRORLOADED ) {
164 require Carp
; import Carp
qw( confess );
168 for my $class (qw(Clone Storable)) {
169 eval "require $class; 1;";
171 $CLONE_CLASS = $class;
172 if ($class eq 'Clone') {
173 *Bio
::Root
::Root
::_dclone
= sub {shift; return Clone
::clone
(shift)};
175 *Bio
::Root
::Root
::_dclone
= sub {
177 local $Storable::Deparse
= 1;
178 local $Storable::Eval
= 1;
179 return Storable
::dclone
(shift);
185 if (!defined $CLONE_CLASS) {
186 *Bio
::Root
::Root
::_dclone
= sub {
187 my ($self, $orig, $level) = @_;
188 my $class = Scalar
::Util
::blessed
($orig) || '';
189 my $reftype = Scalar
::Util
::reftype
($orig) || '';
193 } elsif ($reftype eq "ARRAY") {
194 $data = [map $self->_dclone($_), @
$orig];
195 } elsif ($reftype eq "HASH") {
196 $data = { map { $_ => $self->_dclone($orig->{$_}) } keys %$orig };
197 } elsif ($reftype eq 'CODE') { # nothing, maybe shallow copy?
198 $self->throw("Code reference cloning not supported; install Clone or Storable from CPAN");
199 } else { $self->throw("What type is $_?")}
207 $main::DONT_USE_ERROR
; # so that perl -w won't warn "used only once"
212 Purpose : generic instantiation function can be overridden if
213 special needs of a module cannot be done in _initialize
218 # my ($class, %param) = @_;
221 bless $self, ref($class) || $class;
224 # if the number of arguments is odd but at least 3, we'll give
225 # it a try to find -verbose
228 ## See "Comments" above regarding use of _rearrange().
229 $self->verbose($param{'-VERBOSE'} || $param{'-verbose'});
238 Usage : my $clone = $obj->clone();
240 my $clone = $obj->clone( -start => 110 );
241 Function: Deep recursion copying of any object via Storable dclone()
242 Returns : A cloned object.
243 Args : Any named parameters provided will be set on the new object.
244 Unnamed parameters are ignored.
245 Comments: Where possible, faster clone methods are used, in order:
246 Clone::Fast::clone(), Clone::clone(), Storable::dclone. If neither
247 is present, a pure perl fallback (not very well tested) is used
248 instead. Storable dclone() cannot clone CODE references. Therefore,
249 any CODE reference in your original object will remain, but will not
250 exist in the cloned object. This should not be used for anything
251 other than cloning of simple objects. Developers of subclasses are
252 encouraged to override this method with one of their own.
257 my ($orig, %named_params) = @_;
259 __PACKAGE__
->throw("Can't call clone() as a class method") unless
260 ref $orig && $orig->isa('Bio::Root::Root');
262 # Can't dclone CODE references...
263 # Should we shallow copy these? Should be harmless for these specific
266 my %put_these_back = (
267 _root_cleanup_methods
=> $orig->{'_root_cleanup_methods'},
269 delete $orig->{_root_cleanup_methods
};
271 # call the proper clone method, set lazily above
272 my $clone = __PACKAGE__
->_dclone($orig);
274 $orig->{_root_cleanup_methods
} = $put_these_back{_root_cleanup_methods
};
276 foreach my $key (grep { /^-/ } keys %named_params) {
279 if ($clone->can($method)) {
280 $clone->$method($named_params{$key})
282 $orig->warn("Parameter $method is not a method for ".ref($clone));
291 Usage : my $clone = $obj->_dclone($ref);
293 my $clone = $obj->_dclone($ref);
294 Function: Returns a copy of the object passed to it (a deep clone)
295 Returns : clone of passed argument
297 NOTE : This differs from clone significantly in that it does not clone
298 self, but the data passed to it. This code may need to be optimized
299 or overridden as needed.
300 Comments: This is set in the BEGIN block to take advantage of optimized
301 cloning methods if Clone or Storable is present, falling back to a
302 pure perl kludge. May be moved into a set of modules if the need
303 arises. At the moment, code ref cloning is not supported.
310 Usage : $self->verbose(1)
311 Function: Sets verbose level for how ->warn behaves
313 0 = standard, small warning
314 1 = warning with stack trace
315 2 = warning becomes throw
316 Returns : The current verbosity setting (integer between -1 to 2)
323 my ($self,$value) = @_;
324 # allow one to set global verbosity flag
325 return $DEBUG if $DEBUG;
326 return $VERBOSITY unless ref $self;
328 if (defined $value || ! defined $self->{'_root_verbose'}) {
329 $self->{'_root_verbose'} = $value || 0;
331 return $self->{'_root_verbose'};
334 =head2 _register_for_cleanup
338 sub _register_for_cleanup
{
339 my ($self,$method) = @_;
341 if(! exists($self->{'_root_cleanup_methods'})) {
342 $self->{'_root_cleanup_methods'} = [];
344 push(@
{$self->{'_root_cleanup_methods'}},$method);
348 =head2 _unregister_for_cleanup
352 sub _unregister_for_cleanup
{
353 my ($self,$method) = @_;
354 my @methods = grep {$_ ne $method} $self->_cleanup_methods;
355 $self->{'_root_cleanup_methods'} = \
@methods;
358 =head2 _cleanup_methods
362 sub _cleanup_methods
{
364 return unless ref $self && $self->isa('HASH');
365 my $methods = $self->{'_root_cleanup_methods'} or return;
372 Usage : $obj->throw("throwing exception message");
374 $obj->throw( -class => 'Bio::Root::Exception',
375 -text => "throwing exception message",
376 -value => $bad_value );
377 Function: Throws an exception, which, if not caught with an eval or
378 a try block will provide a nice stack trace to STDERR
380 If Error.pm is installed, and if a -class parameter is
381 provided, Error::throw will be used, throwing an error
382 of the type specified by -class.
383 If Error.pm is installed and no -class parameter is provided
384 (i.e., a simple string is given), A Bio::Root::Exception
387 Args : A string giving a descriptive error message, optional
389 '-class' a string for the name of a class that derives
390 from Error.pm, such as any of the exceptions
391 defined in Bio::Root::Exception.
392 Default class: Bio::Root::Exception
393 '-text' a string giving a descriptive error message
394 '-value' the value causing the exception, or $! (optional)
396 Thus, if only a string argument is given, and Error.pm is available,
397 this is equivalent to the arguments:
399 -class => Bio::Root::Exception
400 Comments : If Error.pm is installed, and you don't want to use it
401 for some reason, you can block the use of Error.pm by
402 Bio::Root::Root::throw() by defining a scalar named
403 $main::DONT_USE_ERROR (define it in your main script
404 and you don't need the main:: part) and setting it to
405 a true value; you must do this within a BEGIN subroutine.
410 my ($self, @args) = @_;
412 my ($text, $class, $value) = $self->_rearrange( [qw(TEXT
415 $text ||= $args[0] if @args == 1;
418 # Enable re-throwing of Error objects.
419 # If the error is not derived from Bio::Root::Exception,
420 # we can't guarantee that the Error's value was set properly
421 # and, ipso facto, that it will be catchable from an eval{}.
422 # But chances are, if you're re-throwing non-Bio::Root::Exceptions,
423 # you're probably using Error::try(), not eval{}.
424 # TODO: Fix the MSG: line of the re-thrown error. Has an extra line
425 # containing the '----- EXCEPTION -----' banner.
427 if( $args[0]->isa('Error')) {
428 my $class = ref $args[0];
429 $class->throw( @args );
432 my $text .= "\nWARNING: Attempt to throw a non-Error.pm object: " . ref$args[0];
433 my $class = "Bio::Root::Exception";
434 $class->throw( '-text' => $text, '-value' => $args[0] );
438 $class ||= "Bio::Root::Exception";
441 if( @args % 2 == 0 && $args[0] =~ /^-/ ) {
443 $args{-text
} = $text;
444 $args{-object
} = $self;
447 $class->throw( scalar keys %args > 0 ?
%args : @args ); # (%args || @args) puts %args in scalar context!
452 $class = ': '.$class if $class;
453 my $std = $self->stack_trace_dump();
454 my $title = "------------- EXCEPTION$class -------------";
455 my $footer = ('-' x CORE
::length($title))."\n";
458 die "\n$title\n", "MSG: $text\n", $std, $footer, "\n";
465 Usage : $obj->debug("This is debugging output");
466 Function: Prints a debugging message when verbose is > 0
468 Args : message string(s) to print to STDERR
473 my ($self, @msgs) = @_;
475 # using CORE::warn doesn't give correct backtrace information; we want the
476 # line from the previous call in the call stack, not this call (similar to
477 # cluck). For now, just add a stack trace dump and simple comment under the
478 # correct conditions.
479 if (defined $self->verbose && $self->verbose > 0) {
480 if (!@msgs || $msgs[-1] !~ /\n$/) {
481 push @msgs, "Debugging comment:" if !@msgs;
482 push @msgs, sprintf("%s %s:%s", @
{($self->stack_trace)[2]}[3,1,2])."\n";
491 Usage : $self->_load_module("Bio::SeqIO::genbank");
492 Function: Loads up (like use) the specified module at run time on demand.
494 Returns : TRUE on success. Throws an exception upon failure.
495 Args : The module to load (_without_ the trailing .pm).
500 my ($self, $name) = @_;
501 my ($module, $load, $m);
502 $module = "_<$name.pm";
503 return 1 if $main::{$module};
505 # untaint operation for safe web-based running (modified after
506 # a fix by Lincoln) HL
507 if ($name !~ /^([\w:]+)$/) {
508 $self->throw("$name is an illegal perl package name");
514 my $io = Bio
::Root
::IO
->new();
515 # catfile comes from IO
516 $load = $io->catfile((split(/::/,$load)));
521 $self->throw("Failed to load module $name. ".$@
);
532 my @cleanup_methods = $self->_cleanup_methods or return;
533 for my $method (@cleanup_methods) {