1#========================================================================
2#
3# Badger::Factory
4#
5# DESCRIPTION
6#   Factory module for loading and instantiating other modules.
7#
8# NOTE
9#   This module has grown organically to fit a number of (possibly
10#   conflicting) needs.  It needs to be completely refactored, and
11#   probably split into a number of different factory modules.  The
12#   TT3 code on which this was originally based had separate base class
13#   factory modules for modules (that just got loaded), objects (that
14#   got loaded and instantiated) and single objects (that got loaded,
15#   created and cached).  With hindsight, it was a mistake to try and
16#   cram all that functionality into one module.  It should be separated
17#   into a base class module/API and a number of specialised subclasses.
18#
19# AUTHOR
20#   Andy Wardley   <abw@wardley.org>
21#
22#========================================================================
23
24package Badger::Factory;
25
26use Badger::Debug ':dump';
27use Badger::Class
28    version   => 0.01,
29    debug     => 0,
30    base      => 'Badger::Prototype Badger::Exporter',
31    import    => 'class',
32    utils     => 'plural blessed textlike dotid camel_case',
33    words     => 'ITEM ITEMS ISA',
34    constants => 'PKG ARRAY HASH REFS ONCE DEFAULT LOADED',
35    constant  => {
36        OBJECT         => 'object',
37        FOUND          => 'found',
38        FOUND_REF      => 'found_ref',
39        PATH_SUFFIX    => '_PATH',
40        NAMES_SUFFIX   => '_NAMES',
41        DEFAULT_SUFFIX => '_DEFAULT',
42    },
43    messages  => {
44        no_item    => 'No item(s) specified for factory to manage',
45        no_default => 'No default defined for %s factory',
46        bad_ref    => 'Invalid reference for %s factory item %s: %s',
47        bad_method => qq{Can't locate object method "%s" via package "%s" at %s line %s},
48    };
49
50our $RUNAWAY = 0;
51our $AUTOLOAD;
52
53*init = \&init_factory;
54
55
56sub init_factory {
57    my ($self, $config) = @_;
58    my $class = $self->class;
59    my ($item, $items, $path, $map, $default);
60
61    # 'item' and 'items' can be specified as config params or we look for
62    # $ITEM and $ITEMS variables in the current package or those of any
63    # base classes.  NOTE: $ITEM and $ITEMS must be in the same package
64    unless ($item = $config->{ item }) {
65        foreach my $pkg ($class->heritage) {
66            no strict   REFS;
67            no warnings ONCE;
68
69            if (defined ($item = ${ $pkg.PKG.ITEM })) {
70                $items = ${ $pkg.PKG.ITEMS };
71                last;
72            }
73        }
74    }
75    return $self->error_msg('no_item')
76        unless $item;
77
78    # use 'items' in config, or grokked from $ITEMS, or guess plural
79    $items = $config->{ items } || $items || plural($item);
80
81    my $ipath    = $item.PATH_SUFFIX;
82    my $inames   = $item.NAMES_SUFFIX;
83    my $idefault = $item.DEFAULT_SUFFIX;
84
85    # Merge all XXXX_PATH package vars with any 'xxxx_path' or 'path' config
86    # items.  Ditto for XXXX_NAME / 'xxxx_name' / 'aka' and  XXXXS/ 'xxxxs'
87
88    my @path  = @$config{ path  => lc $ipath  };
89    my @names = @$config{ names => lc $inames };
90
91    $self->{ path     } = $class->list_vars(uc $ipath, @path);
92    $self->{ names    } = $class->hash_vars(uc $inames, @names);
93    $self->{ $items   } = $class->hash_vars(uc $items, $config->{ $items });
94    $self->{ items    } = $items;
95    $self->{ item     } = $item;
96    $self->{ loaded   } = { };
97    $self->{ no_cache } = defined $config->{ no_cache }     # quick hack
98        ? $config->{ no_cache }
99        : $class->any_var('NO_CACHE') || 0;
100
101    # see if a 'xxxx_default' or 'default' configuration option is specified
102    # or look for the first XXXX_DEFAULT or DEFAULT package variable.
103    $default = $config->{ $idefault }
104            || $config->{ default }
105            || $class->any_var_in( uc $idefault, uc DEFAULT );
106    if ($default) {
107        $self->debug("Setting default to $default") if DEBUG;
108        $self->{ default } = $self->{ names }->{ default } = $default;
109    }
110
111    $self->debug(
112        "Initialised $item/$items factory\n",
113        " Path: ", $self->dump_data($self->{ path }), "\n",
114        "Names: ", $self->dump_data($self->{ names })
115    ) if DEBUG;
116
117    return $self;
118}
119
120sub path {
121    my $self = shift->prototype;
122    return @_
123        ? ($self->{ path } = ref $_[0] eq ARRAY ? shift : [ @_ ])
124        :  $self->{ path };
125}
126
127sub default {
128    my $self = shift->prototype;
129    return @_
130        ? ($self->{ default } = $self->{ names }->{ default } = shift)
131        :  $self->{ default };
132}
133
134sub items {
135    my $self  = shift->prototype;
136    my $items = $self->{ $self->{ items } };
137    if (@_) {
138        my $args = ref $_[0] eq HASH ? shift : { @_ };
139        @$items{ keys %$args } = values %$args;
140    }
141    return $items;
142}
143
144sub item {
145    my $self = shift; $self = $self->prototype unless ref $self;
146    my ($type, @args) = $self->type_args(@_);
147
148    # In most cases we're expecting $type to be a name (e.g. Table) which we
149    # lookup in the items hash, or tack onto one of the module bases in the
150    # path (e.g. Template::Plugin) to create a full module name which we load
151    # and instantiate (e.g. Template::Plugin::Table).  However, the name might
152    # be explicitly mapped to a  reference of some kind, or the $type passed
153    # in could already be a reference (e.g. Template::TT2::Filters allow the
154    # first argument to be a code ref or object which implements the required
155    # filtering behaviour).  In which case, we bypass any name-based lookup
156    # and skip straight onto the "look what I found!" phase
157
158    return $self->found($type, $type, \@args)
159        unless textlike $type;
160
161    $type = $type . '';     # auto-stringify any textlike objects
162
163    # OK, so $type is a string.  We'll also create a canonical version of the
164    # name (lower case dotted) to provide a case/syntax insensitve fallback
165    # (e.g. so "foo.bar" can match against "Foo.Bar", "Foo::Bar" and so on)
166
167    my $items = $self->{ $self->{ items } };
168    my $canon = dotid $type;
169
170    $self->debug("Looking for '$type' or '$canon' in $self->{ items }") if DEBUG;
171#   $self->debug("types: ", $self->dump_data($self->{ types })) if DEBUG;
172
173    # false but defined entry indicates the item is not found
174    return $self->not_found($type, \@args)
175        if exists $items->{ $type }
176           && not $items->{ $type };
177
178    my $item = $items->{ $type  }
179            || $items->{ $canon }
180            # TODO: this needs to be defined-or, like //
181            # Plugins can return an empty string to indicate that they
182            # do nothing.
183            # HMMM.... or does it?
184            ||  $self->find($type, \@args)
185#            ||  $self->default($type, \@args)
186            ||  return $self->not_found($type, \@args);
187
188    $items->{ $type } = $item
189        unless $self->{ no_cache };
190
191    return $self->found($type, $item, \@args);
192}
193
194sub type_args {
195    # Simple method to grok $type and @args from argument list.  The only
196    # processing it does is to set $type to 'default' if it is undefined or
197    # false. Subclasses can re-define this to insert their own type mapping or
198    # argument munging, e.g. to inject values into the configuration params
199    # for an object
200    shift;
201    my $type = shift || DEFAULT;
202    my @args;
203
204    if (ref $type eq HASH) {
205        @args = ($type, @_);
206        $type = $type->{ type } || DEFAULT;
207    }
208    else {
209        @args = @_;
210    }
211
212    return ($type, @args);
213}
214
215sub find {
216    my $self   = shift;
217    my $type   = shift;
218    my $bases  = $self->path;
219    my $module;
220
221    # run the type through the type map to handle any unusual capitalisation,
222    # spelling, aliases, etc.
223    $type = $self->{ names }->{ $type } || $type;
224
225    foreach my $base (@$bases) {
226        return $module
227            if $module = $self->load( $self->module_names($base, $type) );
228    }
229
230    return undef;
231}
232
233sub load {
234    my $self   = shift;
235    my $loaded = $self->{ loaded };
236
237    foreach my $module (@_) {
238        # see if we've previously loaded a module with this name (true
239        # value) or failed to load a module (defined but false value)
240
241        if ($loaded->{ $module }) {
242            $self->debug("$module has been previously loaded") if DEBUG;
243            return $module;
244        }
245        elsif (defined $loaded->{ $module }) {
246            next;
247        }
248
249        no strict REFS;
250        $self->debug("attempting to load $module") if DEBUG;
251
252        # Some filesystems are case-insensitive (like Apple's HFS), so an
253        # attempt to load Badger::Example::foo may succeed, when the correct
254        # package name is actually Badger::Example::Foo.  We double-check
255        # by looking for $VERSION or @ISA.  This is a bit dodgy because we might be
256        # loading something that has no ISA.  Need to cross-check with
257        # what's going on in Badger::Class _autoload()
258
259        my $loadname;
260        if ( ($loadname = class($module)->maybe_load) ) {
261            $self->debug("loaded $module") if DEBUG;
262            $loaded->{ $module } = $loadname;
263            return $module
264        }
265
266        $self->debug("failed to load $module") if DEBUG;
267    }
268
269    return undef;
270}
271
272
273sub found {
274    my ($self, $type, $item, $args) = @_;
275
276    if (ref $item) {
277        # if it's a reference we found then forward it onto the appropriate
278        # method, e.g found_array(), found_hash(), found_code().  Fall back
279        # on found_ref()
280        my $iref = blessed($item)
281            ? OBJECT
282            : lc ref $item;
283
284        $self->debug(
285            "Looking for handler methods: ",
286            FOUND,'_'.$iref, "() or ",
287            FOUND_REF, "()"
288        ) if DEBUG;
289
290        my $method
291             = $self->can(FOUND . '_' . $iref)
292            || $self->can(FOUND_REF)
293            || return $self->error_msg( bad_ref => $self->{ item }, $type, $iref );
294
295        $item = $method->($self, $type, $item, $args);
296    }
297    else {
298        # otherwise it's the name of a module
299        $item = $self->found_module($type, $item, $args);
300    }
301
302    # NOTE: an item can be defined but false, e.g. a Template::Plugin which
303    # return '' from its new() method to indicate it does nothing objecty
304    return unless defined $item;
305
306    $self->debug("Found result: $type => $item") if DEBUG;
307
308    # TODO: what about caching result?  Do we always leave that to subclasses?
309    return $self->result($type, $item, $args);
310}
311
312sub found_module {
313    # This method is called when a module name is found, either by being
314    # predefined in the factory entry table, or loaded on demand from disk.
315    # It ensures the module is loaded and and instantiates an object from the
316    # class name
317    my ($self, $type, $module, $args) = @_;
318    $self->debug("Found module: $type => $module") if DEBUG;
319    $self->{ loaded }->{ $module } ||= class($module)->load;
320    return $self->construct($type, $module, $args);
321}
322
323sub found_array {
324    # This method is called when an ARRAY reference is found.  We assume that
325    # the first item is the module name (which needs to be loaded) and the
326    # second item is the class name (which needs to be instantiated).
327    my ($self, $type, $item, $args) = @_;
328    my ($module, $class) = @$item;
329    $self->{ loaded }->{ $module } ||= class($module)->load;
330    return $self->construct($type, $class, $args);
331}
332
333sub not_found {
334    my ($self, $type, @args) = @_;
335
336    return $type eq DEFAULT
337        ? $self->error_msg( no_default => $self->{ item } )
338        : $self->error_msg( not_found => $self->{ item }, $type );
339}
340
341sub construct {
342    my ($self, $type, $class, $args) = @_;
343    $self->debug("constructing class: $type => $class") if DEBUG;
344    return $class->new(@$args);
345}
346
347sub module_names {
348    my $self = shift;
349    my @bits =
350        map { camel_case($_) }
351        map { split /[\.]+/ } @_;
352
353    return (
354        join( PKG, map { ucfirst $_ } @bits ),
355        join( PKG, @bits )
356    );
357}
358
359
360sub can {
361    my ($self, $name) = @_;
362
363    # upgrade class methods to calls on prototype
364    $self = $self->prototype unless ref $self;
365
366    # NOTE: this method can get called before we've called init_factory()
367    # to define the item/items members, so we tread carefully.
368    if ($self->{ item } && $self->{ item } eq $name) {
369        return $self->SUPER::can('item');
370    }
371    elsif ($self->{ items } && $self->{ items } eq $name) {
372        return $self->SUPER::can('items');
373    }
374    else {
375        return $self->SUPER::can($name);
376    }
377}
378
379sub result {
380    $_[2];
381}
382
383sub AUTOLOAD {
384    my ($self, @args) = @_;
385    my ($name) = ($AUTOLOAD =~ /([^:]+)$/ );
386    return if $name eq 'DESTROY';
387
388    $self->debug("AUTOLOAD $name") if DEBUG;
389
390    local $RUNAWAY = $RUNAWAY;
391    $self->error("AUTOLOAD went runaway on $name")
392        if ++$RUNAWAY > 10;
393
394    # upgrade class methods to calls on prototype
395    $self = $self->prototype unless ref $self;
396
397    $self->debug("factory item: $self->{ item }") if DEBUG;
398
399    if ($name eq $self->{ item }) {
400        $self->class->method( $name => $self->can('item') );
401    }
402    elsif ($name eq $self->{ items }) {
403        $self->class->method( $name => $self->can('items') )
404    }
405    elsif (my $item = $self->try( item => $name, @args )) {
406        return $item;
407    }
408    else {
409        my ($pkg, $file, $line) = caller;
410        my $class = ref $self || $self;
411        die $self->message( bad_method => $name, $class, $file, $line ), "\n";
412    }
413
414    # should be installed now
415    $self->$name(@args);
416}
417
418
4191;
420
421__END__
422
423=head1 NAME
424
425Badger::Factory - base class factory module
426
427=head1 SYNOPSIS
428
429This module is designed to be subclassed to create factory classes that
430automatically load modules and instantiate objects on demand.
431
432    package My::Widgets;
433    use base 'Badger::Factory';
434
435    # tell the base class factory what we create
436    our $ITEM        = 'widget';
437    our $ITEMS       = 'widgets';
438
439    # define module search path for widgets
440    our $WIDGET_PATH = ['My::Widget', 'Your::Widget'];
441
442    # lookup table for any non-standard spellings/capitalisations/paths
443    our $WIDGETS     = {
444        url   => 'My::Widget::URL',       # non-standard capitalisation
445        color => 'My::Widget::Colour',    # different spelling
446        amp   => 'Nigels::Amplifier',     # different path
447    };
448
449You can then use it like this:
450
451    use My::Widgets;
452
453    # class methods (note: widget() is singular)
454    $w = My::Widgets->widget( foo => { msg => 'Hello World' } );
455
456    # same as:
457    use My::Widget::Foo;
458    $w = My::Widget::Foo({ msg => 'Hello World' });
459
460    # add/update widgets lookup table (note: widgets() is plural)
461    My::Widgets->widgets(
462        extra => 'Another::Widget::Module',
463        super => 'Golly::Gosh',
464    );
465
466    # now load and instantiate new widget modules
467    $w = My::Widgets->widget( extra => { msg => 'Hello Badger' } );
468
469You can also create factory objects:
470
471    my $factory = My::Widgets->new(
472        widget_path => ['His::Widget', 'Her::Widget'],
473        widgets     => {
474            extra => 'Another::Widget::Module',
475            super => 'Golly::Gosh',
476        }
477    );
478
479    $w = $factory->widget( foo => { msg => 'Hello World' } );
480
481The L<Badger::Factory::Class> module can be used to simplify the process
482of defining factory subclasses.
483
484    package My::Widgets;
485
486    use Badger::Factory::Class
487        item    => 'widget',
488        path    => 'My::Widget Your::Widget';
489        widgets => {
490            extra => 'Another::Widget::Module',
491            super => 'Golly::Gosh',
492        };
493
494=head1 DESCRIPTION
495
496This module implements a base class factory object for loading modules and
497instantiating objects on demand. It originated in the L<Template::Plugins>
498module, evolved over time in various directions for other projects, and was
499eventually pulled back into line to become C<Badger::Factory>.
500
501=head2 Defining a Factory Module
502
503The C<Badger::Factory> module isn't designed to be used by itself. Rather it
504should be used as a base class for your own factory modules. For example,
505suppose you have a project which has lots of C<My::Widget::*> modules. You can
506define a factory for them like so:
507
508    package My::Widgets;
509    use base 'Badger::Factory';
510
511    our $ITEM           = 'widget';
512    our $ITEMS          = 'widgets';
513    our $WIDGET_PATH    = ['My::Widget', 'Your::Widget'];
514    our $WIDGET_DEFAULT = 'foo';
515    our $WIDGET_NAMES   = {
516        html => 'HTML',
517    };
518
519    # lookup table for any non-standard spellings/capitalisations/paths
520    our $WIDGETS     = {
521        url   => 'My::Widget::URL',       # non-standard capitalisation
522        color => 'My::Widget::Colour',    # different spelling
523        amp   => 'Nigels::Amplifier',     # different path
524    };
525
526    1;
527
528The C<$ITEM> and C<$ITEMS> package variables are used to define the
529singular and plural names of the items that the factory is responsible for.
530In this particular case, the C<$ITEMS> declaration isn't strictly
531necessary because the module would correctly "guess" the plural name
532C<widgets> from the singular C<widget> defined in C<$ITEM>.  However,
533this is only provided as a convenience for those English words that
534pluralise regularly and shouldn't be relied upon to work all the time.
535See the L<pluralise()|Badger::Utils/pluralise()> method in L<Badger::Utils>
536for further information, and explicitly specify the plural in C<$ITEMS> if
537you're in any doubt.
538
539The C<$WIDGET_PATH> is used to define one or more base module names under
540which your widgets are located.  The name of this variable is derived
541from the upper case item name in C<$ITEM> with C<_PATH> appended.  In this
542example, the factory will look for the C<Foo::Bar> module as either
543C<My::Widget::Foo::Bar> or C<Your::Widget::Foo::Bar>.
544
545The C<$WIDGET_DEFAULT> specifies the default item name to use if a request
546is made for a module using an undefined or false name.  If you don't specify
547any value for a default then it uses the literal string C<default>.  Adding
548a C<default> entry to your C<$WIDGET_NAMES> or C<$WIDGETS> will have the same
549effect.
550
551The C<$WIDGET_NAMES> is used to define any additional name mappings. This is
552usually required to handle alternate spellings or unusual capitalisations that
553the default name mapping algorithm would get wrong. For example, a request for
554an C<html> widget would look for C<My::Widget::Html> or C<Your::Widget::Html>.
555Adding a C<$WIDGET_MAP> entry mapping C<html> to C<HTML> will instead send it
556looking for C<My::Widget::HTML> or C<Your::Widget::HTML>.
557
558If you've got any widgets that aren't located in one of these locations,
559or if you want to provide some aliases to particular widgets then you can
560define them in the C<$WIDGETS> package variable.  The name of this variable
561is the upper case conversion of the value defined in the C<$ITEMS> package
562variable.
563
564=head2 Using Your Factory Module
565
566Now that you've define a factory module you can use it like this.
567
568    use My::Widgets;
569
570    my $widgets = My::Widgets->new;
571    my $foo_bar = $widgets->widget('Foo::Bar');
572
573The C<widget()> method is provided to load a widget module and instantiate
574a widget object.
575
576The above example is equivalent to:
577
578    use My::Widget::Foo::Bar;
579    my $foo_bar = My::Widget::Foo::Bar->new;
580
581Although it's not I<strictly> equivalent because the factory could just
582has easily have loaded it from C<Your::Widget::Foo::Bar> in the case that
583C<My::Widget::Foo::Bar> doesn't exist.
584
585You can specify additional arguments that will be forwarded to the object
586constructor method.
587
588    my $foo_bar = $widgets->widget('Foo::Bar', x => 10, y => 20);
589
590If you've specified a C<$WIDGET_DEFAULT> for your factory then you can call
591the L<widget()> method without any arguments to get the default object.
592
593    my $widget = $widgets->widget;
594
595You can use the L<default()> method to change the default module.
596
597    $widgets->default('bar');
598
599The factory module can be customised using configuration parameters. For
600example, you can provide additional values for the C<widget_path>, or define
601additional widgets:
602
603    my $widgets = My::Widgets->new(
604        widget_path => ['His::Widget', 'Her::Widget'],
605        widgets     => {
606            extra => 'Another::Widget::Module',
607            super => 'Golly::Gosh',
608        }
609    );
610
611The factory module is an example of a L<prototype()|Badger::Prototype> module.
612This means that you can call the C<widget()> method as a class method to save
613yourself of explicitly creating a factory object.
614
615    my $widget = My::Widgets->widget('Foo::Bar');
616
617=head1 METHODS
618
619=head2 new()
620
621Constructor method to create a new factory module.
622
623    my $widgets = My::Widgets->new;
624
625=head2 path($path)
626
627Used to get or set the factory module path.
628
629    my $path = $widgets->path;
630    $widgets->path(['My::Widgets', 'Your::Widgets', 'Our::Widgets']);
631
632Calling the method with arguments replaces any existing list.
633
634=head2 names($names)
635
636Used to get or set the names mapping table.
637
638    my $names = $widgets->names;
639    $widgets->names({ html => 'HTML' });
640
641Calling the method with arguments replaces any existing names table.
642
643=head2 default($name)
644
645Used to get or set a name for the default item name.  The default value is
646the literal string C<default>.  This allows you to add a C<default> entry
647to either your L<names()> or L<items()> and it will be located automatically.
648
649=head2 items(%items)
650
651Used to fetch or update the lookup table for mapping names to modules.
652
653    my $items = $widgets->items;
654    $widgets->items( foo => 'My::Plugin::Foo' );
655
656Calling the method with arguments (named parameters or a hash reference)
657will add the new definitions into the existing table.
658
659This method can also be aliased by the plural name defined in C<$ITEMS>
660in your subclass module.
661
662    $widgets->widgets;
663
664=head2 item($name,@args)
665
666Method to load a module and instantiate an object.
667
668    my $widget = $widgets->item('Foo');
669
670Any additional arguments provided after the module name are forwarded to the
671object's C<new()> constructor method.
672
673    my $widget = $widgets->item( Foo => 10, 20 );
674
675This method can also be aliased by the singular name defined in C<$ITEM>
676in your subclass module.
677
678    my $widget = $widgets->widget( Foo => 10, 20 );
679
680The module name specified can be specified in lower case.  The name is
681capitalised as a matter of course.
682
683    # same as Foo
684    my $widget = $widgets->widget( foo => 10, 20 );
685
686Multi-level names can be separated with dots rather than C<::>.  This is in
687keeping with the convention used in the Template Toolkit.  Each element after
688a dot is capitalised.
689
690    # same as Foo::Bar
691    my $widget = $widgets->widget( 'foo.bar' => 10, 20 );
692
693=head1 INTERNAL METHODS
694
695=head2 type_args(@args)
696
697This method can be re-defined by a subclass to perform any pre-manipulation on
698the arguments passed to the L<item()> method.  The first argument is usually
699the type (i.e. name) of module requested, followed by any additional arguments
700for the object constructor.
701
702    my ($self, $type, @args) = @_;
703
704The method should return them like so:
705
706    return ($type, @args);
707
708=head2 find($type,\@args)
709
710This method is called to find and dynamically load a module if it doesn't
711already have an entry in the internal C<items> table.  It iterates through
712each of the base paths for the factory and calls the L<load()> method to
713see if the module can be found under that prefix.
714
715=head2 load(@module_names)
716
717This method is called to dynamically load a module.  It iterates through
718each of the module name passed as arguments until it successfully loads
719one.  At that point it returns the module name that was successfully
720loaded and ignores the remaining arguments.  If none of the modules can
721be loaded then it returns C<undef>
722
723=head2 found($name,$item,\@args)
724
725This method is called when an item has been found, either in the internal
726C<items> lookup table, or by a call to L<find()>. The L<$item> argument is
727usually a module name that is forwarded onto L<found_module()>. However, it
728can also be a reference which will be forwarded onto one of the following
729methods depending on its type: L<found_array()>, L<found_hash()>,
730L<found_scalar()>, L<found_object()> (and in theory, C<found_regex()>,
731C<found_glob()> and maybe others, but they're not implemented).
732
733The result returned by the appropriate C<found_XXXXX()> method will then
734be forwarded onto the L<result()> method.  The method returns the result
735from the L<result()> method.
736
737=head2 found_module($module)
738
739This method is called when a requested item has been mapped to a module name.
740The module is loaded if necessary, then the L<construct()> method is called
741to construct an object.
742
743=head2 found_array(\@array)
744
745An entry in the C<items> (aka C<widgets> in our earlier example) table
746can be a reference to a list containing a module name and a separate class
747name.
748
749    my $widgets = My::Widgets->new(
750        widgets => {
751            wizbang => ['Wiz::Bang', 'Wiz::Bang::Bash'],
752        },
753    );
754
755If the C<wizbang> widget is requested from the C<My::Widgets> factory
756in the example above, then the L<found()> method will call C<found_array()>,
757passing the array reference as an argument.
758
759The module listed in the first element is loaded.  The class name in
760the second element is then used to instantiate an object.
761
762=head2 found_hash(\%hash)
763
764This method isn't implemented in the base class, but can be defined by
765subclasses to handle the case where a request is mapped to a hash reference.
766
767=head2 found_scalar(\$scalar)
768
769This method isn't implemented in the base class, but can be defined by
770subclasses to handle the case where a request is mapped to a scalar reference.
771
772=head2 found_object($object)
773
774This method isn't defined in the base class, but can be defined by subclasses
775to handle the case where a request is mapped to an existing object.
776
777=head2 construct($name,$class,\@args)
778
779This method instantiates a C<$class> object using the arguments provided.
780In the base class this method  simply calls:
781
782    $class->new(@$args);
783
784=head2 result($name,$result,\@args)
785
786This method is called at the end of a successful request after an object
787has been instantiated (or perhaps re-used from an internal cache).  In the
788base class it simply returns C<$result> but can be redefined in a subclass
789to do something more interesting.
790
791=head2 module_names($type)
792
793This method performs the necessary mapping from a requested module name to
794its canonical form.
795
796=head2 not_found($name,@args)
797
798This method is called when the requested item is not found. The method simply
799throws an error using the C<not_found> message format. The method can be
800redefined in subclasses to perform additional fallback handing.
801
802=head2 can($method)
803
804This method implements the magic to ensure that the item-specific accessor
805methods (e.g. C<widget()>/C<widgets()>) are generated on demand.
806
807=head2 AUTOLOAD(@args)
808
809This implements the other bit of magic to generate the item-specific accessor
810methods on demand.
811
812=head1 AUTHOR
813
814Andy Wardley L<http://wardley.org/>
815
816=head1 COPYRIGHT
817
818Copyright (C) 2006-2009 Andy Wardley.  All Rights Reserved.
819
820This module is free software; you can redistribute it and/or
821modify it under the same terms as Perl itself.
822
823=head1 SEE ALSO
824
825L<Badger::Factory::Class>, L<Badger::Codecs>.
826
827=cut
828
829# Local Variables:
830# mode: perl
831# perl-indent-level: 4
832# indent-tabs-mode: nil
833# End:
834#
835# vim: expandtab shiftwidth=4:
836