Provided by: libbadger-perl_0.16-2_all bug

NAME

       Badger::Base - base class module

SYNOPSIS

           # define a new object class derived from Badger::Base
           package Your::Badger::Module;
           use base 'Badger::Base';

           sub init {
               my ($self, $config) = @_;

               # $config is a hash of named parameters
               # - let's assume 'name' is mandatory
               $self->{ name } = $config->{ name }
                   || return $self->error('no name specified');

               # save the rest of the config for later
               $self->{ config } = $config;

               # return $self to indicate success
               return $self;
           }

           # ...any other methods follow....

           # now use it
           use Your::Badger::Module
           my $object = Your::Badger::Module->new( name => 'Brian' );

DESCRIPTION

       This module implements a base class object from which most of the other "Badger" modules
       are derived. It implements a number of methods to aid in object creation, configuration,
       error handling and debugging.

       You can use it as a base class for your own modules to inherit the methods that it
       provides.

           package Your::Badger::Module;
           use base 'Badger::Base';

       You can inherit the default new() constructor method and define your own init() method to
       initialise objects.

           sub init {
               my ($self, $config)

               # $config is a hash of named parameters
               # - let's assume 'name' is mandatory
               $self->{ name } = $config->{ name }
                   || return $self->error('no name specified');

               # save the rest of the config in case any other
               # methods want to use it later
               $self->{ config } = $config;

               # return $self to indicate success
               return $self;
           }

       You can then use your module and instantiate objects. The new() method accepts a list or
       reference to a hash array of named parameters.

           use Your::Badger::Module;

           # list of named parameters
           my $object = Your::Badger::Module->new( name => 'Brian' );

           # hash ref of name parameters
           my $object = Your::Badger::Module->new({ name => 'Brian' });

       "Badger::Base" provides a number of other methods that are generally suitable for all (or
       most) objects to inherit.  These include methods for error reporting, debugging and
       raising warnings.

