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

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.13

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