/[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.12 - (hide annotations)
Tue May 13 08:39:22 2003 UTC (21 years ago) by joko
Branch: MAIN
Changes since 1.11: +186 -14 lines
autocalling constructor after instantiation
added pod documentation

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

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