/[cvs]/nfo/perl/libs/Data/Storage/Handler/Abstract.pm
ViewVC logotype

Diff of /nfo/perl/libs/Data/Storage/Handler/Abstract.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by joko, Thu Oct 17 00:08:07 2002 UTC revision 1.11 by joko, Mon Jan 20 16:43:18 2003 UTC
# Line 1  Line 1 
1  #################################  ##    ------------------------------------------------------------------------
2  #  ##    $Id$
3  #  $Id$  ##    ------------------------------------------------------------------------
4  #  ##    $Log$
5  #  $Log$  ##    Revision 1.11  2003/01/20 16:43:18  joko
6  #  Revision 1.2  2002/10/17 00:08:07  joko  ##    + better argument-property merging
7  #  + bugfixes regarding "deep recursion" stuff  ##    + debugging-output !!!
8  #  ##    + abstract-dummy 'sub createChildNode'
9  #  Revision 1.1  2002/10/10 03:44:07  cvsjoko  ##
10  #  + new  ##    Revision 1.10  2003/01/19 02:31:51  joko
11  #  ##    + fix to 'sub AUTOLOAD'
12  #  ##
13  #################################  ##    Revision 1.9  2002/12/19 16:30:23  joko
14    ##    + added 'sub dropDb' and 'sub rebuildDb' as croakers for concrete implementations of methods in proper handlers
15    ##
16    ##    Revision 1.8  2002/12/13 21:48:35  joko
17    ##    + sub _abstract_function
18    ##
19    ##    Revision 1.7  2002/12/05 07:57:48  joko
20    ##    + now using Tie::SecureHash as a base for the COREHANDLE
21    ##    + former public COREHANDLE becomes private _COREHANDLE now
22    ##
23    ##    Revision 1.6  2002/12/03 15:52:24  joko
24    ##    + fix/feature: if dispatching to deep core method fails (is not declared), try method at Data::Storage - level
25    ##
26    ##    Revision 1.5  2002/12/01 22:19:33  joko
27    ##    + just disconnect if COREHANDLE exists
28    ##
29    ##    Revision 1.4  2002/12/01 04:45:38  joko
30    ##    + sub eraseAll
31    ##    + sub createDb
32    ##
33    ##    Revision 1.3  2002/11/29 04:58:20  joko
34    ##    + Storage::Result now uses the same dispatching mechanism like Storage::Handler
35    ##
36    ##    Revision 1.2  2002/10/17 00:08:07  joko
37    ##    + bugfixes regarding "deep recursion" stuff
38    ##
39    ##    Revision 1.1  2002/10/10 03:44:07  cvsjoko
40    ##    + new
41    ##    ------------------------------------------------------------------------
42    
43    
44  package Data::Storage::Handler::Abstract;  package Data::Storage::Handler::Abstract;
45    
46  use strict;  use strict;
47  use warnings;  use warnings;
48    
49    use base qw( DesignPattern::Object );
50    
51    
52  use Data::Dumper;  use Data::Dumper;
53    use Tie::SecureHash;
54    #use Data::Storage::Handler;
55    use Data::Transform::Deep qw( merge );
56    
57    
58  # get logger instance  # get logger instance
59  my $logger = Log::Dispatch::Config->instance;  my $logger = Log::Dispatch::Config->instance;
# Line 32  sub new { Line 68  sub new {
68      $logger->debug( "$invocant->new( @_ )" );      $logger->debug( "$invocant->new( @_ )" );
69      #$logger->debug( __PACKAGE__ . "->" . "new()" );      #$logger->debug( __PACKAGE__ . "->" . "new()" );
70    
71      # V1 - arguments become properties automagically / normal perl mode blessing
72    =pod
73      # autovivify passed-in arguments as future object attributes into to-be-blessed hash
74      my $self = { @_ };
75      # create object from blessed hash-reference
76      bless $self, $class;
77    =cut
78    
79    #=pod
80      # V2 - maybe more convenient/secure? utilizing Damian Conway's Tie::SecureHash...
81      my $self = Tie::SecureHash->new(
82        $class,
83        # that's it:
84          'metainfo' => undef,
85          'lock_info' => undef,
86          '_COREHANDLE' => undef,
87          'meta' => undef,
88          'locator' => undef,
89          'dataStorageLayer' => undef,
90          'dbi' => undef,
91        # tries:
92          #'Data::Storage::Handler::Abstract::metainfo' => undef,
93          #'dataStorageLayer'
94          #'Data::Storage::Handler::Abstract::dataStorageLayer' => undef,
95          #'Data::Storage::Handler::Tangram::dataStorageLayer' => undef,
96          #'Data::Dumper::locator' => undef,
97          #$class . '::locator' => undef,
98          #'Data::Storage::Handler::Tangram::locator' => undef,
99          #'Data::Storage::Handler::DBI::locator' => undef,
100          #_protected => ,
101          #__private => ,
102      );
103    #=cut
104    
105      # merge passed-in arguments to constructor as properties into already blessed secure object
106    
107        # mungle arguments from array into hash - perl does the job  ;)
108        #my %args = @_;
109        #my %args = ();
110    
111    #print Dumper(@_);
112    
113        # merge attributes one-by-one
114        # TODO: deep_copy? / merge_deep?
115        while (my $elemName = shift @_) {
116          #print "elemName: $elemName", "\n";
117          if (my $elemValue = shift @_) {
118            #print Dumper($elemValue);
119            #print "elemName=$elemName, elemValue=$elemValue", "\n";
120            $self->{$elemName} = $elemValue;
121          }
122          #$self->{$_} = $args{$_};
123          #$self->{$_} = $args{$_};
124        }
125      
126      # V3 - rolling our own security (just for {COREHANDLE} - nothing else)  -  nope, Tie::SecureHash works wonderful
127      #my $self = { @_ };
128      #bless $self, $class;
129      
130      
131    
132    # handle meta data    # handle meta data
133      my $metainfo = _getMetaInfo($class);      #my $metainfo = $self->getMetaInfo($class);
134        my $metainfo = $self->getMetaInfo();
135      if (!$metainfo->{disconnectMethod}) { $metainfo->{disconnectMethod} = 'disconnect'; }      if (!$metainfo->{disconnectMethod}) { $metainfo->{disconnectMethod} = 'disconnect'; }
136      # type?      # type?
137      $invocant =~ s/Data::Storage::Handler:://;      $invocant =~ s/Data::Storage::Handler:://;
138      $metainfo->{type} = $invocant;      $metainfo->{type} = $invocant;
139    
   # create object from blessed hash-reference  
