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

NAME

       Badger::Factory - base class factory module

SYNOPSIS

       This module is designed to be subclassed to create factory classes that automatically load
       modules and instantiate objects on demand.

           package My::Widgets;
           use base 'Badger::Factory';

           # tell the base class factory what we create
           our $ITEM        = 'widget';
           our $ITEMS       = 'widgets';

           # define module search path for widgets
           our $WIDGET_PATH = ['My::Widget', 'Your::Widget'];

           # lookup table for any non-standard spellings/capitalisations/paths
           our $WIDGETS     = {
               url   => 'My::Widget::URL',       # non-standard capitalisation
               color => 'My::Widget::Colour',    # different spelling
               amp   => 'Nigels::Amplifier',     # different path
           };

       You can then use it like this:

           use My::Widgets;

           # class methods (note: widget() is singular)
           $w = My::Widgets->widget( foo => { msg => 'Hello World' } );

           # same as:
           use My::Widget::Foo;
           $w = My::Widget::Foo({ msg => 'Hello World' });

           # add/update widgets lookup table (note: widgets() is plural)
           My::Widgets->widgets(
               extra => 'Another::Widget::Module',
               super => 'Golly::Gosh',
           );

           # now load and instantiate new widget modules
           $w = My::Widgets->widget( extra => { msg => 'Hello Badger' } );

       You can also create factory objects:

           my $factory = My::Widgets->new(
               widget_path => ['His::Widget', 'Her::Widget'],
               widgets     => {
                   extra => 'Another::Widget::Module',
                   super => 'Golly::Gosh',
               }
           );

           $w = $factory->widget( foo => { msg => 'Hello World' } );

       The Badger::Factory::Class module can be used to simplify the process of defining factory
       subclasses.

           package My::Widgets;

           use Badger::Factory::Class
               item    => 'widget',
               path    => 'My::Widget Your::Widget';
               widgets => {
                   extra => 'Another::Widget::Module',
                   super => 'Golly::Gosh',
               };

