]> git.donarmstrong.com Git - class_modular.git/.git/blob - lib/Class/Modular.pm
7835b1224fd1731f764c28ccc9964181a61815a2
[class_modular.git/.git] / lib / Class / Modular.pm
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.
4 # Copyright 2003,2004 by Don Armstrong <don@donarmstrong.com>.
5 # $Id$
6
7 package Class::Modular;
8
9 =head1 NAME
10
11 Class::Modular -- Modular class generation superclass
12
13 =head1 SYNOPSIS
14
15      package Foo;
16
17      use base qw(Class::Modular);
18
19      use vars (@METHODS);
20      BEGIN{@METHODS=qw(blah)};
21
22      sub blah{
23          my $self = shift;
24          return 1;
25      }
26
27      [...]
28
29      package Bar;
30
31      sub method_that_bar_provides{
32           print qq(Hello World!\n);
33      }
34
35      sub _methods($$){
36           return qw(method_that_bar_provides);
37      }
38
39      [...]
40
41      use Foo;
42
43      $foo = new Foo;
44      $foo->load('Bar');
45      $foo->blah && $foo->method_that_bar_provides;
46
47
48 =head1 DESCRIPTION
49
50 Class::Modular is a superclass for generating modular classes, where
51 methods can be added into the class from the perspective of the
52 object, rather than the perspective of the class.
53
54 That is, you can create a class which has a set of generic common
55 functions. Less generic functions can be included or overridden
56 without modifying the base classes. This allows for code to be more
57 modular, and reduces code duplication.
58
59 This module attempts to fill the middle ground between
60 L<Class::Mutator> and true classless OOP, like L<Class::Classless>.
61
62 =head1 FUNCTIONS
63
64 =cut
65
66 use strict;
67 use vars qw($VERSION $DEBUG $REVISION $USE_SAFE);
68
69 use Carp;
70
71 use Storable qw(dclone); # Used for deep copying objects
72 use Safe; # Use Safe when we are dealing with coderefs
73
74 BEGIN{
75      $VERSION = q$0.03SVN$;
76      ($REVISION) = q$LastChangedRevision$ =~ /\$LastChangedRevision:\s+([^\s+])/;
77      $DEBUG = 0 unless defined $DEBUG;
78      $USE_SAFE = 1 unless defined $USE_SAFE;
79 }
80
81 # This is the class_modular namespace, so we don't muck up the
82 # subclass(es) by accident.
83
84 my $cm = q(__class_modular);
85
86 our $AUTOLOAD;
87
88
89 =head2 load
90
91      $cm->load('Subclass');
92      # or
93      $cm->load('Subclass',$options);
94
95 Loads the named Subclass into this object if the named Subclass has
96 not been loaded.
97
98 If debugging is enabled, will warn about loading already loaded
99 subclasses. Use C<$cm->is_loaded('Subclass')> to avoid these warnings.
100
101 =head3 Methods
102
103 If the subclass has a C<_methods> function (or at least,
104 UNIVERSAL::can thinks it does), C<_methods> is called to return a LIST
105 of methods that the subclass wishes to handle. The L<Class::Modular>
106 object and the options SCALAR are passed to the _methods function.
107
108 If the subclass does not have a C<_methods> function, then the array
109 C<@{"${subclass}::METHODS"}> is used to determine the methods that the
110 subclass will handle.
111
112 =head3 _init and required submodules
113
114 If the subclass has a C<_init> function (or at least, UNIVERSAL::can
115 thinks it does), C<_init> is called right after the module is
116 loaded. The L<Class::Modular> object and the options SCALAR are passed
117 to the _methods function. Typical uses for this call are to load other
118 required submodules.
119
120 As this is the most common thing to do in C<_init>, if a subclass
121 doesn't have one, then the array C<@{"${subclass}::SUB_MODULES"}> is
122 used to determine the subclass that need to be loaded:
123
124     for my $module (@{"${subclass}::SUB_MODULES"}) {
125          $self->is_loaded($module) || $self->load($module);
126     }
127
128 =cut
129
130 sub load($$;$) {
131      my ($self,$subclass,$options) = @_;
132
133      $options ||= {};
134
135      # check to see if the subclass has already been loaded.
136
137      if (not defined $self->{$cm}{_subclasses}{$subclass}){
138           eval {
139                no strict 'refs';
140                # Yeah, I don't care if calling an inherited AUTOLOAD
141                # for a non method is deprecated. Bite me.
142                no warnings 'deprecated';
143                eval "require $subclass" or die $@;
144                # We should read @METHODS and @SUB_MODULES and just do
145                # the right thing if at all possible.
146                my $methods = can($subclass,"_methods");
147                if (defined $methods) {
148                     $self->_addmethods($subclass,&$methods($self,$options));
149                }
150                else {
151                     $self->_addmethods($subclass,@{"${subclass}::METHODS"})
152                }
153                my $init = can($subclass,"_init");
154                if (defined $init) {
155                     &$init($self,$options);
156                }
157                else {
158                     for my $module (@{"${subclass}::SUB_MODULES"}) {
159                          $self->is_loaded($module) || $self->load($module);
160                     }
161                }
162           };
163           die $@ if $@;
164           $self->{$cm}{_subclasses}{$subclass} ||= {};
165      }
166      else {
167           carp "Not reloading subclass $subclass" if $DEBUG;
168      }
169 }
170
171 =head2 is_loaded
172
173      if ($cm->is_loaded('Subclass')) {
174            # do something
175      }
176
177 Tests to see if the named subclass is loaded.
178
179 Returns 1 if the subclass has been loaded, 0 otherwise.
180
181 =cut
182
183 sub is_loaded($$){
184      my ($self,$subclass) = @_;
185
186      # An entry will exist in the _subclasses hashref only if 
187      return 1 if exists $self->{$cm}{_subclasses}{$subclass}
188           and defined $self->{$cm}{_subclasses}{$subclass};
189      return 0;
190 }
191
192 =head2 override
193
194      $obj->override('methodname', $code_ref)
195
196 Allows you to override utility functions that are called internally to
197 provide a different default function.  It's superficially similar to
198 _addmethods, which is called by load, but it deals with code
199 references, and requires the method name to be known.
200
201 Methods overridden here are _NOT_ overrideable in _addmethods. This
202 may need to be changed.
203
204 =cut
205
206 sub override {
207      my ($self, $method_name, $function_reference) = @_;
208
209      $self->{$cm}{_methodhash}{$method_name}{reference} = $function_reference;
210      $self->{$cm}{_methodhash}{$method_name}{overridden} = 1;
211 }
212
213
214 =head2 clone
215
216      my $clone  = $obj->clone
217
218 Produces a clone of the object with duplicates of all data and/or new
219 connections as appropriate.
220
221 Calls _clone on all loaded subclasses.
222
223 Warns if debugging is on for classes which don't have a _clone method.
224 Dies on other errors.
225
226 clone uses L<Safe> to allow L<Storable> to deparse code references
227 sanely. Set C<$Class::Modular::USE_SAFE = 0> to disable this. [Doing
228 this may cause errors from Storable about CODE references.]
229
230 =cut
231
232 sub clone {
233      my ($self) = @_;
234
235      my $clone = {};
236      bless $clone, ref($self);
237
238      # copy data structures at this level
239      if ($self->{$cm}{use_safe}) {
240           my $safe = new Safe;
241           $safe->permit(qw(:default require));
242           local $Storable::Deparse = 1;
243           local $Storable::Eval = sub { $safe->reval($_[0]) };
244           $clone->{$cm}{_methodhash} = dclone($self->{$cm}{_methodhash});
245           $clone->{$cm}{_subclasses} = dclone($self->{$cm}{_subclasses});
246      }
247      else {
248           $clone->{$cm}{_methodhash} = dclone($self->{$cm}{_methodhash});
249           $clone->{$cm}{_subclasses} = dclone($self->{$cm}{_subclasses});
250      }
251
252      foreach my $subclass (keys %{$self->{$cm}{_subclasses}}) {
253           # Find out if the subclass has a clone method.
254           # If it does, call it, die on errors.
255           my $function = UNIVERSAL::can($subclass, '_clone');
256           eval {
257                no strict 'refs';
258                # No, I could care less that AUTOLOAD is
259                # deprecated. Eat me.
260                no warnings 'deprecated';
261                &{"${subclass}::_clone"}($self,$clone);
262           };
263           if ($@) {
264                # Die unless we've hit an undefined subroutine.
265                if ($@ !~ /^Undefined function ${subclass}::_clone at [^\n]*$/){
266                     die "Failed while trying to clone: $@";
267                }
268                else {
269                     carp "No _clone method defined for $subclass" if $DEBUG;
270                }
271           }
272      }
273 }
274
275
276 =head2 can
277
278      $obj->can('METHOD');
279      Class::Modular->can('METHOD');
280
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
283 anything it doesn't.
284
285 Returns a coderef to the method if the method is supported, undef
286 otherwise.
287
288 =cut
289
290 sub can{
291      my ($self,$method,$vars) = @_;
292
293      croak "Usage: can(object-ref, method, [vars]);\n" if not defined $method;
294
295      if (ref $self and exists $self->{$cm}{_methodhash}->{$method}) {
296           # If the method is defined, return a reference to the
297           # method.
298           return $self->{$cm}{_methodhash}{$method}{reference};
299      }
300      else {
301           # Otherwise, let UNIVERSAL::can deal with the method
302           # appropriately.
303           return UNIVERSAL::can($self,$method);
304      }
305 }
306
307
308 =head2 handledby
309
310      $obj->handledby('methodname');
311      $obj->handledby('Class::Method::methodname');
312
313 Returns the subclass that handles the method methodname.
314
315 =cut
316
317 sub handledby{
318      my ($self,$method_name) = @_;
319
320      $method_name =~ s/.*\://;
321
322      if (exists $self->{$cm}{_methodhash}{$method_name}) {
323           return $self->{$cm}{_methodhash}{$method_name}{subclass};
324      }
325      return undef;
326 }
327
328
329 =head2 new
330
331      $obj = Foo::Bar->new(qw(baz quux));
332
333 Creates a new Foo::Bar object
334
335 Aditional arguments can be passed to this creator, and they are stored
336 in $self->{creation_args} (and $self->{$cm}{creation_args} by
337 _init.
338
339 This new function creates an object of Class::Modular, and calls the
340 C<$self->load(Foo::Bar)>, which will typically do what you want.
341
342 If you override this method in your subclasses, you will not be able
343 to use override to override methods defined within those
344 subclasses. This may or may not be a feature. You must also call
345 C<$self->SUPER::_init(@_)> if you override new.
346
347 =cut
348
349 sub new {
350      my ($class,@args) = @_;
351
352      # We shouldn't be called $me->new, but just in case
353      $class = ref($class) || $class;
354
355      my $self = {};
356
357      # But why, Don, are you being evil and not using the two argument
358      # bless properly?
359
360      # My child, we always want to go to Class::Modular first,
361      # otherwise we will be unable to override methods in subclasses.
362
363      # But doesn't this mean that subclasses won't be able to override
364      # us?
365
366      # Only if they don't also override new!
367
368      bless $self, 'Class::Modular';
369
370      $self->_init(@args);
371
372      # Now we call our subclass's load routine so that our evil deeds
373      # are masked
374
375      $self->load($class);
376
377      return $self;
378 }
379
380
381 =head1 FUNCTIONS YOU PROBABLY DON'T CARE ABOUT
382
383 =head2 DESTROY
384
385      undef $foo;
386
387 Calls all subclass _destroy methods.
388
389 Subclasses need only implement a _destroy method if they have
390 references that need to be uncircularized, or things that should be
391 disconnected or closed.
392
393 =cut
394
395 sub DESTROY{
396      my $self = shift;
397      foreach my $subclass (keys %{$self->{$cm}{_subclasses}}) {
398           # use eval to try and call the subclasses _destroy method.
399           # Ignore no such function errors, but trap other types of
400           # errors.
401           eval {
402                no strict 'refs';
403                # Shove off, deprecated AUTOLOAD warning!
404                no warnings 'deprecated';
405                &{"${subclass}::_destroy"}($self);
406           };
407           if ($@) {
408                if ($@ !~ /^Undefined (function|subroutine) \&?${subclass}::_destroy (|called )at [^\n]*$/){
409                     die "Failed while trying to destroy: $@";
410                }
411                else {
412                     carp "No _destroy method defined for $subclass" if $DEBUG;
413                }
414           }
415      }
416 }
417
418
419 =head2 AUTOLOAD
420
421 The AUTOLOAD function is responsible for calling child methods which
422 have been installed into the current Class::Modular handle.
423
424 Subclasses that have a new function as well as an AUTOLOAD function
425 must call Class::Modular::AUTOLOAD and set $Class::Modular::AUTOLOAD
426
427      $Class::Modular::AUTOLOAD = $AUTOLOAD;
428      goto &Class::Modular::AUTOLOAD;
429
430 Failure to do the above will break Class::Modular utterly.
431
432 =cut
433
434 sub AUTOLOAD{
435      my $method = $AUTOLOAD;
436
437      $method =~ s/.*\://;
438
439      my ($self) = @_;
440
441      if (not ref($self)) {
442          carp "Not a reference in AUTOLOAD.";
443          return;
444      }
445
446      if (exists $self->{$cm}{_methodhash}{$method} and
447          defined $self->{$cm}{_methodhash}{$method}{reference}) {
448           eval {
449                no strict 'refs';
450                goto &{$self->{$cm}{_methodhash}{$method}{reference}};
451           }
452      }
453      else {
454           croak "Undefined function $AUTOLOAD";
455      }
456 }
457
458 =head2 _init
459
460      $self->_init(@args);
461
462 Stores the arguments used at new so modules that are loaded later can
463 read them from B<creation_args>
464
465 You can also override this method, but if you do so, you should call
466 Class::Modular::_init($self,@_) if you don't set creation_args.
467
468 =cut
469
470 sub _init {
471      my ($self,@creation_args) = @_;
472
473      my $creation_args = [@_];
474      $self->{creation_args} = $creation_args if not exists $self->{creation_args};
475
476      # Make another reference to this, so we can get it if a subclass
477      # overwrites it, or if it was already set for some reason
478      $self->{$cm}->{creation_args} = $creation_args;
479      $self->{$cm}->{use_safe} = $USE_SAFE;
480 }
481
482
483 =head2 _addmethods
484
485      $self->_addmethods()
486
487 Given an array of methods, adds the methods into the _methodhash
488 calling table.
489
490 Methods that have previously been overridden by override are _NOT_
491 overridden again. This may need to be adjusted in load.
492
493 =cut
494
495 sub _addmethods($@) {
496      my ($self,$subclass,@methods) = @_;
497
498      # stick the method into the table
499      # DLA: Make with the munchies!
500
501      foreach my $method (@methods) {
502           if (not $method =~ /^$subclass/) {
503                $method = $subclass.'::'.$method;
504           }
505           my ($method_name) = $method =~ /\:*([^\:]+)\s*$/;
506           if (exists $self->{$cm}{_methodhash}{$method_name}) {
507                if ($self->{$cm}{_methodhash}{$method_name}{overridden}) {
508                     carp "Not overriding already overriden method $method_name\n" if $DEBUG;
509                     next;
510                }
511                carp "Overriding $method_name $self->{$cm}{_methodhash}{$method_name}{reference} with $method\n";
512           }
513           $self->{$cm}{_methodhash}{$method_name}{reference} = $method;
514           $self->{$cm}{_methodhash}{$method_name}{subclass} = $subclass;
515      }
516
517 }
518
519
520 1;
521
522
523 __END__
524
525 =head1 BUGS
526
527 Because this module works through AUTOLOAD, utilities that use
528 can($object) instead of $object->can() will fail to see routines that
529 are actually there. Params::Validate, an excellent module, is
530 currently one of these offenders.
531
532 =head1 COPYRIGHT
533
534 This module is part of DA, Don Armstrong's Modules, and is released
535 under the terms of the GPL version 2, or any later version. See the
536 file README and COPYING for more information.
537
538 Copyright 2003, 2004 by Don Armstrong <don@donarmstrong.com>
539
540 =cut
541
542
543
544