/[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.10 - (show annotations)
Thu Feb 20 20:50:32 2003 UTC (21 years, 3 months ago) by joko
Branch: MAIN
Changes since 1.9: +12 -2 lines
+ small exception handling: now inheriting from little Exception object

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

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