/[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.9 - (show annotations)
Tue Feb 18 18:35:30 2003 UTC (21 years, 3 months ago) by joko
Branch: MAIN
Changes since 1.8: +20 -1 lines
+ encapsulated/abstracted some more functionality: sub load_single

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

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