/[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.8 - (show annotations)
Wed Feb 19 00:36:59 2003 UTC (21 years, 3 months ago) by joko
Branch: MAIN
Changes since 1.7: +11 -4 lines
+ bugfix: this {logger} is the instance itself, so has to be fed with ( level => xyz and namespace => xyz )
+ minor modifications in behaviour

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

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