/[cvs]/nfo/perl/libs/DesignPattern/Bridge.pm
ViewVC logotype

Annotation of /nfo/perl/libs/DesignPattern/Bridge.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.13 - (hide annotations)
Tue Jul 1 23:26:37 2003 UTC (20 years, 10 months ago) by joko
Branch: MAIN
CVS Tags: HEAD
Changes since 1.12: +12 -2 lines
croak to STDERR if module loading fails!

1 joko 1.1 ## --------------------------------------------------------------------------------
2 joko 1.13 ## $Id: Bridge.pm,v 1.12 2003/05/13 08:39:22 joko Exp $
3 joko 1.1 ## --------------------------------------------------------------------------------
4 joko 1.2 ## $Log: Bridge.pm,v $
5 joko 1.13 ## Revision 1.12 2003/05/13 08:39:22 joko
6     ## autocalling constructor after instantiation
7     ## added pod documentation
8     ##
9 joko 1.12 ## Revision 1.11 2003/02/21 08:38:21 joko
10     ## + additional checks
11     ## + raising exceptions
12     ##
13 joko 1.11 ## Revision 1.10 2003/02/20 20:50:32 joko
14     ## + small exception handling: now inheriting from little Exception object
15     ##
16 joko 1.10 ## Revision 1.9 2003/02/18 18:35:30 joko
17     ## + encapsulated/abstracted some more functionality: sub load_single
18     ##
19 joko 1.9 ## Revision 1.8 2003/02/14 14:20:05 joko
20     ## + modified mixin behaviour
21     ##
22 joko 1.8 ## Revision 1.7 2003/02/11 10:34:19 joko
23     ## + loaded module may now lack 'mixin::with' declaration
24     ## + this gets us the possibility to load modules from any perl namespace
25     ## + enabled this mechanism
26     ##
27 joko 1.7 ## Revision 1.6 2003/02/09 16:22:51 joko
28     ## + pseudo constructor mechanism via options
29     ##
30 joko 1.6 ## Revision 1.5 2003/01/31 01:19:50 root
31     ## + fixed: doesn't need Log::Dispatch any more, but uses it if available
32     ##
33 root 1.5 ## Revision 1.4 2003/01/20 16:55:15 joko
34     ## + sub mixinPackage
35     ## + sub include
36     ##
37 joko 1.4 ## Revision 1.3 2002/12/16 19:57:12 joko
38     ## + sub unload
39     ##
40 joko 1.3 ## Revision 1.2 2002/12/15 02:06:15 joko
41     ## + feature to be able to specify module in non-perl-style when loading plugins: e.g. $process->load('Setup/Storage')
42     ##
43 joko 1.2 ## Revision 1.1 2002/12/13 21:46:29 joko
44     ## + initial check-in
45     ##
46 joko 1.1 ## --------------------------------------------------------------------------------
47    
48    
49     package DesignPattern::Bridge;
50    
51     use strict;
52     use warnings;
53    
54 joko 1.10 use base qw(
55     DesignPattern::Object
56     DesignPattern::Exception
57     );
58 joko 1.1
59 joko 1.11
60 joko 1.2 use Data::Dumper;
61    
62 joko 1.12 =pod
63    
64     =head1 NAME
65    
66     DesignPattern::Bridge
67    
68    
69     =head1 DESCRIPTION
70    
71     This acts as a generic backplane for plugins using "Mix-in inheritance".
72    
73    
74     =head2 BACKGROUND
75    
76     Mix-in inheritance
77     Please visit [http://citeseer.nj.nec.com/bracha90mixinbased.html].
78    
79     [...]
80     Abstract: The diverse inheritance mechanisms provided by Smalltalk, Beta,
81     and CLOS are interpreted as different uses of a single underlying construct.
82     Smalltalk and Beta differ primarily in the direction of class hierarchy growth.
83     These inheritance mechanisms are subsumed in a new inheritance model
84     based on composition of mixins, or abstract subclasses. This form of
85     inheritance can also encode a CLOS multiple-inheritance hierarchy, although
86     changes to the encoded hierarchy that would violate... (Update)
87     [...]
88    
89     ...level, and can naturally span component boundaries. Jiazzi supports
90     the composition of class extending components; e.g. mixins [1]. Mixins
91     and cyclic component linking can be combined into an open class pattern,
92     which allows independent features that cross cut class...
93    
94     =head3 History of "mixins"
95    
96     =head4 G. Bracha, W. Cook. Mixin-based inheritance.
97    
98     G. Bracha and W. Cook, "Mixin-Based Inheritance", ECOOP/OOPSLA 1990, 303-311.
99     G. Bracha, W. Cook. Mixin-based inheritance. In OOPSLA/ECOOP '90 Conference Proceedings. ACM SIGPLAN Notices 25, 10 (Oct. 1990).
100    
101     @inproceedings{ bracha90mixinbased,
102     author = "Gilad Bracha and William Cook",
103     title = "Mixin-Based Inheritance",
104     booktitle = "Proceedings of the Conference on Object-Oriented Programming: Systems, Languages, and Applications / Proceedings of the European Conference on Object-Oriented Programming",
105     publisher = "ACM Press",
106     address = "Ottawa, Canada",
107     editor = "Norman Meyrowitz",
108     pages = "303--311",
109     year = "1990",
110     url = "citeseer.nj.nec.com/bracha90mixinbased.html" }
111    
112     =head4 D. Duggan and C. Sourelis. Mixin modules.
113    
114     http://users.hol.gr/~csourelis/thesis.html
115    
116     @misc{ duggan96mixin,
117     author = "D. Duggan and C. Sourelis",
118     title = "Mixin modules",
119     text = "D. Duggan and C. Sourelis. Mixin modules. In Intl. Conf. on Functional
120     Programming, Philadelphia, May 1996. ACM Press.",
121     year = "1996",
122     url = "citeseer.nj.nec.com/sourelis95mixin.html" }
123    
124     =head4 Google on your own:
125    
126     http://www.google.com/search?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&q=mix-in+inheritance
127     http://www.google.com/search?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&q=Moo86+mixins
128    
129    
130     =head3 Discussion
131    
132     http://citeseer.nj.nec.com/context/6117/0
133    
134     =head2 References
135    
136     The Jigsaw Framework:
137     http://citeseer.nj.nec.com/bracha92programming.html
138    
139     http://citeseer.nj.nec.com/114070.html
140     http://citeseer.nj.nec.com/445396.html
141     http://citeseer.nj.nec.com/tichelaar97coordination.html
142     http://citeseer.nj.nec.com/meijler98beyond.html
143    
144     http://citeseer.nj.nec.com/89291.html
145     http://citeseer.nj.nec.com/sousa91runtime.html
146     http://citeseer.nj.nec.com/banavar95application.html
147     http://citeseer.nj.nec.com/sourelis95mixin.html
148     http://citeseer.nj.nec.com/hirschowitz02mixin.html
149    
150     Java: http://csis.pace.edu/~bergin/patterns/multipleinheritance.html
151     C++: http://www.oofile.com.au/oofdoc/samples/ooftst19.htm
152    
153     =head3 Related
154    
155     http://citeseer.nj.nec.com/nrelated/6117/23339
156    
157 joko 1.1
158 joko 1.12 =head3 Traits - Composable Units of Behavior
159 joko 1.1
160 joko 1.12 via: http://citeseer.nj.nec.com/context/22076/0
161    
162     Traits: Composable Units of Behavior - Nathanael Schrli Stphane (Correct)
163     ....is not expressive enough to factor out common features (i.e. instance
164     variables and methods) shared by classes in a complex hierarchy. As a
165     consequence, language designers have proposed various forms of multiple
166     inheritance [Mey88] Kee89] Str86] as well as other mechanisms, such as
167     mixins [Moo86] BC90] FKF98] that allow classes to be composed incrementally
168     from sets of features. Despite the passage of nearly twenty years, neither
169     multiple inheritance nor mixins have achieved wide acceptance [Tai96]
170     Summarizing Alan Snyder s contribution to the inheritance panel discussion
171     at OOPSLA ....
172    
173     ....complete. But as a unit of reuse, a class should be small. These properties
174     often conflict. Furthermore, the role of classes as instance generators requires
175     that each class have a unique place in the class hierarchy, whereas units of
176     reuse should be applicable at arbitrary places. Moon s Flavors [Moo86] were
177     an early attempt to address this problem: Flavors are small, not necessarily
178     complete, and they can be mixed in at arbitrary places in the class hierarchy.
179     More sophisticated notions of mixins were subsequently developed by Bracha
180     and Cook [BC90] and Flatt, Krishnamurthi and Felleisen ....
181    
182     David A. Moon. Object-oriented programming with flavors. In Proceedings
183     OOPSLA '86, ACM SIGPLAN Notices, pages 1--8, November 1986.
184     Published as Proceedings OOPSLA '86, ACM SIGPLAN Notices, volume 21, number 11.
185    
186    
187     from: http://citeseer.nj.nec.com/566972.html
188    
189     Abstract: Inheritance is the fundamental reuse mechanism in object-oriented
190     programming languages; its most prominent variants are single inheritance,
191     multiple inheritance, and mixin inheritance. In the first part of this paper,
192     we identify and illustrate the conceptual and practical reusability problems
193     that arise with these forms of inheritance. We then present a simple
194     compositional model for structuring object-oriented programs, which we call traits.
195     Traits are essentially groups of methods... (Update)
196    
197    
198     =head3 Hybrid - A Language for Programming with Active Objects
199    
200     http://citeseer.nj.nec.com/561934.html
201     http://citeseer.nj.nec.com/nierstrasz92tour.html
202     http://www.iam.unibe.ch/~scg/Archive/NFS/cao.html
203    
204     =head3 Active Objects and Oberon
205    
206    
207     =head2 DETAILS
208    
209     This attempts to be a runtime wrapper around mixin.pm, written by Michael G Schwern
210     and available on CPAN.
211     Please visit:
212     http://magnonel.guild.net/~schwern/talks/Design_Patterns/full_slides/slide036.html
213    
214    
215     =head2 NOTES
216    
217     ## ======== object inheritance ========
218    
219     2002-12:
220     TODO / REFACTORING PROPOSAL
221     leading from Data::Storage to code abstracted out into this module - DesignPattern::Bridge
222     - this is no inheritance and it doesn't have to be
223     - implement this module as a bridge to its sub-modules
224     - use the BridgePattern (http://c2.com/cgi/wiki?BridgePattern)
225     Using patterns was already successfully done with Data::Storage::Handler
226     by implementing the AdapterPattern (http://c2.com/cgi/wiki?AdapterPattern)
227     with Perl's AUTOLOAD-mechanism
228     - try to use Perl's "tie" command to implement this functionality here instead of using AUTOLOAD!
229     - sub getChildNodes
230     - sub run
231    
232     2003-02-11, joko: Does this have anything in parallel with CPAN's Class::Inner? No!
233    
234    
235     =head1 TODO
236    
237     o use Class::Loader
238     o rename to mixin::runtime?
239    
240    
241     =cut
242 joko 1.7
243    
244 joko 1.1 # get logger instance
245 root 1.5 my $logger = eval { Log::Dispatch::Config->instance; };
246 joko 1.1
247 joko 1.3 my $meta;
248 joko 1.1
249 joko 1.13
250     sub DEBUG { 1 }
251    
252    
253 joko 1.1 ## ======== object constructor ========
254 joko 1.7 sub new {
255     my $invocant = shift;
256     my $class = ref($invocant) || $invocant;
257     my @args = ();
258     @_ && (@args = @_);
259     $logger->debug( __PACKAGE__ . "->new(@args)" ) if $logger;
260     my $self = { @_ };
261    
262     # trace
263 joko 1.1 #print "class: $class", "\n";
264 joko 1.7
265     # create instance
266     bless $self, $class;
267 joko 1.12
268     # NEW: 2003-04-16
269     $self->constructor() if $self->can('constructor');
270 joko 1.7
271     return $self;
272     }
273 joko 1.1
274    
275     ## ======== method overrider ========
276     sub AUTOLOAD2 {
277    
278     my $self = shift;
279     our $AUTOLOAD;
280    
281     ##print "AUTOLOAD\n";
282    
283     my $method = $AUTOLOAD;
284     $method =~ s/^.*:://;
285    
286 root 1.5 $logger->debug( __PACKAGE__ . "->" . $method . "(@_)" . " (AUTOLOAD called, not dispatched)" ) if $logger;
287 joko 1.1
288     ## ->DESTROY would - if not declared - trigger an AUTOLOAD also
289     return if $method =~ m/::DESTROY$/;
290    
291     ## if ($self->_filter_AUTOLOAD($method)) {
292     ## $self->_accessStorage();
293     ## $self->{STORAGEHANDLE}->$method(@_);
294     ## }
295    
296     }
297 joko 1.3
298     sub _getPluginPackage {
299     my $self = shift;
300     my $modulename_load = shift;
301    
302     # substitute slashes through double double-colons to load modules perl-style
303     $modulename_load =~ s/\//::/g;
304    
305     # build full package name
306     my $self_classname = ref $self;
307 joko 1.7 # name
308     my $package = $modulename_load;
309    
310     # if package is absolute, cut away prefix ('/' or '::')
311     if ($package !~ s/^:://) {
312     # else: prefix with base classname if above name is relative (lacks of '/' or '::')
313     $package = $self_classname . '::' . $package
314     }
315    
316 joko 1.3 return $package;
317     }
318 joko 1.1
319     sub load {
320 joko 1.9
321     my $self = shift;
322     my $modulename = shift;
323     my $options = shift;
324    
325     if (ref $modulename eq 'ARRAY') {
326     foreach (@$modulename) {
327     $self->load_single($_, $options);
328     }
329     } else {
330     $self->load_single($modulename, $options);
331     }
332    
333     }
334    
335     sub load_single {
336 joko 1.1
337     my $self = shift;
338 joko 1.3 my $modulename_load = shift;
339 joko 1.1
340 joko 1.6 my $options = shift;
341    
342 joko 1.4 my $self_modulename = ref $self;
343 joko 1.3 my $package = $self->_getPluginPackage($modulename_load);
344 joko 1.1
345 joko 1.3 if ($meta->{loaded}->{$package}) {
346     return 1;
347     }
348 joko 1.2
349 root 1.5 #$logger->info( __PACKAGE__ . "->load: $package" ) if $logger;
350     #$logger->info( __PACKAGE__ . "->load: $self_modulename" ) if $logger;
351     $logger->debug( $self_modulename . "->load: $package\t[via " . __PACKAGE__ . "]" ) if $logger;
352 joko 1.1
353     # this is the module testing phase - use mixin doesn't seem to propagate errors by default
354     eval("use $package;");
355 joko 1.10 $self->checkExceptions();
356    
357     =pod
358 joko 1.1 if ($@) {
359 joko 1.3 $meta->{loaded}->{$package} = 0;
360 joko 1.2 # include caller information
361     my @caller = caller;
362     my $caller_msg = $caller[1] . ':' . $caller[2];
363 root 1.5 my $msg = __PACKAGE__ . "->load: $@ ($caller_msg)";
364     if ($logger) {
365     $logger->error($msg);
366     } else {
367     print $msg, "\n";
368     }
369 joko 1.1 }
370 joko 1.10 =cut
371 joko 1.1
372     #print "ref-1: ", ref $self, "\n";
373     #print "ref-2: ", ref $self::SUPER, "\n";
374    
375     # V1:
376     #bless $self, $package;
377    
378     # V2:
379 joko 1.8 $self->mixinPackage($package);
380    
381     if (my $method = $options->{method}) {
382     $self->$method();
383     }
384 joko 1.7
385 joko 1.8 return 1;
386    
387     }
388    
389     sub mixinPackage {
390     my $self = shift;
391     my $package = shift;
392    
393 joko 1.7 # switch into foreign package and prepare for mixin
394     $self->mixin_prepare($package);
395    
396     # switch into local package (scope which uses DesignPattern::Bridge) and mixin plugin-module
397     $self->mixin_do($package);
398 joko 1.6
399 joko 1.4 }
400    
401     # TODO: maybe refactor to DesignPattern::Object? what about the '$logger'?
402 joko 1.7 sub mixin_prepare {
403     my $self = shift;
404     my $package = shift;
405     my $self_classname = ref $self;
406     eval("package $package; use mixin::with '$self_classname';");
407    
408     # FIXME: --- this is redundant ---
409     if ($@) {
410     $meta->{loaded}->{$package} = 0;
411 joko 1.13 my $msg = __PACKAGE__ . "->load: $@";
412     print STDERR $msg, "\n" if DEBUG;
413     $logger->error( $msg ) if $logger;
414 joko 1.7 } else {
415     $meta->{loaded}->{$package} = 1;
416     }
417     # FIXME: --- this is redundant ---
418    
419     }
420    
421     sub mixin_do {
422 joko 1.4 my $self = shift;
423     my $package = shift;
424     # switch into foreign package and mixin plugin-module
425 joko 1.3 my $self_classname = ref $self;
426 joko 1.1 eval("package $self_classname; use mixin '$package';");
427     #eval("use mixin_all '$package';");
428 joko 1.7
429     # FIXME: --- this is redundant ---
430 joko 1.1 if ($@) {
431 joko 1.3 $meta->{loaded}->{$package} = 0;
432 root 1.5 $logger->error( __PACKAGE__ . "->load: $@" ) if $logger;
433 joko 1.3 } else {
434     $meta->{loaded}->{$package} = 1;
435 joko 1.1 }
436 joko 1.7 # FIXME: --- this is redundant ---
437    
438 joko 1.3 }
439    
440     sub unload {
441    
442     my $self = shift;
443     my $modulename_unload = shift;
444    
445     my $package = $self->_getPluginPackage($modulename_unload);
446 joko 1.1
447 joko 1.3 if ($meta->{loaded}->{$package}) {
448     $meta->{loaded}->{$package} = 0;
449     my $where = __PACKAGE__ . ':' . __LINE__;
450 root 1.5 $logger->debug( __PACKAGE__ . "->unload: FIXME: DESTROY object is not implemented at '$where'." ) if $logger;
451 joko 1.3 }
452    
453 joko 1.1 }
454 joko 1.3
455 joko 1.1
456     sub boot {
457     my $self = shift;
458     $self->_abstract_function('boot');
459 joko 1.4 }
460    
461     sub include {
462     my $self = shift;
463     my $includefile = shift;
464     my $package = shift;
465 joko 1.11
466     # pre-flight checks
467     if (!$includefile) {
468     $self->raiseException('Filename for inclusion was empty.');
469     return;
470     }
471    
472     # go for it ...
473     eval("require '$includefile';");
474     # ... and handle errors afterwards catching every message from perl itself ...
475     return if $self->checkExceptions();
476    
477     # ... otherwise continue assuming everything is fine
478 joko 1.4 $self->mixinPackage($package) if $package;
479 joko 1.11
480 joko 1.1 }
481    
482     1;
483 joko 1.7 __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed