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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (show annotations)
Thu Mar 27 15:44:32 2003 UTC (21 years, 1 month ago) by joko
Branch: MAIN
Changes since 1.8: +17 -2 lines
fixes/enhancements to 'sub log_basic'

1 ## ---------------------------------------------------------------------------
2 ## $Id: Object.pm,v 1.8 2003/02/19 00:36:59 joko Exp $
3 ## ---------------------------------------------------------------------------
4 ## $Log: Object.pm,v $
5 ## Revision 1.8 2003/02/19 00:36:59 joko
6 ## + bugfix: this {logger} is the instance itself, so has to be fed with ( level => xyz and namespace => xyz )
7 ## + minor modifications in behaviour
8 ##
9 ## Revision 1.7 2003/02/18 18:34:35 joko
10 ## + fix: just logs if possible (sub log_basic)
11 ##
12 ## Revision 1.6 2003/02/11 11:04:27 joko
13 ## + metadata (args, caller, etc.) are now stored inside {__bridge}
14 ##
15 ## Revision 1.5 2003/02/09 16:24:46 joko
16 ## + pseudo constructor mechanism by calling method 'constructor' on object instantiation
17 ##
18 ## Revision 1.4 2003/01/22 17:56:49 root
19 ## + fix: just use the logger if it's available
20 ##
21 ## Revision 1.3 2003/01/20 16:54:22 joko
22 ## + sub fromPackage: refactored from libp's 'getNewPerlObjFromPkgName' or s.th.l.th.
23 ##
24 ## Revision 1.2 2002/12/27 16:05:42 joko
25 ## + played with Devel::CallerItem and Devel::StackTrace
26 ##
27 ## Revision 1.1 2002/12/13 21:46:29 joko
28 ## + initial check-in
29 ##
30 ## ---------------------------------------------------------------------------
31
32
33 package DesignPattern::Object;
34
35 use strict;
36 use warnings;
37
38
39 use Data::Dumper;
40 #use Devel::CallerItem;
41 #use Devel::StackTrace;
42
43
44 my $_dp_globals;
45
46 $_dp_globals = {
47 TRACE => 0,
48 };
49
50
51 sub new {
52
53 # the classname in most cases
54 my $classname = shift;
55
56 # use already blessed reference, if passed in - else use the very classname
57 my $class = ref ($classname) || $classname;
58
59 #$self->log_basic( "$classname->new( ... )" . "\t[via " . __PACKAGE__ . "]" , 'debug');
60
61 # the base for our object - a plain perl hash, which ....
62 my $self = {};
63 # note:
64 # this makes an instance of an arbitrary perl variable,
65 # the most often used for this purpose is - guess it - the hash,
66 # since it resembles object-properties in a convenient way:
67 # $object->{property} = 'Hello World!';
68 # if you _do_ care about privacy you might take a look
69 # at CPAN's Tie::SecureHash or Class::Contract ... have fun!
70
71 # TODO: what about logging in here? inherit from
72 # DesignPattern::Object::Logger for this purpose....
73 # ... or would this give us (harmful) circular module dependencies???
74 #$self->log_basic( __PACKAGE__ . "->new( @args )", 'debug' ); # this is not "common"!
75
76
77 # remember the stacktrace: abstract this out (DesignPattern::Object::Trace) or parametrize!
78 #my $trace = Devel::StackTrace->new();
79 #print Dumper($trace);
80 #print Dumper($trace->frame(1)->args());
81
82 #print "args: ", $self->{'__caller'}->hasargs(), "\n";
83
84 #print Dumper($self);
85 #exit;
86
87
88 # argument-handling ...
89
90 # ... get them ...
91 my @args = ();
92 @_ && (@args = @_);
93
94 # ... check if we can coerce them into an array (this needs an even number of arguments)
95 my $argcount = $#args + 1;
96 my $fract = $argcount / 2;
97
98 my $seperate = pop @args if $fract != int($fract);
99
100 # mixin arguments
101 $self = { @args };
102
103 # scan for arguments prefixed by a double underscore '__'
104 foreach (keys %$self) {
105 if (/^__(.+?)$/) {
106 $self->{__bridge}->{$1} = $self->{$_};
107 delete $self->{$_};
108 }
109 }
110
111 # mixin seperate - FIXME: should this not be done after blessing?
112 $self->{__bridge}->{'arg'} = $seperate if $seperate;
113
114 # ... bless hash into object using classname
115 bless $self, $class;
116
117 # remember the caller
118 $self->{__bridge}->{caller_module} = caller;
119 #print Dumper(caller(2));
120 #exit;
121
122 $self->{__bridge}->{class_name} = $classname;
123
124 # patches for backward compatibility
125 $self->{'__arg'} = $self->{__bridge}->{'arg'} if $self->{__bridge}->{'arg'};
126 $self->{'__caller'} = $self->{__bridge}->{caller_module} if $self->{__bridge}->{caller_module};
127 $self->{'__classname'} = $self->{__bridge}->{class_name} if $self->{__bridge}->{class_name};
128
129 $self->_init() if $self->can('_init');
130 $self->constructor() if $self->can('constructor');
131
132 # trace
133 #print Dumper($self);
134 #exit;
135
136 return $self;
137 }
138
139 sub _abstract_function {
140 my $self = shift;
141 my $self_classname = ref $self;
142 my $function_name = shift;
143 # was:
144 $self->log_basic( __PACKAGE__ . ": function '$function_name' is an abstract method, please implement it in '$self_classname'.", 'warning');
145 # is:
146 #die( __PACKAGE__ . ": Function '$function_name' is an abstract method, please implement it in '$self_classname'.");
147 #exit;
148 }
149
150 sub fromPackage {
151 my $self = shift;
152 #my $self_classname = ref $self;
153 my $pkgname = shift;
154 my @args = @_;
155 # my $args = shift;
156
157 # my $caller = $self->{'__caller'};
158
159 #print Dumper($args);
160
161 $self->log_basic( __PACKAGE__ . "->fromPackage( pkgname $pkgname args @args )", 'debug');
162
163 # perl-load
164 my $evstring = "use $pkgname;";
165 eval($evstring);
166
167 # report errors
168 if ($@) {
169 # build error-messages
170 my $issuer = __PACKAGE__ . ':' . __LINE__;
171 my $errmsg_native = "Error in eval: " . $@;
172 #my $classname = $self->{__classname};
173 my $errmsg_critical = '';
174 if ($errmsg_native =~ m/Can't locate (.+?) in \@INC/) {
175 $errmsg_critical = "Could not instantiate object from package '$pkgname' ('$1' not found).";
176 } else {
177 $errmsg_critical = $errmsg_native;
178 }
179 # write error to logging-output (console|file|database)
180 $self->log_basic( $errmsg_native . " (issuer='$issuer', code='$evstring')", 'debug' );
181 $self->log_basic( $errmsg_critical, 'warning' );
182 return;
183 }
184
185 # object-creation
186 my $object = $pkgname->new(@args);
187
188 # trace
189 #print Dumper($object);
190
191 # run boot-methods on object
192 $object->_init() if $object->can('_init');
193 $object->constructor() if $object->can('constructor');
194
195 return $object;
196 }
197
198 sub log_basic {
199 my $self = shift;
200 my $message = shift;
201 my $level = shift;
202
203 #return;
204 $level ||= 'info';
205
206 my $notSoGood = ($level =~ /warning|error|critical/);
207
208 # STDERR?
209 if ($level && $notSoGood) {
210 print STDERR $level, ": ", $message, "\n";
211 }
212
213 # STDOUT?
214 if ($_dp_globals->{TRACE} || $notSoGood) {
215 print $level, ": ", $message, "\n";
216 }
217
218 # get logger instance
219 if (!$_dp_globals->{logger}) {
220 $_dp_globals->{logger} = eval { Log::Dispatch::Config->instance; };
221 }
222
223 if ($_dp_globals->{logger}) {
224 $_dp_globals->{logger}->log( level => $level, message => $message);
225 #} else {
226 #print $level, ": ", $message, "\n";
227 }
228
229 }
230
231 1;
232 __END__

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