1 package CXGN
::Class
::Exporter
;
5 # VERBOSE: Developer Variable, default quiet
6 # 0: non-verbose, no developer messages
7 # 1: print messages on DBH exchange
8 # 2: print messages on any import() call
11 # require CXGN::Class::Exporter;
12 # $CXGN::Class::Exporter::VERBOSE = 2;
17 #Uses the default exporter, want to allow subclasses to use
18 #our importer for DBH-exchange capability
28 #We can have this do nothing to kill the dprint messages
29 #Need to make sure DBH exchanging actually works
30 return unless $VERBOSE;
33 print STDERR
"# " . $msg . "\n";
42 Use this as a base class to get a standard CXGN import() function on your class,
43 which does a few cool things:
44 1) Implements its own light-weight EXPORT/EXPORT_OK routine
45 2) Can take one hash ref as a set of class routines to execute, with scalar/ref argument.
46 If sub doesn't exist, will just set package scalar in the importing module
47 3) Handles exchange of global database handles between modules
50 use CXGN::DB::Connection qw/export this and that/ { verbose => 0 }
51 #equivalent to CXGN::DB::Connection->verbose(0);
56 use base qw/CXGN::Class::Exporter/;
59 our @EXPORT_OK = qw/works like Exporter/;
60 our @EXPORT = qw/ditto/;
65 our $EXCHANGE_DBH = 1; #pushes or pulls global $DBH to anything that uses this module
66 #our $IMPORT_DBH = 1; would only pull a $DBH from the using script/module
67 #our $EXPORT_DBH = 1; would only push a $DBH to the using script/module
82 use Foo qw/works/, { baz => 1 };
84 print "YaHoo!" if defined(&works) && defined(&ditto);
89 Setting the package variable IMPORT_DBH to 'true' within a class will
90 attempt DBH-importing. This means that if $DBH is defined within the
91 calling script/class, then it will be grabbed and set as a the DBH
92 package variable within the importer.
94 This is part of an effort to minimize connections to the database.
95 The idea is that all classes that need database access should use
96 global database handles, which can be grabbed from other classes.
98 If fresh handles are needed, they could always be created at-will.
111 dprint
"$class importer called by $pkg with args: " . join(", ", @args) . "\n" if $VERBOSE > 1;
112 my @expok = grep { !ref && /^[\$\@\%\*&]?\w+$/ } @args;
113 CXGN
::Class
::Exporter
->export($class, $pkg, @expok);
115 my @refs = grep { ref eq "HASH" } @args;
117 die "Error: $pkg sent multiple hash ref import-arguments to $class\n";
121 while(my($k,$v) = each %$args){
122 if(defined(&{$class."::".$k})){
126 ${$class."::$k"} = $v;
130 CXGN
::Class
::Exporter
->resolve_DBH_exchange($class, $pkg);
135 my ($source, $target, @ok) = @_;
136 foreach my $export (@
{$source.'::EXPORT'}){
137 $this->export_variable($source, $target, $export);
140 $export_ok{$_} = 1 foreach(@
{$source.'::EXPORT_OK'});
141 foreach my $ok (@ok){
142 die "Package $source does not list '$ok' within EXPORT_OK\n" unless $export_ok{$ok};
143 $this->export_variable($source, $target, $ok);
147 sub export_variable
{
149 my ($source, $target, $var) = @_;
150 my ($type) = $var =~ /^([\$\@\%&\*])/;
152 $var =~ s/\Q$type\E//;
153 ${$target.'::'.$var} = ${$source.'::'.$var} if $type eq '$';
154 @
{$target.'::'.$var} = @
{$source.'::'.$var} if $type eq '@';
155 %{$target.'::'.$var} = %{$source.'::'.$var} if $type eq '%';
156 *{$target.'::'.$var} = *{$source.'::'.$var} if $type eq '*';
157 *{$target.'::'.$var} = \
&{$source.'::'.$var} if $type eq '&';
160 warn "Method \&${source}::$var() does not exist\n" unless defined(&{"${source}::$var"});
161 *{$target.'::'.$var} = \
&{$source.'::'.$var};
165 sub resolve_DBH_exchange
{
170 my $lldbh = sub { $this->looks_like_DBH(@_) };
172 if( ${$class."::IMPORT_DBH"} && $lldbh->(${$pkg."::DBH"}) && !$lldbh->(${$class."::DBH"}) ){
173 dprint
"$class is pulling its DBH from $pkg\n";
174 $this->send_DBH($pkg, $class); #Pull the DBH from $pkg
177 elsif ( ${$class."::EXPORT_DBH"}
178 && $lldbh->(${$class."::DBH"})
179 && !$lldbh->(${$pkg."::DBH"})
181 dprint
"$class is pushing its DBH to $pkg\n";
182 $this->send_DBH($class, $pkg); #push DBH to $pkg
184 elsif (${$class."::EXCHANGE_DBH"} && ${$pkg."::EXCHANGE_DBH"}){
186 $lldbh->(${$class."::DBH"})
187 && !$lldbh->(${$pkg."::DBH"})
189 dprint
"$class exchanging (push) its DBH with $pkg\n";
190 $this->send_DBH($class, $pkg);
193 $lldbh->(${$pkg."::DBH"})
194 && !$lldbh->(${$class."::DBH"})
196 dprint
"$class exchanging (pull) its DBH with $pkg\n";
197 $this->send_DBH($pkg, $class);
206 my $DBH = ${$source."::DBH"};
207 return unless defined $DBH;
208 return unless $this->looks_like_DBH($DBH);
209 if(defined(&{$dest."::DBH"})){
213 ${$dest."::DBH"} = $DBH;
220 $DBH = $this if (ref($this) && !$DBH); #used :: (or exported) form of sub
221 return 0 unless defined($DBH);
222 return 0 unless ref($DBH);
225 $DBH->can("anything");
228 foreach(qw
/disconnect prepare commit quote do selectall_hashref ping tables/){
229 return 0 unless defined &{ref($DBH).'::'.$_};
234 *looks_like_dbh
= \
&looks_like_DBH
;