140      # direct accessible (non-protected) properties         ( was: my $self = { }; )      # direct accessible (non-protected) properties         ( was: my $self = { }; )
141      my $self = { metainfo => $metainfo, @_ };      $self->{metainfo} = $metainfo;
     bless $self, $class;  
142    
143    return $self;    return $self;
144  }  }
145    
146    
147    # TODO: use NEXT.pm inside this mechanism (to avoid repetitions...)
148  sub AUTOLOAD {  sub AUTOLOAD {
149    
150    # recursion problem to be avoided here!!!    # recursion problem to be avoided here!!!
# Line 69  sub AUTOLOAD { Line 166  sub AUTOLOAD {
166    # find out methodname    # find out methodname
167    my $methodname = $AUTOLOAD;    my $methodname = $AUTOLOAD;
168    $methodname =~ s/^.*:://;    $methodname =~ s/^.*:://;
169      
170    #print "method: $methodname", "\n";
171      
172      # TODO: document this! handler-private methods listed here will not be triggered (internal use)
173      # in this case, "exists" is a method reserved for Tie::SecureHash,
174      # which encapsulates the perl data structure (HASH) under this object
175      # this is to prevent deep recursion's
176      return if lc $methodname eq 'exists';
177    
178    print "$methodname - 1", "\n";
179    
180      # TODO: enhance logging/debugging
181      #if (!$self->exists('COREHANDLE')) { return; }
182    
183    # handle locking (hack)    # handle locking (hack)
184    if ($self->{lock_info}->{last_method} && $methodname eq $self->{lock_info}->{last_method}) {    if ($self->can('exists') && $self->exists('lock_info') && $self->{lock_info}->{last_method} && $methodname eq $self->{lock_info}->{last_method}) {
185      $self->{lock_info}->{log_lock} = 1;      $self->{lock_info}->{log_lock} = 1;
186    } else {    } else {
187      $self->{lock_info}->{log_lock} = 0;      $self->{lock_info}->{log_lock} = 0;
188    }    }
189    $self->{lock_info}->{last_method} = $methodname;    $self->{lock_info}->{last_method} = $methodname;
190        
191    print "$methodname - 2", "\n";
192    
193    #print Dumper($self);
194    #exit;
195    
196      # get corehandle instance from underlying handler
197      my $core = $self->getCOREHANDLE();
198    
199    # test for COREHANDLE    # test for COREHANDLE
200    if (!$self->{COREHANDLE}) {    #if (!$self->{_COREHANDLE}) {
201      #print "no COREHANDLE", "\n";  #=pod
202      if (!$self->{lock_info}->{log_lock}) {    #if (!$self->exists('_COREHANDLE')) {
203        $logger->error( __PACKAGE__ . "[$self->{metainfo}->{type}]" . ": " . "COREHANDLE is undefined while trying to execute method \"$methodname\"" );    #if (!$self->{_COREHANDLE}) {
204      if (!$core) {
205    
206    #print Dumper($self);    
207    #exit;
208    
209        my $handlertype = $self->{metainfo}->{type};
210        $handlertype ||= '';
211    
212        my $err_msg_core = __PACKAGE__ . "[$handlertype]" . ": " . "COREHANDLE is undefined while trying to execute method \"$methodname\"";
213    print $err_msg_core, "\n";
214        if ($self->exists('lock_info') && !$self->{lock_info}->{log_lock}) {
215          $logger->error( $err_msg_core );
216      }      }
217      return;      return;
218    }    }
219    #=cut
220    
221    #print "$methodname - 3", "\n";
222    
223    # try to dispatch method-call to Storage::Handler::*    # try to dispatch method-call to Storage::Handler::*
224    #if ($self->can($methodname)) {    #if ($self->can($methodname)) {
# Line 94  sub AUTOLOAD { Line 227  sub AUTOLOAD {
227      #if ($res) { return $res; }      #if ($res) { return $res; }
228    #}    #}
229    
230    #print "$methodname - 4", "\n";
231    
232    # try to dispatch method-call to COREHANDLE    # try to dispatch method-call to COREHANDLE
233    if ($self->{COREHANDLE}->can($methodname) || $self->{COREHANDLE}->can("AUTOLOAD")) {    # was:
234      #my $core = $self->{_COREHANDLE};
235      # is:
236      #my $core = $self->getCOREHANDLE();
237    
238    #print Dumper($core);
239    #exit;
240    
241      # was:
242      #if ($self->{_COREHANDLE}->can($methodname) || $self->{_COREHANDLE}->can("AUTOLOAD")) {
243      # is:
244      if ($core->can($methodname) || $core->can("AUTOLOAD")) {
245      #$logger->debug( __PACKAGE__ . "->" . $methodname . " (AUTOLOAD)" );      #$logger->debug( __PACKAGE__ . "->" . $methodname . " (AUTOLOAD)" );
246      #$lock_AUTOLOAD = 1 if ($methodname eq 'insert');      #$lock_AUTOLOAD = 1 if ($methodname eq 'insert');
247      if (!$self->{lock_info}->{log_lock}) {      if (!$self->{lock_info}->{log_lock}) {
# Line 106  sub AUTOLOAD { Line 252  sub AUTOLOAD {
252      }      }
253      #$lock_AUTOLOAD = 0;      #$lock_AUTOLOAD = 0;
254      #$logger->log( level => 'debug', message => __PACKAGE__ . "->" . $methodname . " (AUTOLOAD)" );      #$logger->log( level => 'debug', message => __PACKAGE__ . "->" . $methodname . " (AUTOLOAD)" );
255      return $self->{COREHANDLE}->$methodname(@_);      
256    #print "calling: $methodname", "\n";
257        
258        # method calls making it until here will get dispatched to the proper handler
259        return $core->$methodname(@_);
260      
261      } elsif ($self->can($methodname)) {
262        # try to call specified method inside our or inherited module(s) scope(s)
263        return $self->$methodname(@_);
264    }    }
265    
266  }  }
267    
268  sub DESTROY {  sub DESTROY {
269    my $self = shift;    my $self = shift;
270    if ($self->{COREHANDLE}) {    #if ($self->{COREHANDLE}) {
271      if ($self->exists('_COREHANDLE')) {
272      $logger->debug( __PACKAGE__ . "[$self->{metainfo}->{type}]" . "->DESTROY" );      $logger->debug( __PACKAGE__ . "[$self->{metainfo}->{type}]" . "->DESTROY" );
273    
274      my $disconnectMethod = $self->{metainfo}->{disconnectMethod};      my $disconnectMethod = $self->{metainfo}->{disconnectMethod};
275    
276      # call "disconnect" or alike on COREHANDLE      # call "disconnect" or alike on COREHANDLE
277      # was: $self->{COREHANDLE}->disconnect();      # was: $self->{COREHANDLE}->disconnect();
278      $disconnectMethod && ( $self->{COREHANDLE}->$disconnectMethod() );      $disconnectMethod && $self->{_COREHANDLE} && ( $self->{_COREHANDLE}->$disconnectMethod() );
279    
280      undef $self->{COREHANDLE};      undef $self->{_COREHANDLE};
281    }    }
282  }  }
283    
284    sub _typeCheck2 {
 sub _abstract_function {  
   my $self = shift;  
   my $fName = shift;  
   my $class = ref($self);  
   $logger->error( __PACKAGE__ . ": function \"$fName\" is an abstract method, please implement it in \"$class\"");  
   #exit;  
 }  
   
 sub _typeCheck {  
285    my $type = shift;    my $type = shift;
286    print "type: $type";    print "type: $type";
287    eval("use Data::Storage::$type;");    eval("use Data::Storage::$type;");
288  }  }
289    
 sub _getMetaInfo {  
   my $packagename = shift;  
   #return $self->$metainfo;  
   
   my $ns = '$' . $packagename . "::metainfo";  
   $logger->debug( __PACKAGE__ . "->" . "_getMetaInfo()" . "   " . "[$ns]" );  
   return eval($ns);  
 }  
   