METHODS

   new(\%config)
       This is a general purpose constructor method. It accepts either a reference to a hash
       array of named parameters or a list of named parameters which are then folded into a hash
       reference.

           # hash reference of named params
           my $object = Your::Badger::Module->new({
               arg1 => 'value1',
               arg2 => 'value2',
               ...etc...
           });

           # list of named params
           my $object = Your::Badger::Module->new(
               arg1 => 'value1',
               arg2 => 'value2',
               ...etc...
           );

       The constructor creates a new object by blessing a hash reference and then calling the
       "init()" method. A reference to the hash array of named parameters is passed as a single
       argument. In most cases you should be able to re-use the existing new() method and define
       your own init() method to initialise the object.

       The "new()" method returns whatever the init() method returns. This will normally be the
       $self object reference, but your own init() methods are free to return whatever they like.
       However, it must be a true value of some kind or the new() method will throw an error
       indicating that the init() method failed.

   init(\%config)
       This initialisation method is called by the "new()" constructor method.  This is the
       method that you'll normally want to redefine when you create a subclass of "Badger::Base".

       The "init()" method is passed a reference to a hash array of named configuration
       parameters. The method may perform any configuration or initialisation processes and
       should generally return the $self reference to indicate success.

           sub init {
               my ($self, $config) = @_;

               # set the 'answer' parameter or default to 42
               $self->{ answer } = $config->{ answer } || 42;

               return $self;
           }

       The "init()" method can return any true value which will then be sent back as the return
       value from new(). In most cases you'll want to return the $self object reference, but the
       possibility exists of returning other values instead (e.g. to implement singletons,
       prototypes, or some other clever object trickery).

       If something goes wrong in the "init()" method then you should call the error() method (or
       error_msg()) to throw an error.

           sub init {
               my ($self, $config) = @_;

               # set the 'answer' parameter or report error
               $self->{ answer } = $config->{ answer }
                   || return $self->error('no answer supplied');

               return $self;
           }

       The only function of the default init() method in "Badger::Base" is to save a reference to
       the $config hash array in "$self->{ config }". If you use the default init() method, or
       add an equivalent line to your own init() method, then you can defer inspection of the
       configuration parameters until later. For example, you might have a method which does
       something like this:

           our $DATE_FORMAT = '%Y-%d-%b';

           sub date_format {
               my $self = shift;
               return @_
                   ? ($self->{ date_format } = shift)      # set from argument
                   :  $self->{ date_format }               # get from self...
                  ||= $self->{ config }->{ date_format }   #  ...or config...
                  ||  $DATE_FORMAT;                        #  ...or pkg var
           }

       This allows you to use "$self->{date_format}" as a working copy of the value while keeping
       the original configuration value (if any) intact in "$self->{config}->{date_format}". The
       above method will set the value if you pass an argument and return the current value if
       you don't. If no current value is defined then it defaults to the value in the config hash
       or the $DATE_FORMAT package variable. Now any other methods that require access to a date
       format need only call to the "date_format()" method to have it Do The Right Thing.

       The benefit here is that you don't have to waste time (and memory) in the init() method
       copying the "date_format" parameter from $config into $self. That doesn't mean that it's
       always the right thing to do, but it can be useful for configuration options that are
       infrequently used.

       The on_error() and on_warn() methods follow this protocol. They look for an "ON_ERROR" or
       "ON_WARN" item in $self or an "on_error" or "on_warn" parameter in "$self->{config}". If
       you want to define "on_error" and/or "on_warn" handlers as configuration parameters then
       you'll need to either copy the $config reference into "$self->{config}" or copy the
       individual items into "$self->{ON_ERROR}" and/or "$self->{ON_WARN}", respectively.

           # either copy the config...
           sub init {
               my ($self, $config) = @_;
               $self->{ config } = $config;
               # ...more code...
               return $self;
           }

           # ...or the individual items
           sub init {
               my ($self, $config) = @_;

               # no need to check if either of these are defined because the
               # on_warn() and on_error() methods will Do The Right Thing.
               $self->{ ON_WARN  } = $config->{ on_warn  };
               $self->{ ON_ERROR } = $config->{ on_error };

               # ...more code...
               return $self;
           }

       With either of the above in place, you can then define "on_warn" and "on_error" handlers
       and expect them to work when the error() and warn() methods are called.

           my $object = Your::Badger::Module->new(
               on_warn  => \&my_warn,
               on_error => \&my_error,
           );

           $object->warn("Rebel Alliance engaging");    # calls my_warn()
           $object->error("Exhaust port unshielded!");  # calls my_error()

   warn($message)
       A method to raise a warning.  The default behaviour is to forward all arguments to Perl's
       "warn" function.  However, you can install your own warning handlers on a per-class or
       per-object basis using the on_warn() method or by setting a $ON_WARN package variable in
       your module.  See on_warn() for further details.

           $object->warn("Careful with that axe, Eugene!");

   on_warn($handler, $another_handler, ...)
       This method allows you to install one or more callback handlers which are called whenever
       a warning is raised via the warn() method. Multiple handlers can be installed and will be
       called in turn whenever an error occurs.  The warning message is passed as an argument to
       the handlers.

       For example, if you wanted to forward warning messages to your favourite logging tool, you
       might do something like this:

           my $log = My::Fave::Log::Tool->new(%log_config);

           $object->on_warn(
               sub {
                   my $message = shift;
                   $log->warning("$message);
                   return $message;
               }
           );

       The value returned from the callback is forwarded to the next handler (if there is one).
       If a callback returns a false value or an empty list then the remaining handlers will not
       be called.

       The default behaviour of the "on_warn()" method is to replace any existing warning
       handlers with the new one(s) specified.  You can prefix the handler(s) with 'before' or
       'after' to add them to the existing list of handlers. e.g.

           $object->on_warn( before => \&one, \&two );
           $object->on_warn( after  => \&one, \&two );

       The on_warn() method returns a reference to the list, so you can also monkey about with it
       directly if you want the handler(s) to go somewhere else.

           my $handlers = $object->on_warn;
           shift(@$handlers, \&one);       # add before existing handlers
           push(@$handlers, \&two);        # add after existing handlers

       You can also specify a method name as a warning handler. For example, if you want to
       automatically upgrade all warnings to errors for a particular object, you can write this:

           $object->on_warn('error');      # calls $object->error() on warnings

       You can also specify 'warn' as a handler which will call Perl's "warn()" function.  This
       is the default value.  To explicitly disable any handlers, you can use a value of 0.

           $object->on_warn('warn');       # raise warning - the default action
           $object->on_warn(0);            # no warnings

       These values can be imported from Badger::Constants as the "WARN" and "NONE" constants.

           use Badger::Constants 'WARN NONE';
           $object->on_warn(WARN);         # raise warning - the default action
           $object->on_warn(NONE);         # no warnings

       The on_warn() method works equally well as a class method. In this case it sets the
       $ON_WARN package variable for the class. This acts as the default handler list for any
       objects of that class that don't explicitly define their own warning handlers.

           Your::Badger::Module->on_warn(\&handler_sub);

       If you prefer you can define this using the $ON_WARN package variable.  This will then be
       used as the default for all objects of this class.

           package Your::Badger::Module;
           use base 'Badger::Base';
           our $ON_WARN = \&handler_sub;

       Multiple values should be defined using a list reference.  Method names and the special
       "warn" flag can also be included.

           our $ON_WARN = [ \&this_code_first, 'this_method_next', 'warn' ]

   error($message)
       The "error()" method is used for error reporting.  When an object method fails for some
       reason, it calls the "error()" method passing an argument denoting the problem that
       occurred.  This causes an exception object to be created (see Badger::Exception) and
       thrown via "throw()".  In this case the "error()" method will never return.

           sub engage {
               my $self = shift;
               return $self->error('warp drive offline');
           }

       Multiple arguments can be passed to the "error()" method.  They are concatenated into a
       single string.

           sub engage {
               my $self = shift;
               return $self->error(
                   'warp drive ',
                    $self->{ engine_no },
                   ' is offline'
               );
           }

       The error method can also be called without arguments to return the error message
       previously thrown by a call to "error()". In this case it performs exactly the same
       function as the reason() method.

           eval { $enterprise->engage }
               || warn "Could not engage: ", $enterprise->error;

       The fact that the "error()" method can be called without arguments allows you to write
       things like this:

           # doesn't throw anything if list is empty
           $self->error(@list_of_errors);

       An existing exception object can also be passed as a single argument to the error method.
       In this case, the exception object is re-thrown unmodified.

           sub save_the_world {
               eval { $self->world_peace };

               if ($@) {
                   $self->call_international_rescue($@);   # call Thunderbirds
                   return $self->error($@);                # re-throw error
               };
           }

       ASIDE: You may have noticed in these examples that I'm using the "return" keyword when
       raising an error.  For example:

           return $self->error('warp drive offline');

       The "error()" method doesn't return when you call it with arguments so the "return"
       keyword has no effect whatsoever. However, I like to put it there to give a clear
       indication of what my intentions are at that point. It also means that the code will
       continue to return even if a subclass should "accidentally" define a different error()
       method that doesn't throw an error (don't laugh - it happens). It's also useful when used
       in conjunction with syntax highlighting to see at a glance where the potential exit points
       from a method are (assuming you make "return" bright red or something obvious like I do).

       The "error()" method can also be called as a class method. In this case, it updates and
       retrieves the $ERROR package variable in the package of the subclass module. This can be
       used to raise and examine errors thrown by class methods.

           # calling package error() method
           my $object = eval { Your::Badger::Module->new() }
               || warn "Could not create badger module: ",
                       Your::Badger::Module->error();

           # accessing $ERROR package variable
           my $object = eval { Your::Badger::Module->new() }
               || warn 'Could not create badger module: ",
                       $Your::Badger::Module::ERROR;

   on_error($handler, $another_handler, ...)
       This method is similar to on_warn() in allowing you to install a callback handler which is
       called whenever an error is raised via the error() method (or the error_msg() wrapper).

           $world->on_error(
               sub {
                   my $message = shift;

                   Thunderbirds->call({
                       priority => IR_PRIORITY_HIGH,
                       message  => $message,
                   });

                   return $message;    # forward message to next handler
               }
           );

       The value returned from the callback is forwarded to the next handler.  If a callback
       returns a false value or an empty list then the remaining handlers will not be called.
       However, the error will still be raised regardless of what any of the handlers do or
       return.

   decline($reason, $more_reasons, ...)
       The "decline()" method is used to indicate that a method failed but without raising an
       error. It is typically used for methods that are asked to fetch a resource (e.g. a record
       in a database, file in a filesystem, etc.) that may not exist. In the case where it isn't
       considered an error if the requested resource is missing then the method can call the
       decline() method. It works like error() in that it stores the message internally for later
       inspection via reason(). But instead of throwing the message as an exception, it simply
       returns "undef"

           sub forage {
               my ($self, $name) = @_;

               # hard error if database isn't connected
               my $db = $self->{ database }
                   || return $self->error('no database')

               if ($thing = $db->fetch_thing($name)) {
                   # return true value on success
                   return $thing;
               }
               else {
                   # soft decline if not found
                   return $self->decline("not found: $name")
               }
           }

       Like error(), the decline() method can be called without arguments to return the most
       recent decline message, although it's probably better to use reason() which is designed
       specifically for that purpose.  The decline() method can also be called as a class method
       as well as an object method, as per error().

   declined()
       Returns the values of the internal flag which indicates if an object declined by calling
       the decline() method.  This is set to 1 whenever the decline() method is called and
       cleared back to 0 whenever the error() method is called.

           my $result = eval { $forager->fetch('nuts') };

           if ($result) {
               print "result: $result\n";
           }
           elsif ($forager->declined) {
               print "declined: ", $forager->reason, "\n";
           }
           else {
               print "error: ", $forager->reason, "\n";
           }

   reason()
       Returns the message generated by the most recent call to error() or decline() (or any of
       the wrapper methods like error_msg() and decline_msg()).

           $forager->forage('nuts and berries')
               || die $forager->reason;

   message($type, @args)
       This method generates a message using a pre-defined format. Message formats should be
       defined in a $MESSAGES package variable in the object's package or one of its base
       classes.

           # base class
           package Badger::Example::One
           use base 'Badger::Base';

           our $MESSAGES = {
               hai => 'Hello %s',
           };

           # subclass
           package Badger::Example::Two;
           use base 'Badger::Example::One';

           our $MESSAGES = {
               bye => 'Goodbye %s',
           };

           # using the classes
           package main;

           my $two = Badger::Example::Two->new();
           $two->message( hai => 'World' );    # Hello World
           $two->message( bye => 'World' );    # Goodbye World

       The $two object can use message formats defined in its own package
       ("Badger::Example::Two") and also those of its base class ("Badger::Example::One").

       The messages are formatted using the xprintf() function in Badger::Utils. This is a thin
       wrapper around the built-in "sprintf()" function with some additional formatting controls
       to simplify the process of using positional arguments.

       Messages are used internally by the error_msg() and decline_msg() methods for generating
       error messages, but you can use them for any kind of simple message generation.

       There are a number of benefits to defining messages in a central repository like this.

       First, it makes it easy to reuse the same message format in different places.  Also known
       as the "DRY" principle - Don't Repeat Yourself.

       Second, it allows you to put all your messages in one place instead of dotting them all
       over your code. The benefit here is a clearer separation of concerns between the
       underlying logic of your application and the presentational aspects.

       The third benefit comes as a result of this clear separation - it becomes trivially easy
       to change the messages generated by your application because they're all defined in one
       place (possibly in several different modules if that's how you choose to break it down,
       but at least they're in one place in each of those modules). Possible applications of this
       include: localising an application to different spoken languages; generating messages in
       colour (as the Badger::Debug and Badger::Test modules do); or formatting messages as HTML.

   warn_msg($message, @args)
       This is a wrapper around the warn() and message() methods.  The first argument defines a
       message format.  The remaining arguments are then applied to that format via the message()
       method.  The resulting output is then forwarded to the warn() method.

           our $NAME     = 'Badger';
           our $MESSAGES = {
               using_default => "Using default value for %s: %s",
           };

           sub init {
               my ($self, $config) = @_;

               if ($config->{ name }) {
                   $self->{ name } = $config->{ name };
               }
               else {
                   $self->warn_msg( using_default => name => $NAME );
                   $self->{ name } = $NAME;
               }

               return $self;
           }

       If a "name" isn't provided as a configuration parameter then the default $NAME will be
       used and the following warning will be generated:

           Using default value for name: Badger

   error_msg($message, @args)
       This is a wrapper around the error() and message() methods, similar to warn_msg().

           package Your::Zoo;
           use base 'Badger::Base';

           our $MESSAGES = {
               not_found => "I can't find the %s you asked for: %s",
           }

           sub animal {
               my ($self, $name) = @_;

               return $self->fetch_an_animal($name)
                   || $self->error_msg( missing => animal => $name );
           }

       Calling the "animal()" method on this object with an animal that can't be found, like
       this:

           $zoo->animal('Badgerpotamus');

       Will generate an error message like this:

           your.zoo error - I can't find the animal you asked for: Badgerpotamus

   decline_msg($message, @args)
       This is a wrapper around the decline() and message() methods, similar to warn_msg() and
       error_msg().

           our $MESSAGES = {
               not_found => 'No %s found in the forest',
           };

           sub forage {
               my ($self, $name) = @_;

               return $self->database->fetch_item($name)
                   || $self->decline_msg( not_found => $name );
           }

       The reason() method can be used to return the message generated.

           my $food = $forager->forage('nuts')
               || warn $forager->reason;       # No nuts found in the forest

   fatal_msg($message, @args)
       This is a wrapper around the fatal() and message() methods, similar to error_msg() and co.

   throw($type, $info, %more_info)
       This method throws an exception by calling "die()".  It can be called with one argument,
       which can either be a Badger::Exception object (or subclass), or an error message which is
       upgraded to an exception object (which makes it behave exactly the same as error()).

           # error message - same thing as error()
           $object->throw('an error has occurred');

           # exception object
           $e = Badger::Exception->new(
               type => 'engine',
               info => 'warp drive offline'
           );
           $object->throw($e);

       In the first case, the exception() and throws() methods will be called to determine the
       exception class (Badger::Exception by default) and type for the exception, respectively.

       The method can also be called with two arguments. The first defines the exception "type",
       the second the error message.

           $object->throw( engine => 'warp drive offline' );

       The second argument can also be another exception object.  If the exception has the same
       type as the first argument then it is re-thrown unchanged.

           $e = Badger::Exception->new(
               type => 'engine',
               info => 'warp drive offline'
           );
           $object->throw( engine => $e ) };

       In the example above, the $e exception already has a type of "engine" and so is thrown
       without change.  If the exception types don't match, or if the exception isn't the right
       kind of exception object that we're expecting (as reported by exception()) then a new
       exception is thrown with the old one attached via the "info" field.

            $object->throw( propulsion => $e );

       Here a new "propulsion" exception is thrown, with the previous "engine" exception linked
       in via the "info" field. The exception object has type() and info() methods that allow you
       to inspect its value, iteratively if necessary. Or you can just print an exception and
       rely on its overloaded stringification operator to call the text() method. For the error
       thrown in the previous example, that would be:

           propulsion error - engine error - warp drive offline

   throw_msg($type, $message, @args)
       This is a wrapper around the throw() and message() methods for throwing custom exceptions
       using message formats to generate the error information string. The first argument defines
       the exception type. The second is the name of the message format. The remaining arguments
       are uses to populate the placeholders in the message format.

           our $MESSAGES = {
               offline => '%s is offline',
           };

           sub engage {
               my $self = shift;
               $self->throw_msg( warp => offline => 'warp drive' )
                   unless $self->warp_drive_ready;
               # make it so
           }

           # throws the following exception:
           warp error - warp drive is offline

   try($method, @args)
       This method wraps another method call in an "eval" block to catch any exceptions thrown.

           my $result = $object->try( fetch => 'answer' ) || 42;

       This example is equivalent to:

           my $result = eval { $object->fetch('answer') } || 42;

       The error thrown can be retrieved using the "reason()" method.

           my $result = $object->try( fetch => 'answer' )|| do {
               warn "Could not fetch answer: ", $object->reason;
               42;     # a sensible default
           };

       If you call the "try()" method without any arguments then it will return a
       "Badger::Base::Trial" object as a wafer thin wrapper around the original object.  Any
       methods called on this delegate object will be forwarded to the original object, wrapped
       up in an "eval" block to catch any errors thrown.

           my $result = $object->try->fetch('answer') ||= do {
               ...
           };

   catch($type, $method, @args)
       TODO - this method depends on some code in Badger::Exception which I haven't written yet.

   throws($type)
       You can set the default exception type for throw() by calling the throws() method with an
       argument, either as an object method (to affect that object only) or as a class method (to
       affect all objects that don't set their own value explicitly).  Note that the error() and
       error_msg() methods call throw() internally, so changing the exception type will also
       affect the exceptions thrown by those methods.

           # object method
           $object->throws('food');
           $object->throw('No nuts');              # food error - No nuts
           $object->error('No nuts');              # food error - No nuts

           # class method
           Badger::Example->throws('food');
           Badger::Example->throw('No berries');   # food error - No berries
           Badger::Example->error('No berries');   # food error - No berries

           # all objects of this class now throw food by default
           my $badger = Badger::Example->new;
           $badger->throw('No cheese');            # food error - No cheese
           $badger->error('No cheese');            # food error - No cheese

       You can also set this value for an object by passing a "throws" configuration parameter to
       the new() constructor method.

           my $badger = Badger::Example->new(
               throws => 'food',
           );

       This relies on the default behaviour of the init() method which stores a reference to the
       original configuration parameters in "$self->{config}".  If you want to use this feature
       then you should ensure that any specialised init() method you define does the same thing,
       or copies the "throws" value from $config into "$self->{THROWS}".

           # example 1: store entire config for later
           sub init {
               my ($self, $config) = @_;
               $self->{ config } = $config;
               # do other stuff
               return $self;
           }

           # example 2: extract specific parameter up front
           sub init {
               my ($self, $config) = @_;
               $self->{ THROWS } = $config->{ throws };
               # do other stuff
               return $self;
           }

       You can set the default exception type for your own modules that inherit from
       "Badger::Base" by adding a $THROWS package variable;

           package Badger::Example;
           use base 'Badger::Base';
           our $THROWS = 'food';

       If you don't specify an exception type then one will be generated from the module's class
       name using the id() method in Badger::Class.

   exception($class)
       This method can be used to get or set the exception class for an object.  The default
       value is Badger::Exception.

           use Badger::Example;
           use Some::Other::Exception;
           Badger::Example->exception('Some::Other::Exception');

           # now Badger::Example objects throw Some::Other::Exception

       You can set the default exception class for your own modules that inherit from
       "Badger::Base" by adding a $EXCEPTION package variable;

           package Badger::Example;
           use base 'Badger::Base';
           use Some::Other::Exception;
           our $EXCEPTION = 'Some::Other::Exception';

   fatal($info, $more_info, ...)
       This method is used internally to raise a fatal error.  It bypasses the normal error
       reporting mechanism and dies with a stack backtrace by calling "confess()" (see Carp).

       The most common reason for a fatal error being raised is calling the message() method (or
       either of the error_msg() or decline_msg() wrapper methods) with a message format that
       doesn't exist. The stack backtrace will tell you where in your code you're making the call
       so you can easily find and fix it.

   not_implemented($what)
       A method of convenience which raises an error indicating that the method isn't implemented

           sub example_method {
               shift->not_implemented;
           }

       Calling the "example_method()" would result in an error message similar to this (shown
       here split across two lines):

           your.badger.module error - example_method() is not implemented
           for Your::Badger::Module in /path/to/your/script.pl at line 42

       Note that it tells you where the "example_method()" was called from, not where the method
       is defined.

       The "not_implemented()" method is typically used in methods defined in a base classes that
       subclasses are expected to re-define (a.k.a. pure virtual methods or abstract methods).

       You can pass an argument to be more specific about what it is that isn't implemented.

           sub example_method {
               shift->not_implemented('in base class');
           }

       The argument is added to the generated error message following the method name.  A single
       space is also added to separate them.

           your.badger.module error - example_method() is not implemented in
           base class for Your::Badger::Module in ...etc...

   todo($what)
       A method of convenience useful during developing to indicate that a method isn't
       implemented yet.  It raises an error stating that the method is still TODO.

           sub not_yet_working {
               shift->todo;
           }

       The error message generated looks something like this:

           your.badger.module error - not_yet_working() is TODO in
           Your::Badger::Module at line 42

       You can pass an argument to be more specific about what is still TODO.

           sub not_yet_working {
               my ($self, $x) = @_;
               if (ref $x) {
                   $self->todo('support for references');
               }
               else {
                   # do something
               }
           }

       The error message generated would then be:

           your.badger.module error - not_yet_working() support for
           references is TODO in Your::Badger::Module at line 42

   debug($msg1,$msg2,...)
       This method is mixed in from the Badger::Debug module. It provides a simple way of
       generating debugging messages which include the source module and line number where the
       message was generated.

           sub example {
               my $self = shift;
               $self->debug('entered example()');
               # ... some code ...
               $self->debug('leaving example()');
           }

   debug_msg($message, @args)
       This is a wrapper around the debug() and message() methods, similar to warn_msg(),
       error_msg() and friends.

           our $MESSAGES = {
               here => 'You are in %s',
           };

           sub example {
               my $self = shift;

               $self->debug_msg(
                   here => 'a maze of twisty little passages, all alike'
               ) if DEBUG;

               # ... some code ...

               $self->debug_msg(
                   here => 'boat, floating on a sea of purest green'
               ) if DEBUG;
           }

   debug_up($level,$msg1,$msg2,...)
       Another debugging method mixed in from Badger::Debug.  This is a wrapper around debug()
       which reports the file and line number of a caller higher up the call stack.  This is
       typically used when you create your own debugging methods, as shown in the following
       example.

           sub parse {
               my $self = shift;

               while (my ($foo, $bar) = $self->get_foo_bar) {
                   $self->trace($foo, $bar);               # report line here
                   # do something
               }
           }

           sub trace {
               my ($self, $foo, $bar) = @_;
               $self->debug_up(2, "foo: $foo  bar: $bar"); # not here
           }

       See Badger::Debug for further details.

PACKAGE VARIABLES

       The "Badger::Base" module uses a number of package variables to control the default
       behaviour of the objects derived from it.

   $DEBUG
       This flag can be set true to enable debugging in "Badger::Base".

           $Badger::Base::DEBUG = 1;

       The "Badger::Base" module does not use or define any $DEBUG variable in the subclasses
       derived from it.  However, you may want to do something similar in your own modules to
       assist in debugging.

           package Your::Badger::Module;
           use base 'Badger::Base';

           # allow flag to be set before this module is loaded
           our $DEBUG = 0 unless defined $DEBUG;

           sub gnarly_method {
               my ($self, $item) = @_;
               $self->debug("gnarly_method($item)\n") if $DEBUG;
               # your gnarly code
           }

       The "Badger::Class" module defines the "debug" method and import hook which will
       automatically define a $DEBUG variable for you.

           package Your::Badger::Module;

           use Badger::Class
               base  => 'Badger::Base',
               debug => 0;

   $DECLINED
       This package variable is defined in each subclass derived from "Badger::Base". It is a
       boolean (0/1) flag used by the error(), decline() and declined() methods. The decline()
       method sets it to 1 to indicate that the object declined a request. The error() method
       clears it back to 0 to indicate that a hard error occurred. The declined() method simply
       returns the value.

   $ERROR
       This package variable is defined in each subclass derived from "Badger::Base".  It stores
       the most recent error message raised by decline() or error().

   $EXCEPTION
       This package variable is used to define the name of the class that should be used to
       instantiate exception objects.  The default value in "Badger::Base" is
       "Badger::Exception".

       Subclasses may define an $EXCEPTION package variable to change this value.

           package Your::Badger::Module;
           use base 'Badger::Base';
           use Your::Exception;
           our $EXCEPTION = 'Your::Exception';

       Those that don't explicitly define an $EXCEPTION will inherit the value from any of their
       base classes, possibly coming all the way back up to the default value in "Badger::Base".

       Calling the "exception()" class method with an argument will update the $EXCEPTION package
       variable in that class.

           # sets $Your::Badger::Module::EXCEPTION
           Your::Badger::Module->exception('Your::Exception');

   $MESSAGES
       This package variable is used to reference a hash array of messages that can be used with
       the message(), warn_msg(), error_msg() and decline_msg() methods. The "Badger::Base"
       module defines a number of messages that it uses internally.

           our $MESSAGES = {
               not_found       => '%s not found: %s',
               not_found_in    => '%s not found in %s',
               not_implemented => '%s is not implemented %s',
               no_component    => 'No %s component defined',
               bad_method      => "Invalid method '%s' called on %s at %s line %s",
               invalid         => 'Invalid %s specified: %s',
               unexpected      => 'Invalid %s specified: %s (expected a %s)',
               missing_to      => 'No %s specified to %s',
               missing         => 'No %s specified',
               todo            => '%s is TODO %s',
               at_line         => '%s at line %s',
               at_file_line    => '%s in %s at line %s',
           };

       The message() method searches for $MESSAGES in the current class and those of any base
       classes.  That means that any objects derived from "Badger::Base" can use these message
       formats.

           package Your::Badger::Module;
           use base 'Badger::Base';

           sub init {
               my ($self, $config) = @_;
               $self->{ name } = $config->{ name }
                   || $self->error_msg( missing => $name );
               return $self;
           }

       You can define additional $MESSAGES for your own classes.

           package Your::Badger::Module;
           use base 'Badger::Base';

           our $MESSAGES = {
               life_jim  => "It's %s Jim, but not as we know it",
           }

           sub bones {
               my ($self, $thing)= @_;
               $self->warn_msg( life_jim => $thing );
               return $self;
           }

       Calling the "bones()" method like this:

           $object->bones('a badger');

       will generate a warning like this:

           It's a badger Jim, but not as we know it.

   $ON_ERROR
       This package variable is used to define one or more error handlers that will be invoked
       whenever the error() method is called.

       The "Badger::Base" module doesn't define any $ON_ERROR package variable by default.  The
       on_error() method can be called as a class method to set the $ON_ERROR package variable.

           Your::Badger::Module->on_error(\&my_handler);

       You can also define an $ON_ERROR handler or list of handlers in your module.

           package Your::Badger::Module;
           use base 'Badger::Base';

           # one of the following...
           our $ON_ERROR = 'warn';         # call Perl's warn()
           our $ON_ERROR = 'method_name';
           our $ON_ERROR = \&code_ref;
           our $ON_ERROR = [ 'warn', 'method_name', \&code_ref ];

           # code refs get message as first argument
           sub code_ref {
               my $message = shift;
               # do something...
           }

           # methods get implicit $self, then message argument
           sub method_name {
               my ($self, $message) = @_;
               # do something...
           }

   $ON_WARN
       This package variable is used to define one or more error handlers that will be invoked
       whenever the warning() method is called.  It works in exactly the same way as $ON_ERROR.

   $THROWS
       This package variable is used to define the default exception type thrown by the throw()
       method (and error() and error_msg() which call it indirectly).  It can be set by calling
       the throws() class method.

           Your::Badger::Module->throws('food');

       You can define $THROWS in your own modules that are derived from "Badger::Base".

           package Your::Badger::Module;
           use base 'Badger::Base';
           our $THROWS = 'food';

       If the $THROWS value is not defined in the current class or any of an object's base
       classes, then the id() method is used to construct an identifier for the module to use
       instead.

OBJECT INTERNALS

       The "Badger::Base" module uses the following internal object items to store information.

   config
       The default init() method stores a reference to the hash array of configuration parameters
       in the "$self->{config}" slot. If you're using the default init() method then your other
       methods can use this to lookup configuration parameters lazily.

       If you've defined your own init() method then this item won't exist unless your init()
       method adds it explicitly.

   DECLINED
       The value of the declined flag, as per the $DECLINED package variable.

   ERROR
       The last error raised, as per the $ERROR package variable.

   EXCEPTION
       Used to store the class name that should used to instantiate exceptions.  Equivalent to
       the $EXCEPTION package variable but operating on a per-object basis. Can be inspected or
       modified by calling the exception() object method.

   ON_ERROR
       An internal list of handlers to call when an error is raised.  Equivalent to the $ON_ERROR
       package variable but operating on a per-object basis.  Can be inspected or modified by
       calling the on_error() object method.

   ON_WARN
       An internal list of handlers to call when a warning is raised.  Equivalent to the $ON_WARN
       package variable but operating on a per-object basis.  Can be inspected or modified by
       calling the on_warn() object method.

   THROWS
       Used to store the exception type that the object should throw.  Equivalent to the $THROWS
       package variable but operating on a per-object basis.  Can be inspected or modified by
       calling the throws() object method.

AUTHOR

       Andy Wardley <http://wardley.org/>

COPYRIGHT

       Copyright (C) 1996-2009 Andy Wardley.  All Rights Reserved.

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