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>.
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
49 use vars qw($VERSION $DEBUG);
53 use Storable qw(dclone); # Used for deep copying objects
57 ($REVISION) = q$LastChangedRevision$ =~ /\$LastChangedRevision:\s+([^\s+])/;
58 $DEBUG = 0 unless defined $DEBUG;
66 Usage : $obj = Foo::Bar->new();
67 Function: Creates a new Foo::Bar object
68 Returns : A new Foo::Bar object
71 Aditional arguments can be passed to this creator, and they are
72 stored in $self->{_creation_args}. You can also override the new
73 method in your subclass. It's just provided here for completeness.
78 my ($class,@args) = @_;
80 # We shouldn't be called $me->new, but just in case
81 $class = ref($class) || $class;
100 Stores the arguments used at new so modules that are loaded later can
106 my ($self,@creation_args) = @_;
108 $self->{creation_args} = [@_];
115 Usage : $db->load('FOO::Subclass');
116 Function: loads a Class::Modular subclass
118 Args : SCALAR subclass SCALAR options
120 Loads the named subclass into this object if the named subclass has
123 The options scalar is passed to $subclass::_methods when determining
124 which methods should be added using _addmethods.
126 The subclasses _init method is called right after methods are loaded.
128 If debugging is enabled, will warn about loading already loaded
135 my ($self,$subclass,$options) = @_;
139 # check to see if the subclass has already been loaded.
141 if (not defined $self->{_subclasses}->{$subclass}){
144 eval "require $subclass" or die $@;
145 $self->_addmethods($subclass,&{"${subclass}::_methods"}($self,$options));
146 &{"${subclass}::_init"}($self);
149 $self->{_subclasses}->{$subclass} = {};
152 carp "Not reloading subclass $subclass" if $DEBUG;
159 Usage : $self->_addmethods()
160 Function: Adds the passed methods into the function table
162 Args : ARRAY of methods
164 Given an array of methods, adds the methods into the _methodhash
167 Methods that have previously been overridden by override are _NOT_
168 overridden again. This may need to be adjusted in load.
172 sub _addmethods($@) {
173 my ($self,$subclass,@methods) = @_;
175 # stick the method into the table
176 # DLA: Make with the munchies!
178 foreach my $method (@methods) {
179 if (not $method =~ /^$subclass/) {
180 $method = $subclass.'::'.$method;
182 my ($method_name) = $method =~ /\:*([^\:]+)\s*$/;
183 if (exists $self->{_methodhash}->{$method_name}) {
184 if ($self->{_methodhash}->{$method_name}->{overridden}) {
185 carp "Not overriding already overriden method $method_name\n" if $DEBUG;
188 carp "Overriding $method_name $self->{_methodhash}->{$method_name}->{reference} with $method\n";
190 $self->{_methodhash}->{$method_name}->{reference} = $method;
191 $self->{_methodhash}->{$method_name}->{subclass} = $subclass;
199 Usage : $obj->override('methodname', $code_ref)
200 Function: Overrides the method methodname and calls $code_ref instead.
201 Returns : TRUE on success, FALSE on failure.
202 Args : SCALAR method name
203 CODEREF function reference
205 Allows you to override utility functions that are called internally
206 to provide a different default function.
208 It's superficially similar to _addmethods, which is called by load,
209 but it deals with code references, and requires the method name to be
212 Methods overridden here are _NOT_ overrideable in _addmethods. This
213 may need to be changed.
218 my ($self, $method_name, $function_reference) = @_;
220 $self->{_methodhash}->{$method_name}->{reference} = $function_reference;
221 $self->{_methodhash}->{$method_name}->{overridden} = 1;
227 Usage : my $clone = $obj->clone
228 Function: Produces a clone of the Class::Modular object
232 Produces a clone of the object with duplicates of all data and/or new
233 connections as appropriate.
235 Calls _clone on all loaded subclasses.
237 Warns if debugging is on for classes which don't have a _clone
238 method. Dies on other errors.
246 bless $clone, ref($self);
248 # copy data structures at this level
249 $clone->{_methodhash} = dclone($self->{_methodhash});
250 $clone->{_subclasses} = dclone($self->{_subclasses});
252 foreach my $subclass (keys %{$self->{_subclasses}}) {
253 # use eval to try and call the subclasses _clone method.
254 # Ignore no such function errors, but trap other types of
257 # XXX Switch to can instead.
260 &$subclass::_clone($self,$clone);
263 # Die unless we've hit an undefined subroutine.
264 die $@ unless $@ =~ /Undefined\s*subroutine\s*\&.*\:\:\_clone/;
265 warn "$subclass doesn't have a _clone method\n$@" if $DEBUG;
277 Class::Modular->can('METHOD');
281 Replaces UNIVERSAL's can method so that handled methods are reported
282 correctly. Calls UNIVERSAL::can in the places where we don't know
287 A coderef to the method if the method is supported, undef otherwise.
296 my ($self,$method,$vars) = @_;
298 if (ref $self and exists $self->{_methodhash}->{$method}) {
299 # If the method is defined, return a reference to the
301 return $self->{_methodhash}->{$method}->{reference};
304 # Otherwise, let UNIVERSAL::can deal with the method
306 return UNIVERSAL::can($self,$method);
314 $obj->handledby('methodname');
315 $obj->handledby('Class::Method::methodname');
319 Returns the subclass that handles this method.
332 my ($self,$method_name) = @_;
334 $method_name =~ s/.*\://;
336 if (exists $self->{_methodhash}->{$method_name}) {
337 return $self->{_methodhash}->{$method_name}->{subclass};
351 Calls all subclass _destroy methods.
353 Subclasses need only implement a _destroy method if they have
354 references that need to be uncircularized, or things that should be
355 disconnected or closed.
361 foreach my $subclass (keys %{$self->{_subclasses}}) {
362 # use eval to try and call the subclasses _destroy method.
363 # Ignore no such function errors, but trap other types of
367 &$subclass::_destroy($self);
370 # Die unless we've hit an undefined subroutine.
371 die $@ unless $@ =~ /Undefined\s*subroutine\s*\&.*\:\:\_clone/;
372 warn "$subclass doesn't have a _clone method\n$@" if $DEBUG;
381 Usage : Called by perl
382 Function: Calls child methods which have been installed into this handle
386 The AUTOLOAD function is responsible for calling child methods which
387 have been installed into the current Class::Modular handle.
389 Subclasses that have a new function as well as an AUTOLOAD function
390 must call Class::Modular::AUTOLOAD and set $Class::Modular::AUTOLOAD
392 $Class::Modular::AUTOLOAD = $AUTOLOAD;
393 goto &Class::Modular::AUTOLOAD;
398 my $method = $AUTOLOAD;
404 if (not ref($self)) {
405 carp "Not a reference in AUTOLOAD.";
409 if (exists $self->{_methodhash}->{$method} and
410 defined $self->{_methodhash}->{$method}->{reference}) {
413 goto &{$self->{_methodhash}{$method}{reference}};
417 croak "Undefined function $AUTOLOAD";