/[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.7 - (show annotations)
Tue Feb 18 18:34:35 2003 UTC (21 years, 3 months ago) by joko
Branch: MAIN
Changes since 1.6: +40 -10 lines
+ fix: just logs if possible (sub log_basic)

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

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