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

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

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