File Coverage

DataFax/StudySubs.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package DataFax::StudySubs;
2              
3 1     1   38655 use strict;
  1         2  
  1         448  
4 1     1   7 use vars qw(@ISA $VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS);
  1         2  
  1         304  
5 1     1   7 use Carp;
  1         7  
  1         94  
6 1     1   3187 use IO::File;
  1         14849  
  1         125  
7 1     1   1584 use Net::Rexec 'rexec';
  0            
  0            
8              
9             $VERSION = 0.10;
10             use DataFax;
11             @ISA = qw(Exporter DataFax);
12             @EXPORT = qw(dfparam disp_param debug_level echo_msg get_dfparam);
13             @EXPORT_OK = qw(dfparam disp_param debug_level echo_msg get_dfparam
14             exec_cmd
15             );
16             %EXPORT_TAGS= (
17             all =>[@EXPORT_OK],
18             echo_msg=>[qw(dfparam disp_param debug_level echo_msg get_dfparam)],
19             param =>[qw(dfparam disp_param get_dfparam)],
20             cmd =>[qw(exec_cmd)],
21             );
22              
23             =head1 NAME
24              
25             DataFax::StudySubs - DataFax common sub routines
26              
27             =head1 SYNOPSIS
28              
29             use DataFax::StudySubs qw(:all);
30              
31             =head1 DESCRIPTION
32              
33             This class contains the common sub-routines used in DataFax.
34              
35             =cut
36              
37             sub new {
38             my ($s, %args) = @_;
39             return $s->SUPER::new(%args);
40             }
41              
42             # ---------------------------------------------------------------------
43              
44             =head1 Export Tag: all
45              
46             The :all tag includes the all the methods in this module.
47              
48             use DataFax::StudySubs qw(:all);
49              
50             It includes the following sub-routines:
51              
52             =head2 dfparam($var, $ar[,$val])
53              
54             Input variables:
55              
56             $var - variable name
57             $ar - parameter hash or array ref
58             $val - value to be added or assigned
59              
60             Variables used or routines called:
61              
62             None
63              
64             How to use:
65              
66             use DataFax::DFstudyDB qw(dfparam);
67             my $ar = {a=>1,b=>25};
68             my $br = [1,2,5,10];
69             # for hash ref
70             my $va = $self->dfparam('a',$ar); # set $va = 1
71             my $v1 = $self->dfparam('v1',$ar); # set $v1 = ""
72             my $v2 = $self->dfparam('b',$ar); # set $v2 = 25
73             # for array ref
74             my $v3 = $self->dfparam(0,$br); # set $v3 = 1
75             my $v4 = $self->dfparam(3,$br); # set $v4 = 10
76             # add or assign values and return array ref
77             $self->dfparam('c',$ar,30); # set $ar->{c} = 30
78             $self->dfparam(5,$br,50); # set $br->[5] = 50
79              
80             Return: $r - the value in the hash or empty string or array ref.
81              
82             This method gets and sets the $var in $ar. If the varirable
83             does not exists in $ar, it tries in $self as well for 'get'.
84              
85             =cut
86              
87             sub dfparam {
88             my ($s, $v, $r) = @_;
89             if ($#_>2) { # there is a third input
90             $r->[$v] = $_[3] if $v =~ /^\d+$/ && ref($r) =~ /ARRAY/;
91             $r->{$v} = $_[3] if ref($r) =~ /HASH/ || ref $r;
92             return ;
93             }
94             # if only variable name and the name exists in the class object
95             return $s->{$v} if $#_==1 && exists $s->{$v};
96             # return blank if no $v or $r is not array, hash nor object
97             return "" if $v =~ /^\s*$/;
98             return $s->{$v} if exists $s->{$v} && !$r;
99             return "" if ! ref($r);
100             return "" if $v !~ /^\d+$/ && ref($r) =~ /ARRAY/;
101              
102             return (exists $r->[$v])?$r->[$v]:"" if ref($r) =~ /^ARRAY/;
103             # if $r = $s, then ref $r will make it sure to catch that as well
104             return (exists $r->{$v})?$r->{$v}:((exists $s->{$v})?$s->{$v}:"")
105             if ref($r) =~ /^HASH/ || ref $r;
106             return ""; # catch all
107             }
108              
109             =head2 get_dfparam($vs, $ar)
110              
111             Input variables:
112              
113             $vs - a list of variable names separated by comma
114             $ar - parameter hash or array ref
115              
116             Variables used or routines called:
117              
118             dfparam - get individual parameter
119              
120             How to use:
121              
122             use DataFax::DFstudyDB qw(:all);
123             my $ar = {a=>1,b=>25};
124             my ($va, $vb) = $self->get_dfparam('a,b',$ar);
125              
126             Return: array or array ref
127              
128             This method gets multiple values for listed variables.
129              
130             =cut
131              
132             sub get_dfparam {
133             my $s = shift;
134             my ($vs, $r) = @_;
135             return () if ! $vs;
136             my $p = [];
137             $vs =~ s/\s+//g; # remove any spaces
138             foreach my $k (split /,/, $vs) {
139             push @$p, $s->dfparam($k, $r);
140             }
141             return wantarray ? @$p : $p;
142             }
143              
144             =head2 exec_cmd ($cmd, $pr)
145              
146             Input variables:
147              
148             $cmd - a full unix command with paraemters and arguments
149             $pr - parameter hash ref
150             datafax_host - DataFax host name or ip address
151             local_host - local host name or ip address
152             datafax_usr - DataFax user name
153             datafax_pwd - DataFax user password
154              
155             Variables used or routines called:
156              
157             get_dfparam - get values for multiple parameters
158              
159             How to use:
160              
161             use DataFax::DFstudyDB qw(:all);
162             # Case 1: hosts are different and without id and password
163             my $cmd = "cat /my/dir/file.txt";
164             my $pr = {datafax_host=>'dfsvr',local_host='svr2'};
165             my @a = $self->exec_cmd($cmd,$pr); # uses rsh to run the cmd
166              
167             # Case 2: different hosts with id and password
168             my $pr = {datafax_host=>'dfsvr',local_host='svr2',
169             datafax_usr=>'fusr', datafax_pwd=>'pwd' };
170             my @a = $self->exec_cmd($cmd,$pr); # uses rexec
171              
172             # Case 2: hosts are the same
173             my $pr = {datafax_host=>'dfsvr',local_host='dfsvr'};
174             my $ar = $self->exec_cmd('/my/file.txt',$pr); # case 2:
175              
176             Return: array or array ref
177              
178             This method opens a file or runs a command and return the contents
179             in array or array ref.
180              
181             =cut
182              
183             sub exec_cmd {
184             my $s = shift;
185             my ($cmd, $pr) = @_;
186             my $vs='datafax_host,local_host,datafax_usr,datafax_pwd';
187             my ($dfh,$lsv,$usr,$pwd) = $s->get_dfparam($vs,$pr);
188             $lsv = `hostname` if ! $lsv;
189             my ($rc, @a);
190             if ($dfh ne $lsv) {
191             # croak "ERR: no user name for remote access.\n" if ! $usr;
192             # croak "ERR: no password for user $usr.\n" if ! $pwd;
193             if ($usr && $pwd) { # use rexec
194             $s->echo_msg(" CMD: $cmd at $dfh for user $usr...", 1);
195             ($rc, @a) = rexec($dfh, $cmd, $usr, $pwd);
196             $rc == 0 || carp " WARN: could not run $cmd on $dfh.\n";
197             } else { # use rsh
198             my $u = "rsh $dfh $cmd |";
199             my $fh = new IO::File;
200             $fh->open("$u")||carp " WARN: could not run $u: $!.\n";
201             @a=<$fh>; close($fh);
202             }
203             } else { # use perl module
204             $s->echo_msg(" CMD: $cmd at $lsv...", 1);
205             my $fh = new IO::File;
206             $fh->open("$cmd") || carp " WARN: could not run $cmd: $!.\n";
207             @a=<$fh>; close($fh);
208             }
209             return wantarray ? @a : \@a;
210             }
211              
212             =head2 debug_level($n)
213              
214             Input variables:
215              
216             $n - a number between 0 and 100. It specifies the
217             level of messages that you would like to
218             display. The higher the number, the more
219             detailed messages that you will get.
220              
221             Variables used or routines called: None.
222              
223             How to use:
224              
225             $self->debug_level(2); # set the message level to 2
226             print $self->debug_level; # print current message level
227              
228             Return: the debug level or set the debug level.
229              
230             =cut
231              
232             sub debug_level {
233             # my ($c_pkg,$c_fn,$c_ln) = caller;
234             # my $s = ref($_[0])?shift:(bless {}, $c_pkg);
235             my $s = shift;
236             croak "ERR: Too many args to debug." if @_ > 1;
237             @_ ? ($s->{_debug_level}=shift) : return $s->{_debug_level};
238             }
239              
240             =head2 echo_msg($msg, $lvl, $fh)
241              
242             Input variables:
243              
244             $msg - the message to be displayed. No newline
245             is needed in the end of the message. It
246             will add the newline code at the end of
247             the message.
248             $lvl - the message level is assigned to the message.
249             If it is higher than the debug level, then
250             the message will not be displayed.
251             $fh - file handler, or set the file hanlder in this parameter
252             $ENV{FH_DEBUG_LOG}
253              
254             Variables used or routines called:
255              
256             debug_level - get debug level.
257              
258             How to use:
259              
260             # default msg level to 0
261             $self->echo_msg('This is a test");
262             # set the msg level to 2
263             $self->echo_msg('This is a test", 2);
264              
265             Return: None.
266              
267             This method will display message or a hash array based on I
268             level. If I is set to '0', no message or array will be
269             displayed. If I is set to '2', it will only display the message
270             level ($lvl) is less than or equal to '2'. If you call this
271             method without providing a message level, the message level ($lvl) is
272             default to '0'. Of course, if no message is provided to the method,
273             it will be quietly returned.
274              
275             This is how you can call I:
276              
277             my $df = DataFax->new;
278             $df->echo_msg("This is a test"); # default the msg to level 0
279             $df->echo_msg("This is a test",1); # assign the msg as level 1 msg
280             $df->echo_msg("Test again",2); # assign the msg as level 2 msg
281             $df->echo_msg($hrf,1); # assign $hrf as level 1 msg
282             $df->echo_msg($hrf,2); # assign $hrf as level 2 msg
283              
284             If I is set to '1', all the messages with default message level,
285             i.e., 0, and '1' will be displayed. The higher level messages
286             will not be displayed.
287              
288             This method displays or writes the message based on debug level.
289             The filehandler is provided through $fh or $ENV{FH_DEBUG_LOG}, and
290             the outputs are written to the file.
291              
292             =cut
293              
294             sub echo_msg {
295             # my ($c_pkg,$c_fn,$c_ln) = caller;
296             # my $self = ref($_[0])?shift:(bless {},$c_pkg);
297             my $self = shift;
298             my ($msg,$lvl, $fh) = @_;
299             $fh = (exists $ENV{FH_DEBUG_LOG})?$ENV{FH_DEBUG_LOG}:"";
300             $fh = "" if !$fh || ($fh && ref($fh) !~ /(IO::File|GLOB)/);
301             if (!defined($msg)) { return; } # return if no msg
302             if (!defined($lvl)) { $lvl = 0; } # default level to 0
303             my $class = ref($self)||$self; # get class name
304             my $dbg = $self->debug_level; # get debug level
305             if (!$dbg) { return; } # return if not debug
306             my $ref = ref($msg);
307             if ($ref eq $class || $ref =~ /(ARRAY|HASH)/) {
308             if ($lvl <= $dbg) { $self->disp_param($msg); }
309             } else {
310             $msg = "

$msg

" if exists $ENV{QUERY_STRING} &&
311             $msg =~ /^\s*\d+\.\s+\w+/;
312             $msg =~ s/\/(\w+)\@/\/****\@/g if $msg =~ /(\w+)\/(\w+)\@(\w+)/;
313             $msg = "$msg\n";
314             $msg =~ s/\n/
\n/gm if exists $ENV{QUERY_STRING};
315             if ($lvl <= $dbg) {
316             if ($fh) { print $fh $msg; } else { print $msg; }
317             }
318             }
319             }
320              
321             =head2 disp_param($arf,$lzp, $fh)
322              
323             Input variables:
324              
325             $arf - array reference
326             $lzp - number of blank space indented in left
327             $fh - file handler
328              
329             Variables used or routines called:
330              
331             echo_msg - print debug messages
332             debug_level - set debug level
333             disp_param - recusively called
334              
335             How to use:
336              
337             use DataFax::StudySubs qw(:echo_msg);
338             my $self= bless {}, "main";
339             $self->disp_param($arf);
340              
341             Return: Display the content of the array.
342              
343             This method recursively displays the contents of an array. If a
344             filehandler is provided through $fh or $ENV{FH_DEBUG_LOG}, the outputs
345             are written to the file.
346              
347             =cut
348              
349             sub disp_param {
350             my ($self, $hrf, $lzp, $fh) = @_;
351             my $otp = ref $hrf;
352             $self->echo_msg(" - displaying parameters in $otp...");
353             $fh = (exists $ENV{FH_DEBUG_LOG})?$ENV{FH_DEBUG_LOG}:"";
354             $fh = "" if !$fh || ($fh && ref($fh) !~ /(IO::File|GLOB)/);
355             if (!$lzp) { $lzp = 15; } else { $lzp +=4; }
356             my $fmt;
357             if (exists $ENV{QUERY_STRING}) {
358             # $fmt = "%${lzp}s = %-30s
\n";
359             $fmt = (" " x $lzp) . "%s = %-30s
\n";
360             } else {
361             $fmt = "%${lzp}s = %-30s\n";
362             }
363             if (!$hrf) {
364             print "Please specify an array ref.\n";
365             return;
366             }
367             # print join "|", $self, "HRF", $hrf, ref($hrf), "\n";
368             my ($v);
369             if (ref($hrf) eq 'HASH'|| $hrf =~ /.*=HASH/) {
370             foreach my $k (sort keys %{$hrf}) {
371             if (!defined(${$hrf}{$k})) { $v = "";
372             } else { $v = ${$hrf}{$k}; }
373             if ($v =~ /([-\w_]+)\/(\w+)\@(\w+)/) {
374             $v =~ s{(\w+)/(\w+)\@}{$1/\*\*\*\@}g;
375             }
376             chomp $v;
377             if ($fh) { printf $fh $fmt, $k, $v;
378             } else { printf $fmt, $k, $v; }
379             if (ref($v) =~ /^(HASH|ARRAY)$/ ||
380             $v =~ /.*=(HASH|ARRAY)/) {
381             my $db1 = $self->debug_level;
382             $self->debug_level(0);
383             # print "$k = ${$hrf}{$k}: @{${$hrf}{$k}}\n";
384             $self->disp_param(${$hrf}{$k},$lzp);
385             $self->debug_level($db1);
386             if ($fh) { print $fh "\n"; } else { print "\n"; }
387             }
388             }
389             } elsif (ref($hrf) eq 'ARRAY' || $hrf =~ /.*=ARRAY/) {
390             foreach my $i (0..$#{$hrf}) {
391             if (!defined(${$hrf}[$i])) { $v = "";
392             } else { $v = ${$hrf}[$i]; }
393             if ($v =~ /([-\w_]+)\/(\w+)\@(\w+)/) {
394             $v =~ s{(\w+)/(\w+)\@}{$1/\*\*\*\@}g;
395             }
396             chomp $v;
397             if ($fh) { printf $fh $fmt, $i, $v;
398             } else { printf $fmt, $i, $v; }
399             if (ref($v) =~ /^(HASH|ARRAY)$/ ||
400             $v =~ /.*=(HASH|ARRAY)/) {
401             my $db1 = $self->debug_level;
402             $self->debug_level(0);
403             $self->disp_param(${$hrf}[$i],$lzp);
404             $self->debug_level($db1);
405             if ($fh) { print $fh "\n"; } else { print "\n"; }
406             }
407             }
408             }
409             }
410              
411             1;
412