1 # This module is part of DA, Don Armstrong's Modules, and is released
2 # under the terms of the GPL version 2, or any later version. See the
3 # file README and COPYING for more information. Copyright 2003 by Don
4 # Armstrong <don@donarmstrong.com>.
5 # $Id: Modular.pm,v 1.4 2003/10/24 04:48:51 don Exp $
7 package Class::Modular;
11 Class::Modular -- Modular class generation superclass
17 @ISA = qw(Class::Modular);
22 Class::Modular is a superclass for generating modular classes, where
23 methods can be added into the class from the perspective of the
24 object, rather than the perspective of the class.
26 That is, you can create a class which has a set of generic common
27 functions. Less generic functions can be included or overridden
28 without modifying the base classes. This allows for code to be more
29 modular, and reduces code duplication.
35 new is responsible for blessing and creating a new database superclass.
39 load is responsible for loading database plugins
51 use vars qw($VERSION $DEBUG);
55 use Data::Copy qw(deep_copy); # Used for deep copying objects
58 ($VERSION) = q$Revision: 1.4 $ =~ /\$Revision:\s+([^\s+])/;
59 $DEBUG = 0 unless defined $DEBUG;
67 Usage : $obj = Foo::Bar->new();
68 Function: Creates a new Foo::Bar object
69 Returns : A new Foo::Bar object
72 Aditional arguments can be passed to this creator, and they are
73 stored in $self->{_creation_args}. You can also override the new
74 method in your subclass. It's just provided here for completeness.
79 my ($class,@args) = @_;
81 # We shouldn't be called $me->new, but just in case
82 $class = ref($class) || $class;
87 $self->{_creation_args} = [@args];
96 Usage : $db->load('FOO::Subclass');
97 Function: loads a Class::Modular subclass
99 Args : SCALAR subclass SCALAR options
101 Loads the named subclass into this object if the named subclass has
104 The options scalar is passed to $subclass::_methods when determining
105 which methods should be added using _addmethods.
107 The subclasses _init method is called right after methods are loaded.
109 If debugging is enabled, will warn about loading already loaded
116 my ($self,$subclass,$options) = @_;
120 # check to see if the subclass has already been loaded.
122 if (not defined $self->{_subclasses}->{$subclass}){
125 $self->_addmethods($subclass,&{"${subclass}::_methods"}($self,$options));
126 &{"${subclass}::_init"}($self);
129 $self->{_subclasses}->{$subclass} = {};
132 carp "Not reloading subclass $subclass" if $DEBUG;
139 Usage : $self->_addmethods()
140 Function: Adds the passed methods into the function table
142 Args : ARRAY of methods
144 Given an array of methods, adds the methods into the _methodhash
147 Methods that have previously been overridden by override are _NOT_
148 overridden again. This may need to be adjusted in load.
152 sub _addmethods($@) {
153 my ($self,$subclass,@methods) = @_;
155 # stick the method into the table
156 # DLA: Make with the munchies!
158 foreach my $method (@methods) {
159 if (not $method =~ /^$subclass/) {
160 $method = $subclass.$method;
162 my ($method_name) = $method =~ /\:*([^\:]+)\s*$/;
163 if (exists $self->{_methodhash}->{$method_name}) {
164 if ($self->{_methodhash}->{$method_name}->{overridden}) {
165 carp "Not overriding already overriden method $method_name\n" if $DEBUG;
168 carp "Overriding $method_name $self->{_methodhash}->{$method_name}->{reference} with $method\n";
170 $self->{_methodhash}->{$method_name}->{reference} = $method;
178 Usage : $obj->override('methodname', $code_ref)
179 Function: Overrides the method methodname and calls $code_ref instead.
180 Returns : TRUE on success, FALSE on failure.
181 Args : SCALAR method name
182 CODEREF function reference
184 Allows you to override utility functions that are called internally
185 to provide a different default function.
187 It's superficially similar to _addmethods, which is called by load,
188 but it deals with code references, and requires the method name to be
191 Methods overridden here are _NOT_ overrideable in _addmethods. This
192 may need to be changed.
197 my ($self, $method_name, $function_reference) = @_;
199 $self->{_methodhash}->{$method_name}->{reference} = $function_reference;
200 $self->{_methodhash}->{$method_name}->{overridden} = 1;
206 Usage : my $clone = $obj->clone
207 Function: Produces a clone of the Class::Modular object
211 Produces a clone of the object with duplicates of all data and/or new
212 connections as appropriate.
214 Calls _clone on all loaded subclasses.
216 Warns if debugging is on for classes which don't have a _clone
217 method. Dies on other errors.
225 bless $clone, ref($self);
227 # copy data structures at this level
228 $clone->{_methodhash} = deep_copy($self->{_methodhash});
229 $clone->{_subclasses} = deep_copy($self->{_subclasses});
231 foreach my $subclass (keys %{$self->{_subclasses}}) {
232 # use eval to try and call the subclasses _clone method.
233 # Ignore no such function errors, but trap other types of
238 &$subclass::_clone($self,$clone);
241 # Die unless we've hit an undefined subroutine.
242 die $@ unless $@ =~ /Undefined\s*subroutine\s*\&.*\:\:\_clone/;
243 warn "$subclass doesn't have a _clone method\n$@" if $DEBUG;
259 Calls all subclass _destroy methods.
261 Subclasses need only implement a _destroy method if they have
262 references that need to be uncircularized, or things that should be
263 disconnected or closed.
269 foreach my $subclass (keys %{$self->{_subclasses}}) {
270 # use eval to try and call the subclasses _destroy method.
271 # Ignore no such function errors, but trap other types of
275 &$subclass::_destroy($self);
278 # Die unless we've hit an undefined subroutine.
279 die $@ unless $@ =~ /Undefined\s*subroutine\s*\&.*\:\:\_clone/;
280 warn "$subclass doesn't have a _clone method\n$@" if $DEBUG;
289 Usage : Called by perl
290 Function: Calls child methods which have been installed into this handle
294 The AUTOLOAD function is responsible for calling child methods which
295 have been installed into the current Class::Modular handle.
300 my $method = $AUTOLOAD;
306 if (not ref($self)) {
307 carp "Not a reference in AUTOLOAD.";
311 if (defined $self->{_methodhash}->{$method}->{reference}) {
314 goto &$self->{_methodhash}->{$method}->{reference};