DESCRIPTION

       This module implements a base class factory object for loading modules and instantiating
       objects on demand. It originated in the Template::Plugins module, evolved over time in
       various directions for other projects, and was eventually pulled back into line to become
       "Badger::Factory".

   Defining a Factory Module
       The "Badger::Factory" module isn't designed to be used by itself. Rather it should be used
       as a base class for your own factory modules. For example, suppose you have a project
       which has lots of "My::Widget::*" modules. You can define a factory for them like so:

           package My::Widgets;
           use base 'Badger::Factory';

           our $ITEM           = 'widget';
           our $ITEMS          = 'widgets';
           our $WIDGET_PATH    = ['My::Widget', 'Your::Widget'];
           our $WIDGET_DEFAULT = 'foo';
           our $WIDGET_NAMES   = {
               html => 'HTML',
           };

           # lookup table for any non-standard spellings/capitalisations/paths
           our $WIDGETS     = {
               url   => 'My::Widget::URL',       # non-standard capitalisation
               color => 'My::Widget::Colour',    # different spelling
               amp   => 'Nigels::Amplifier',     # different path
           };

           1;

       The $ITEM and $ITEMS package variables are used to define the singular and plural names of
       the items that the factory is responsible for.  In this particular case, the $ITEMS
       declaration isn't strictly necessary because the module would correctly "guess" the plural
       name "widgets" from the singular "widget" defined in $ITEM.  However, this is only
       provided as a convenience for those English words that pluralise regularly and shouldn't
       be relied upon to work all the time.  See the pluralise() method in Badger::Utils for
       further information, and explicitly specify the plural in $ITEMS if you're in any doubt.

       The $WIDGET_PATH is used to define one or more base module names under which your widgets
       are located.  The name of this variable is derived from the upper case item name in $ITEM
       with "_PATH" appended.  In this example, the factory will look for the "Foo::Bar" module
       as either "My::Widget::Foo::Bar" or "Your::Widget::Foo::Bar".

       The $WIDGET_DEFAULT specifies the default item name to use if a request is made for a
       module using an undefined or false name.  If you don't specify any value for a default
       then it uses the literal string "default".  Adding a "default" entry to your $WIDGET_NAMES
       or $WIDGETS will have the same effect.

       The $WIDGET_NAMES is used to define any additional name mappings. This is usually required
       to handle alternate spellings or unusual capitalisations that the default name mapping
       algorithm would get wrong. For example, a request for an "html" widget would look for
       "My::Widget::Html" or "Your::Widget::Html".  Adding a $WIDGET_MAP entry mapping "html" to
       "HTML" will instead send it looking for "My::Widget::HTML" or "Your::Widget::HTML".

       If you've got any widgets that aren't located in one of these locations, or if you want to
       provide some aliases to particular widgets then you can define them in the $WIDGETS
       package variable.  The name of this variable is the upper case conversion of the value
       defined in the $ITEMS package variable.

   Using Your Factory Module
       Now that you've define a factory module you can use it like this.

           use My::Widgets;

           my $widgets = My::Widgets->new;
           my $foo_bar = $widgets->widget('Foo::Bar');

       The "widget()" method is provided to load a widget module and instantiate a widget object.

       The above example is equivalent to:

           use My::Widget::Foo::Bar;
           my $foo_bar = My::Widget::Foo::Bar->new;

       Although it's not strictly equivalent because the factory could just has easily have
       loaded it from "Your::Widget::Foo::Bar" in the case that "My::Widget::Foo::Bar" doesn't
       exist.

       You can specify additional arguments that will be forwarded to the object constructor
       method.

           my $foo_bar = $widgets->widget('Foo::Bar', x => 10, y => 20);

       If you've specified a $WIDGET_DEFAULT for your factory then you can call the widget()
       method without any arguments to get the default object.

           my $widget = $widgets->widget;

       You can use the default() method to change the default module.

           $widgets->default('bar');

       The factory module can be customised using configuration parameters. For example, you can
       provide additional values for the "widget_path", or define additional widgets:

           my $widgets = My::Widgets->new(
               widget_path => ['His::Widget', 'Her::Widget'],
               widgets     => {
                   extra => 'Another::Widget::Module',
                   super => 'Golly::Gosh',
               }
           );

       The factory module is an example of a prototype() module.  This means that you can call
       the "widget()" method as a class method to save yourself of explicitly creating a factory
       object.

           my $widget = My::Widgets->widget('Foo::Bar');

METHODS

   new()
       Constructor method to create a new factory module.

           my $widgets = My::Widgets->new;

   path($path)
       Used to get or set the factory module path.

           my $path = $widgets->path;
           $widgets->path(['My::Widgets', 'Your::Widgets', 'Our::Widgets']);

       Calling the method with arguments replaces any existing list.

   names($names)
       Used to get or set the names mapping table.

           my $names = $widgets->names;
           $widgets->names({ html => 'HTML' });

       Calling the method with arguments replaces any existing names table.

   default($name)
       Used to get or set a name for the default item name.  The default value is the literal
       string "default".  This allows you to add a "default" entry to either your names() or
       items() and it will be located automatically.

   items(%items)
       Used to fetch or update the lookup table for mapping names to modules.

           my $items = $widgets->items;
           $widgets->items( foo => 'My::Plugin::Foo' );

       Calling the method with arguments (named parameters or a hash reference) will add the new
       definitions into the existing table.

       This method can also be aliased by the plural name defined in $ITEMS in your subclass
       module.

           $widgets->widgets;

   item($name,@args)
       Method to load a module and instantiate an object.

           my $widget = $widgets->item('Foo');

       Any additional arguments provided after the module name are forwarded to the object's
       "new()" constructor method.

           my $widget = $widgets->item( Foo => 10, 20 );

       This method can also be aliased by the singular name defined in $ITEM in your subclass
       module.

           my $widget = $widgets->widget( Foo => 10, 20 );

       The module name specified can be specified in lower case.  The name is capitalised as a
       matter of course.

           # same as Foo
           my $widget = $widgets->widget( foo => 10, 20 );

       Multi-level names can be separated with dots rather than "::".  This is in keeping with
       the convention used in the Template Toolkit.  Each element after a dot is capitalised.

           # same as Foo::Bar
           my $widget = $widgets->widget( 'foo.bar' => 10, 20 );

