[Templates-cvs] cvs commit: TT3/lib/Template/TT3 Factory.pm
cvs@template-toolkit.org
cvs@template-toolkit.org
Thu, 04 Dec 2003 15:12:34 +0000
cvs 03/12/04 15:12:31
Added: lib/Template/TT3 Factory.pm
Log:
added Template::TT3::Factory
Revision Changes Path
1.1 TT3/lib/Template/TT3/Factory.pm
Index: Factory.pm
===================================================================
#============================================================= -*-perl-*-
#
# Template::TT3::Factory
#
# DESCRIPTION
# Factory module for loading and instantiating other Template modules.
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2003 Andy Wardley. All Rights Reserved.
# Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# REVISION
# $Id: Factory.pm,v 1.1 2003/12/04 15:12:31 abw Exp $
#
# TODO
# * if module entry can be a string or hash table, then module() could
# return either, leaving the caller to work out which. Perhaps it
# should automatically fold strings (module names) into hash arrays
# of the form { module => $module_name }
#
#========================================================================
package Template::TT3::Factory;
use strict;
use warnings;
use Template::TT3::Base;
use Template::TT3::Utils;
use vars qw( $VERSION $DEBUG $ERROR $WARNING $UTILS $MODULES );
use base qw( Template::TT3::Base );
$VERSION = sprintf("%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/);
$DEBUG = 0 unless defined $DEBUG;
$ERROR = '';
$UTILS = 'Template::TT3::Utils';
$MODULES = { };
#------------------------------------------------------------------------
# init({ name => $module, name => $module, ... })
#
# Initialisation method which builds a factory table mapping names to
# modules, by merging any $MODULES hash defined in the derived class
# package with any extra definitions passed in as arguments.
#------------------------------------------------------------------------
sub init {
my ($self, $config) = @_;
my $class = ref $self || $self;
# merge $MODULES class hash and MODULES (or modules) config hash
my $classmods = do {
no strict 'refs';
${"$class\::MODULES"} || { };
};
my $configmods = $config->{ modules }
|| $config->{ MODULES }
|| { };
$self->{ modules } = {
%$classmods,
%$configmods,
};
$self->{ loaded } = { };
# set utility class
$self->{ utils } = $config->{ utils }
|| $UTILS;
$self->debug("init() => $self\n") if $DEBUG;
return $self;
}
#------------------------------------------------------------------------
# module($name)
# module($name, $module)
#
# Accessor/mutator method for managing the internal module lookup table
# that maps generic names to specific module implementations. Returns
# the current module package name for a named item when called with one
# argument, or updates it when called with two.
#------------------------------------------------------------------------
sub module {
my ($self, $name, $module) = @_;
my $class = ref($self) || $self;
my ($modmod, $utils);
my $mods = ref $self ? $self->{ modules } : do {
no strict 'refs';
${"$class\::MODULES"} || { };
};
if (defined($module)) {
# update table with new module
$mods->{ $name } = $module;
return $module;
}
else {
$module = $mods->{ $name }
|| return $self->error("module not found: $name");
}
# load relevant module if we haven't already done so
unless ($self->{ loaded }->{ $name }) {
if (UNIVERSAL::isa($module, 'HASH')) {
# if 'module' isn't defined in the hash then the
# user doesn't want us to load a module for this class
$modmod = $module->{ module };
}
else {
$modmod = $module;
}
if ($modmod) {
# delegate to Utils class
$utils = $self->{ utils }
|| return $self->error('no utility class defined');
$utils->load_module($modmod)
|| return $self->error($utils->error());
}
$self->{ loaded }->{ $name } = $module;
}
# TODO: should this always return a hash (or string?)
return $module;
}
sub class {
my ($self, $name) = @_;
my $module = $self->module($name) || return;
my $modclass;
if (UNIVERSAL::isa($module, 'HASH')) {
# if 'class' isn't defined in the hash then we
# look for 'module', or fail
$modclass = $module->{ class } || $module->{ module }
|| return $self->error("no class or module defined for $name");
}
else {
$modclass = $module;
}
return $modclass;
}
sub create {
my ($self, $module, @args) = @_;
my $class = $self->class($module) || return;
my $object;
eval {
# call the class constructor method
$self->debug("calling $class->new(", join(', ', @args), ")\n") if $DEBUG;
$object = $class->new(@args)
|| $self->error("failed to create $class object",
UNIVERSAL::can($class, 'error')
? (': ', $class->error) : ());
};
if ($@) {
chomp($@);
return $self->error("failed to create $class object: $@");
};
return $object;
}
# TT
#
# sub object { }
#
# sub preload { }
#
# sub isa { }
# # Webkit
#
# sub instance { } # can be a singleton
#
# sub construct { }
#
1;
__END__
=head1 NAME
Template::TT3::Factory - load and instantiate other Template modules
=head1 SYNOPSIS
use Template::TT3::Factory
# TODO
=head1 DESCRIPTION
# TODO
=head1 METHODS
=head2 method1()
# TODO
=head2 method2()
# TODO
=head1 AUTHOR
Andy Wardley E<lt>abw@wardley.orgE<gt>
=head1 VERSION
$Revision: 1.1 $
=head1 COPYRIGHT
Copyright (C) 1996-2003 Andy Wardley. All Rights Reserved.
Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=head1 SEE ALSO
# TODO
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4: