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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (show annotations)
Fri Feb 14 14:20:05 2003 UTC (21 years, 3 months ago) by joko
Branch: MAIN
Changes since 1.7: +19 -7 lines
+ modified mixin behaviour

1 ## --------------------------------------------------------------------------------
2 ## $Id: Bridge.pm,v 1.7 2003/02/11 10:34:19 joko Exp $
3 ## --------------------------------------------------------------------------------
4 ## $Log: Bridge.pm,v $
5 ## Revision 1.7 2003/02/11 10:34:19 joko
6 ## + loaded module may now lack 'mixin::with' declaration
7 ## + this gets us the possibility to load modules from any perl namespace
8 ## + enabled this mechanism
9 ##
10 ## Revision 1.6 2003/02/09 16:22:51 joko
11 ## + pseudo constructor mechanism via options
12 ##
13 ## Revision 1.5 2003/01/31 01:19:50 root
14 ## + fixed: doesn't need Log::Dispatch any more, but uses it if available
15 ##
16 ## Revision 1.4 2003/01/20 16:55:15 joko
17 ## + sub mixinPackage
18 ## + sub include
19 ##
20 ## Revision 1.3 2002/12/16 19:57:12 joko
21 ## + sub unload
22 ##
23 ## Revision 1.2 2002/12/15 02:06:15 joko
24 ## + feature to be able to specify module in non-perl-style when loading plugins: e.g. $process->load('Setup/Storage')
25 ##
26 ## Revision 1.1 2002/12/13 21:46:29 joko
27 ## + initial check-in
28 ##
29 ## --------------------------------------------------------------------------------
30
31
32 package DesignPattern::Bridge;
33
34 use strict;
35 use warnings;
36
37 use base qw( DesignPattern::Object );
38
39 use Data::Dumper;
40
41 ## ======== object inheritance ========
42
43 # TODO / REFACTORING PROPOSAL
44 # leading from Data::Storage to code abstracted out into this module - DesignPattern::Bridge
45 # - this is no inheritance and it doesn't have to be
46 # - implement this module as a bridge to its sub-modules
47 # - use the BridgePattern (http://c2.com/cgi/wiki?BridgePattern)
48 # Using patterns was already successfully done with Data::Storage::Handler
49 # by implementing the AdapterPattern (http://c2.com/cgi/wiki?AdapterPattern)
50 # with Perl's AUTOLOAD-mechanism
51 # - try to use Perl's "tie" command to implement this functionality here instead of using AUTOLOAD!
52 # - sub getChildNodes
53 # - sub run
54
55 # 2003-02-11, joko: does this have anything in parallel with CPAN's Class::Inner?
56
57
58 # get logger instance
59 my $logger = eval { Log::Dispatch::Config->instance; };
60
61 my $meta;
62
63 ## ======== object constructor ========
64 sub new {
65 my $invocant = shift;
66 my $class = ref($invocant) || $invocant;
67 my @args = ();
68 @_ && (@args = @_);
69 $logger->debug( __PACKAGE__ . "->new(@args)" ) if $logger;
70 my $self = { @_ };
71
72 # trace
73 #print "class: $class", "\n";
74
75 # create instance
76 bless $self, $class;
77
78 return $self;
79 }
80
81
82 ## ======== method overrider ========
83 sub AUTOLOAD2 {
84
85 my $self = shift;
86 our $AUTOLOAD;
87
88 ##print "AUTOLOAD\n";
89
90 my $method = $AUTOLOAD;
91 $method =~ s/^.*:://;
92
93 $logger->debug( __PACKAGE__ . "->" . $method . "(@_)" . " (AUTOLOAD called, not dispatched)" ) if $logger;
94
95 ## ->DESTROY would - if not declared - trigger an AUTOLOAD also
96 return if $method =~ m/::DESTROY$/;
97
98 ## if ($self->_filter_AUTOLOAD($method)) {
99 ## $self->_accessStorage();
100 ## $self->{STORAGEHANDLE}->$method(@_);
101 ## }
102
103 }
104
105 sub _getPluginPackage {
106 my $self = shift;
107 my $modulename_load = shift;
108
109 # substitute slashes through double double-colons to load modules perl-style
110 $modulename_load =~ s/\//::/g;
111
112 # build full package name
113 my $self_classname = ref $self;
114 # name
115 my $package = $modulename_load;
116
117 # if package is absolute, cut away prefix ('/' or '::')
118 if ($package !~ s/^:://) {
119 # else: prefix with base classname if above name is relative (lacks of '/' or '::')
120 $package = $self_classname . '::' . $package
121 }
122
123 return $package;
124 }
125
126 sub load {
127
128 my $self = shift;
129 my $modulename_load = shift;
130
131 my $options = shift;
132
133 my $self_modulename = ref $self;
134 my $package = $self->_getPluginPackage($modulename_load);
135
136 if ($meta->{loaded}->{$package}) {
137 return 1;
138 }
139
140 #$logger->info( __PACKAGE__ . "->load: $package" ) if $logger;
141 #$logger->info( __PACKAGE__ . "->load: $self_modulename" ) if $logger;
142 $logger->debug( $self_modulename . "->load: $package\t[via " . __PACKAGE__ . "]" ) if $logger;
143
144 # this is the module testing phase - use mixin doesn't seem to propagate errors by default
145 eval("use $package;");
146 if ($@) {
147 $meta->{loaded}->{$package} = 0;
148 # include caller information
149 my @caller = caller;
150 my $caller_msg = $caller[1] . ':' . $caller[2];
151 my $msg = __PACKAGE__ . "->load: $@ ($caller_msg)";
152 if ($logger) {
153 $logger->error($msg);
154 } else {
155 print $msg, "\n";
156 }
157 }
158
159 #print "ref-1: ", ref $self, "\n";
160 #print "ref-2: ", ref $self::SUPER, "\n";
161
162 # V1:
163 #bless $self, $package;
164
165 # V2:
166 $self->mixinPackage($package);
167
168 if (my $method = $options->{method}) {
169 $self->$method();
170 }
171
172 return 1;
173
174 }
175
176 sub mixinPackage {
177 my $self = shift;
178 my $package = shift;
179
180 # switch into foreign package and prepare for mixin
181 $self->mixin_prepare($package);
182
183 # switch into local package (scope which uses DesignPattern::Bridge) and mixin plugin-module
184 $self->mixin_do($package);
185
186 }
187
188 # TODO: maybe refactor to DesignPattern::Object? what about the '$logger'?
189 sub mixin_prepare {
190 my $self = shift;
191 my $package = shift;
192 my $self_classname = ref $self;
193 eval("package $package; use mixin::with '$self_classname';");
194
195 # FIXME: --- this is redundant ---
196 if ($@) {
197 $meta->{loaded}->{$package} = 0;
198 $logger->error( __PACKAGE__ . "->load: $@" ) if $logger;
199 } else {
200 $meta->{loaded}->{$package} = 1;
201 }
202 # FIXME: --- this is redundant ---
203
204 }
205
206 sub mixin_do {
207 my $self = shift;
208 my $package = shift;
209 # switch into foreign package and mixin plugin-module
210 my $self_classname = ref $self;
211 eval("package $self_classname; use mixin '$package';");
212 #eval("use mixin_all '$package';");
213
214 # FIXME: --- this is redundant ---
215 if ($@) {
216 $meta->{loaded}->{$package} = 0;
217 $logger->error( __PACKAGE__ . "->load: $@" ) if $logger;
218 } else {
219 $meta->{loaded}->{$package} = 1;
220 }
221 # FIXME: --- this is redundant ---
222
223 }
224
225 sub unload {
226
227 my $self = shift;
228 my $modulename_unload = shift;
229
230 my $package = $self->_getPluginPackage($modulename_unload);
231
232 if ($meta->{loaded}->{$package}) {
233 $meta->{loaded}->{$package} = 0;
234 my $where = __PACKAGE__ . ':' . __LINE__;
235 $logger->debug( __PACKAGE__ . "->unload: FIXME: DESTROY object is not implemented at '$where'." ) if $logger;
236 }
237
238 }
239
240
241 sub boot {
242 my $self = shift;
243 $self->_abstract_function('boot');
244 }
245
246 sub include {
247 my $self = shift;
248 my $includefile = shift;
249 my $package = shift;
250 # TODO: do better error-detection here / prevent dies under all circumstances!
251 require $includefile;
252 $self->mixinPackage($package) if $package;
253 }
254
255 1;
256 __END__

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