INTERNAL METHODS

   type_args(@args)
       This method can be re-defined by a subclass to perform any pre-manipulation on the
       arguments passed to the item() method.  The first argument is usually the type (i.e. name)
       of module requested, followed by any additional arguments for the object constructor.

           my ($self, $type, @args) = @_;

       The method should return them like so:

           return ($type, @args);

   find($type,\@args)
       This method is called to find and dynamically load a module if it doesn't already have an
       entry in the internal "items" table.  It iterates through each of the base paths for the
       factory and calls the load() method to see if the module can be found under that prefix.

   load(@module_names)
       This method is called to dynamically load a module.  It iterates through each of the
       module name passed as arguments until it successfully loads one.  At that point it returns
       the module name that was successfully loaded and ignores the remaining arguments.  If none
       of the modules can be loaded then it returns "undef"

   found($name,$item,\@args)
       This method is called when an item has been found, either in the internal "items" lookup
       table, or by a call to find(). The $item argument is usually a module name that is
       forwarded onto found_module(). However, it can also be a reference which will be forwarded
       onto one of the following methods depending on its type: found_array(), found_hash(),
       found_scalar(), found_object() (and in theory, "found_regex()", "found_glob()" and maybe
       others, but they're not implemented).

       The result returned by the appropriate "found_XXXXX()" method will then be forwarded onto
       the result() method.  The method returns the result from the result() method.

   found_module($module)
       This method is called when a requested item has been mapped to a module name.  The module
       is loaded if necessary, then the construct() method is called to construct an object.

   found_array(\@array)
       An entry in the "items" (aka "widgets" in our earlier example) table can be a reference to
       a list containing a module name and a separate class name.

           my $widgets = My::Widgets->new(
               widgets => {
                   wizbang => ['Wiz::Bang', 'Wiz::Bang::Bash'],
               },
           );

       If the "wizbang" widget is requested from the "My::Widgets" factory in the example above,
       then the found() method will call "found_array()", passing the array reference as an
       argument.

       The module listed in the first element is loaded.  The class name in the second element is
       then used to instantiate an object.

   found_hash(\%hash)
       This method isn't implemented in the base class, but can be defined by subclasses to
       handle the case where a request is mapped to a hash reference.

   found_scalar(\$scalar)
       This method isn't implemented in the base class, but can be defined by subclasses to
       handle the case where a request is mapped to a scalar reference.

   found_object($object)
       This method isn't defined in the base class, but can be defined by subclasses to handle
       the case where a request is mapped to an existing object.

   construct($name,$class,\@args)
       This method instantiates a $class object using the arguments provided.  In the base class
       this method  simply calls:

           $class->new(@$args);

   result($name,$result,\@args)
       This method is called at the end of a successful request after an object has been
       instantiated (or perhaps re-used from an internal cache).  In the base class it simply
       returns $result but can be redefined in a subclass to do something more interesting.

   module_names($type)
       This method performs the necessary mapping from a requested module name to its canonical
       form.

   not_found($name,@args)
       This method is called when the requested item is not found. The method simply throws an
       error using the "not_found" message format. The method can be redefined in subclasses to
       perform additional fallback handing.

   can($method)
       This method implements the magic to ensure that the item-specific accessor methods (e.g.
       "widget()"/"widgets()") are generated on demand.

   AUTOLOAD(@args)
       This implements the other bit of magic to generate the item-specific accessor methods on
       demand.

AUTHOR

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

COPYRIGHT

       Copyright (C) 2006-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.

SEE ALSO

       Badger::Factory::Class, Badger::Codecs.