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

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

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