--- nfo/perl/libs/DesignPattern/Object.pm 2002/12/27 16:05:42 1.2 +++ nfo/perl/libs/DesignPattern/Object.pm 2003/02/11 11:04:27 1.6 @@ -1,14 +1,26 @@ -## -------------------------------------------------------------------------------- -## $Id: Object.pm,v 1.2 2002/12/27 16:05:42 joko Exp $ -## -------------------------------------------------------------------------------- +## --------------------------------------------------------------------------- +## $Id: Object.pm,v 1.6 2003/02/11 11:04:27 joko Exp $ +## --------------------------------------------------------------------------- ## $Log: Object.pm,v $ +## Revision 1.6 2003/02/11 11:04:27 joko +## + metadata (args, caller, etc.) are now stored inside {__bridge} +## +## Revision 1.5 2003/02/09 16:24:46 joko +## + pseudo constructor mechanism by calling method 'constructor' on object instantiation +## +## Revision 1.4 2003/01/22 17:56:49 root +## + fix: just use the logger if it's available +## +## Revision 1.3 2003/01/20 16:54:22 joko +## + sub fromPackage: refactored from libp's 'getNewPerlObjFromPkgName' or s.th.l.th. +## ## Revision 1.2 2002/12/27 16:05:42 joko ## + played with Devel::CallerItem and Devel::StackTrace ## ## Revision 1.1 2002/12/13 21:46:29 joko ## + initial check-in ## -## -------------------------------------------------------------------------------- +## --------------------------------------------------------------------------- package DesignPattern::Object; @@ -21,6 +33,10 @@ #use Devel::CallerItem; #use Devel::StackTrace; + +# get logger instance +my $logger = eval { Log::Dispatch::Config->instance; }; + sub new { # the classname in most cases @@ -29,6 +45,8 @@ # use already blessed reference, if passed in - else use the very classname my $class = ref ($classname) || $classname; + $logger->debug( "$classname->new( ... )" . "\t[via " . __PACKAGE__ . "]" ) if $logger; + # the base for our object - a plain perl hash, which .... my $self = {}; # note: @@ -44,10 +62,6 @@ # ... or would this give us (harmful) circular module dependencies??? #$logger->debug( __PACKAGE__ . "->new( @args )" ); # this is not "common"! - # remember the caller - $self->{'__caller'} = caller; - #print Dumper(caller(2)); - #exit; # remember the stacktrace: abstract this out (DesignPattern::Object::Trace) or parametrize! #my $trace = Devel::StackTrace->new(); @@ -59,6 +73,7 @@ #print Dumper($self); #exit; + # argument-handling ... # ... get them ... @@ -74,12 +89,39 @@ # mixin arguments $self = { @args }; - # mixin seperate - $self->{'__arg'} = $seperate if $seperate; + # scan for arguments prefixed by a double underscore '__' + foreach (keys %$self) { + if (/^__(.+?)$/) { + $self->{__bridge}->{$1} = $self->{$_}; + delete $self->{$_}; + } + } + + # mixin seperate - FIXME: should this not be done after blessing? + $self->{__bridge}->{'arg'} = $seperate if $seperate; # ... bless hash into object using classname bless $self, $class; + + # remember the caller + $self->{__bridge}->{caller_module} = caller; + #print Dumper(caller(2)); + #exit; + + $self->{__bridge}->{class_name} = $classname; + + # patches for backward compatibility + $self->{'__arg'} = $self->{__bridge}->{'arg'} if $self->{__bridge}->{'arg'}; + $self->{'__caller'} = $self->{__bridge}->{caller_module} if $self->{__bridge}->{caller_module}; + $self->{'__classname'} = $self->{__bridge}->{class_name} if $self->{__bridge}->{class_name}; + $self->_init() if $self->can('_init'); + $self->constructor() if $self->can('constructor'); + + # trace + #print Dumper($self); + #exit; + return $self; } @@ -88,10 +130,54 @@ my $self_classname = ref $self; my $function_name = shift; # was: - # $logger->error( __PACKAGE__ . ": function \"$fName\" is an abstract method, please implement it in \"$class\""); + $logger->warning( __PACKAGE__ . ": function '$function_name' is an abstract method, please implement it in '$self_classname'."); # is: - die( __PACKAGE__ . ": Function '$function_name' is an abstract method, please implement it in '$self_classname'."); + #die( __PACKAGE__ . ": Function '$function_name' is an abstract method, please implement it in '$self_classname'."); #exit; } +sub fromPackage { + my $self = shift; + #my $self_classname = ref $self; + my $pkgname = shift; + my @args = @_; +# my $args = shift; + +# my $caller = $self->{'__caller'}; + +#print Dumper($args); + + $logger->debug( __PACKAGE__ . "->fromPackage( pkgname $pkgname args @args )" ); + + # perl-load + my $evstring = "use $pkgname;"; + eval($evstring); + + # report errors + if ($@) { + # build error-messages + my $errmsg_native = __PACKAGE__ . ':' . __LINE__ . " Error in eval \"$evstring\": " . $@; + #my $classname = $self->{__classname}; + my $errmsg_critical = ''; + if ($errmsg_native =~ m/Can't locate (.+?) in \@INC/) { + $errmsg_critical = "Could not instantiate object from package '$pkgname' - location of '$1' failed."; + } else { + $errmsg_critical = $errmsg_native; + } + # write error to logging-output (console|file|database) + $logger->debug( $errmsg_native ); + $logger->critical( $errmsg_critical ); + return; + } + + # object-creation + my $object = $pkgname->new(@args); + + # run boot-methods on object + $object->_init() if $object->can('_init'); + $object->constructor() if $object->can('constructor'); + + return $object; +} + 1;