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

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

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