290    
291  # ====================================================  # ====================================================
292  #   PUBLIC METHODS  #   PUBLIC METHODS
293  # ====================================================  # ====================================================
294    
295    # TODO: abstract "abstract methods" to list/hash to be used in AUTOLOAD    sub existsChildNode {
   # e.g.: my @ABSTRACT_METHODS = (qw( connect sendCommand getChildNodes ));  
   
   sub connect {  
       
296      my $self = shift;      my $self = shift;
297      $self->_abstract_function('connect');      my $nodename = shift;
298      return;      #$nodename = 'TransactionRoutingTable';
299            $logger->debug( __PACKAGE__ . "->existsChildNode( nodename $nodename )" );
300      $logger->debug( "\"connect\" has to be implemented by handler!" );      $self->getChildNodes() unless $self->{meta}->{childnodes};
301      return;      my $result = grep(m/$nodename/i, @{$self->{meta}->{childnodes}});     # TODO: use "/i" only on win32-systems!
302        return $result;
303      }
304    
305      sub connect_tmp {
306            
307  #    my $self = shift;  #    my $self = shift;
308  #    my $connectionString = shift;  #    my $connectionString = shift;
# Line 174  sub _getMetaInfo { Line 311  sub _getMetaInfo {
311    
312    }    }
313        
314    
315    # ====================================================
316    #   CONCRETE METHOD DUMMIES (croaking via "$logger" by calling "_abstract_function")
317    # ====================================================
318    
319      # TODO:
320      #   - abstract "abstract methods" to list/hash to be used in AUTOLOAD
321      #      e.g.: my @ABSTRACT_METHODS = (qw( connect sendCommand getChildNodes ));
322      #      use Class::XYZ (Construct)
323      #   - build them via anonymous subs
324      #   - introduce them via symbols
325    
326      sub getCOREHANDLE {
327        my $self = shift;
328        $self->_abstract_function('getCOREHANDLE');
329      }
330    
331    sub sendCommand {    sub sendCommand {
332      my $self = shift;      my $self = shift;
333      $self->_abstract_function('sendCommand');      $self->_abstract_function('sendCommand');
334    }    }
335    
336      sub createChildNode {
337        my $self = shift;
338        $self->_abstract_function('createChildNode');
339      }
340    
341      sub existsChildNode_tmp {
342        my $self = shift;
343        $self->_abstract_function('existsChildNode');
344      }
345    
346    sub getChildNodes {    sub getChildNodes {
347      my $self = shift;      my $self = shift;
348      $self->_abstract_function('getChildNodes');      $self->_abstract_function('getChildNodes');
# Line 189  sub _getMetaInfo { Line 353  sub _getMetaInfo {
353      $self->_abstract_function('configureCOREHANDLE');      $self->_abstract_function('configureCOREHANDLE');
354    }    }
355    
 1;  
