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.8 2003/12/09 02:00:10 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
49 use vars qw($VERSION $DEBUG);
53 use Data::Copy qw(deep_copy); # Used for deep copying objects
56 ($VERSION) = q$Revision: 1.8 $ =~ /\$Revision:\s+([^\s+])/;
57 $DEBUG = 0 unless defined $DEBUG;
65 Usage : $obj = Foo::Bar->new();
66 Function: Creates a new Foo::Bar object
67 Returns : A new Foo::Bar object
70 Aditional arguments can be passed to this creator, and they are
71 stored in $self->{_creation_args}. You can also override the new
72 method in your subclass. It's just provided here for completeness.
77 my ($class,@args) = @_;
79 # We shouldn't be called $me->new, but just in case
80 $class = ref($class) || $class;
99 Stores the arguments used at new so modules that are loaded later can
105 my ($self,@creation_args) = @_;
107 $self->{creation_args} = [@_];
114 Usage : $db->load('FOO::Subclass');
115 Function: loads a Class::Modular subclass
117 Args : SCALAR subclass SCALAR options
119 Loads the named subclass into this object if the named subclass has
122 The options scalar is passed to $subclass::_methods when determining
123 which methods should be added using _addmethods.
125 The subclasses _init method is called right after methods are loaded.
127 If debugging is enabled, will warn about loading already loaded
134 my ($self,$subclass,$options) = @_;
138 # check to see if the subclass has already been loaded.
140 if (not defined $self->{_subclasses}->{$subclass}){
143 eval "require $subclass" or die $@;
144 $self->_addmethods($subclass,&{"${subclass}::_methods"}($self,$options));
145 &{"${subclass}::_init"}($self);
148 $self->{_subclasses}->{$subclass} = {};
151 carp "Not reloading subclass $subclass" if $DEBUG;
158 Usage : $self->_addmethods()
159 Function: Adds the passed methods into the function table
161 Args : ARRAY of methods
163 Given an array of methods, adds the methods into the _methodhash
166 Methods that have previously been overridden by override are _NOT_
167 overridden again. This may need to be adjusted in load.
171 sub _addmethods($@) {
172 my ($self,$subclass,@methods) = @_;
174 # stick the method into the table
175 # DLA: Make with the munchies!
177 foreach my $method (@methods) {
178 if (not $method =~ /^$subclass/) {
179 $method = $subclass.'::'.$method;
181 my ($method_name) = $method =~ /\:*([^\:]+)\s*$/;
182 if (exists $self->{_methodhash}->{$method_name}) {
183 if ($self->{_methodhash}->{$method_name}->{overridden}) {
184 carp "Not overriding already overriden method $method_name\n" if $DEBUG;
187 carp "Overriding $method_name $self->{_methodhash}->{$method_name}->{reference} with $method\n";
189 $self->{_methodhash}->{$method_name}->{reference} = $method;
190 $self->{_methodhash}->{$method_name}->{subclass} = $subclass;
198 Usage : $obj->override('methodname', $code_ref)
199 Function: Overrides the method methodname and calls $code_ref instead.
200 Returns : TRUE on success, FALSE on failure.
201 Args : SCALAR method name
202 CODEREF function reference
204 Allows you to override utility functions that are called internally
205 to provide a different default function.
207 It's superficially similar to _addmethods, which is called by load,
208 but it deals with code references, and requires the method name to be
211 Methods overridden here are _NOT_ overrideable in _addmethods. This
212 may need to be changed.
217 my ($self, $method_name, $function_reference) = @_;
219 $self->{_methodhash}->{$method_name}->{reference} = $function_reference;
220 $self->{_methodhash}->{$method_name}->{overridden} = 1;
226 Usage : my $clone = $obj->clone
227 Function: Produces a clone of the Class::Modular object
231 Produces a clone of the object with duplicates of all data and/or new
232 connections as appropriate.
234 Calls _clone on all loaded subclasses.
236 Warns if debugging is on for classes which don't have a _clone
237 method. Dies on other errors.
245 bless $clone, ref($self);
247 # copy data structures at this level
248 $clone->{_methodhash} = deep_copy($self->{_methodhash});
249 $clone->{_subclasses} = deep_copy($self->{_subclasses});
251 foreach my $subclass (keys %{$self->{_subclasses}}) {
252 # use eval to try and call the subclasses _clone method.
253 # Ignore no such function errors, but trap other types of
256 # XXX Switch to can instead.
259 &$subclass::_clone($self,$clone);
262 # Die unless we've hit an undefined subroutine.
263 die $@ unless $@ =~ /Undefined\s*subroutine\s*\&.*\:\:\_clone/;
264 warn "$subclass doesn't have a _clone method\n$@" if $DEBUG;
276 Class::Modular->can('METHOD');
280 Replaces UNIVERSAL's can method so that handled methods are reported
281 correctly. Calls UNIVERSAL::can in the places where we don't know
286 A coderef to the method if the method is supported, undef otherwise.
295 my ($self,$method,$vars) = @_;
297 if (ref $self and exists $self->{_methodhash}->{$method}) {
298 # If the method is defined, return a reference to the
300 return $self->{_methodhash}->{$method}->{reference};
303 # Otherwise, let UNIVERSAL::can deal with the method
305 return UNIVERSAL::can($self,$method);
313 $obj->handledby('methodname');
314 $obj->handledby('Class::Method::methodname');
318 Returns the subclass that handles this method.
331 my ($self,$method_name) = @_;
333 $method_name =~ s/.*\://;
335 if (exists $self->{_methodhash}->{$method_name}) {
336 return $self->{_methodhash}->{$method_name}->{subclass};
350 Calls all subclass _destroy methods.
352 Subclasses need only implement a _destroy method if they have
353 references that need to be uncircularized, or things that should be
354 disconnected or closed.
360 foreach my $subclass (keys %{$self->{_subclasses}}) {
361 # use eval to try and call the subclasses _destroy method.
362 # Ignore no such function errors, but trap other types of
366 &$subclass::_destroy($self);
369 # Die unless we've hit an undefined subroutine.
370 die $@ unless $@ =~ /Undefined\s*subroutine\s*\&.*\:\:\_clone/;
371 warn "$subclass doesn't have a _clone method\n$@" if $DEBUG;
380 Usage : Called by perl
381 Function: Calls child methods which have been installed into this handle
385 The AUTOLOAD function is responsible for calling child methods which
386 have been installed into the current Class::Modular handle.
388 Subclasses that have a new function as well as an AUTOLOAD function
389 must call Class::Modular::AUTOLOAD and set $Class::Modular::AUTOLOAD
391 $Class::Modular::AUTOLOAD = $AUTOLOAD;
392 goto &Class::Modular::AUTOLOAD;
397 my $method = $AUTOLOAD;
403 if (not ref($self)) {
404 carp "Not a reference in AUTOLOAD.";
408 if (exists $self->{_methodhash}->{$method} and
409 defined $self->{_methodhash}->{$method}->{reference}) {
412 goto &{$self->{_methodhash}{$method}{reference}};
416 croak "Undefined function $AUTOLOAD";