356      sub getMetaInfo {
357        my $self = shift;
358        $self->_abstract_function('getMetaInfo');
359        return;
360      }
361    
362      sub getListUnfiltered {
363        my $self = shift;
364        $self->_abstract_function('getListUnfiltered');
365        return;
366      }
367    
368      sub getListFiltered {
369        my $self = shift;
370        $self->_abstract_function('getListFiltered');
371        return;
372      }
373    
374      sub sendQuery {
375        my $self = shift;
376        $self->_abstract_function('sendQuery');
377        return;
378      }
379    
380      sub connect {
381        my $self = shift;
382        $self->_abstract_function('connect');
383        return;
384      }
385    
386      sub testIntegrity {
387        my $self = shift;
388        $self->_abstract_function('testIntegrity');
389        return;
390      }
391    
392      sub quoteSql {
393        my $self = shift;
394        $self->_abstract_function('quoteSql');
395        return;
396      }
397    
398      sub eraseAll {
399        my $self = shift;
400        $self->_abstract_function('eraseAll');
401        return;
402      }
403    
404      sub createDb {
405        my $self = shift;
406        $self->_abstract_function('createDb');
407        return;
408      }
409    
410      sub dropDb {
411        my $self = shift;
412        $self->_abstract_function('dropDb');
413        return;
414      }
415    
416      sub rebuildDb {
417        my $self = shift;
418        $self->_abstract_function('rebuildDb');
419        return;
420      }
421    
422    1;

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.11

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