File Coverage

blib/lib/Bio/Tools/Run/WrapperBase/CommandExts.pm
Criterion Covered Total %
statement 223 422 52.8
branch 73 208 35.1
condition 21 69 30.4
subroutine 21 32 65.6
pod 9 17 52.9
total 347 748 46.3


line stmt bran cond sub pod time code
1             #
2             # BioPerl module for Bio::Tools::Run::WrapperBase::CommandExts
3             #
4             # Please direct questions and support issues to
5             #
6             # Cared for by Mark A. Jensen
7             #
8             # Copyright Mark A. Jensen
9             #
10             # You may distribute this module under the same terms as perl itself
11              
12             # POD documentation - main docs before the code
13              
14             =head1 NAME
15              
16             Bio::Tools::Run::WrapperBase::CommandExts - Extensions to WrapperBase for handling programs with commands *ALPHA*
17              
18             =head1 SYNOPSIS
19              
20             Devs, see L.
21             Users, see L.
22              
23             =head1 DESCRIPTION
24              
25             This is a developer-focused experimental module. The main idea is to
26             extend L to make it relatively easy to
27             create run wrappers around I of related programs, like
28             C or C.
29              
30             Some definitions:
31              
32             =over
33              
34             =item * program
35              
36             The program is the command-line frontend application. C, for example, is run from the command line as follows:
37              
38             $ samtools view -bS in.bam > out.sam
39             $ samtools faidx
40              
41             =item * command
42              
43             The command is the specific component of a suite run by executing the
44             program. In the example above, C and C are commands.
45              
46             =item * command prefix
47              
48             The command prefix is an abbreviation of the command name used
49             internally by C method, and sometimes by the user of the
50             factory for specifying command line parameters to subcommands of
51             composite commands.
52              
53             =item * composite command
54              
55             A composite command is a pipeline or script representing a series of
56             separate executions of different commands. Composite commands can be
57             specified by configuring C appropriately; the composite
58             command can be run by the user from a factory in the same way as
59             ordinary commands.
60              
61             =item * options, parameters, switches and filespecs
62              
63             An option is any command-line option; i.e., a specification set off by
64             a command-line by a specifier (like C<-v> or C<--outfile>). Parameters
65             are command-line options that accept a value (C<-title mydb>);
66             switches are boolean flags (C<--no-filter>). Filespecs are barewords
67             at the end of the command line that usually indicate input or output
68             files. In this module, this includes files that capture STDIN, STDOUT,
69             or STDERR via redirection.
70              
71             =item * pseudo-program
72              
73             A "pseudo-program" is a way to refer to a collection of related
74             applications that are run independently from the command line, rather
75             than via a frontend program. The C suite of programs is an
76             example: C, C, etc. C can be
77             configured to create a single factory for a suite of related,
78             independent programs that treats each independent program as a
79             "pseudo-program" command.
80              
81             =back
82              
83             This module essentially adds the non-assembler-specific wrapper
84             machinery of fangly's L to the
85             L namespace, adding the general
86             command-handling capability of L. It creates run
87             factories that are automatically Bio::ParameterBaseI compliant,
88             meaning that C, C,
89             C, C, and C
90             are available.
91              
92             =head1 DEVELOPER INTERFACE
93              
94             C is currently set up to read particular package globals
95             which define the program, the commands available, command-line options
96             for those commands, and human-readable aliases for those options.
97              
98             The easiest way to use C is probably to create two modules:
99              
100             Bio::Tools::Run::YourRunPkg
101             Bio::Tools::Run::YourRunPkg::Config
102              
103             The package globals should be defined in the C module, and the
104             run package itself should begin with the following mantra:
105              
106             use YourRunPkg::Config;
107             use Bio::Tools::Run::WrapperBase;
108             use Bio::Tools::Run::WrapperBase::CommandExts;
109             sub new {
110             my $class = shift;
111             my @args = @_;
112             my $self = $class->SUPER::new(@args);
113             ...
114             return $self;
115             }
116              
117             The following globals can/should be defined in the C module:
118              
119             $program_name
120             $program_dir
121             $use_dash
122             $join
123             @program_commands
124             %command_prefixes
125             @program_params
126             @program_switches
127             %param_translation
128             %composite_commands
129             %command_files
130              
131             See L for detailed descriptions.
132              
133             The work of creating a run wrapper with C lies mainly in
134             setting up the globals. The key methods for the developer interface are:
135              
136             =over
137              
138             =item * program_dir($path_to_programs)
139              
140             Set this to point the factory to the executables.
141              
142             =item * _run(@file_args)
143              
144             Runs an instantiated factory with the given file args. Use in the
145             C method override.
146              
147             =item * _create_factory_set()
148              
149             Returns a hash of instantiated factories for each true command from a
150             composite command factory. The hash keys are the true command names, so
151             you could do
152              
153             $cmds = $composite_fac->_create_factory_set;
154             for (@true_commands) {
155             $cmds->{$_}->_run(@file_args);
156             }
157              
158             =item * executables($cmd,[$fullpath])
159              
160             For pseudo-programs, this gets/sets the full path to the executable of
161             the true program corresponding to the command C<$cmd>.
162              
163             =back
164              
165             =head2 Implementing Composite Commands
166              
167             =head2 Implementing Pseudo-programs
168              
169             To indicate that a package wraps disparate programs under a single pseudo program, use an asterisk before the program name:
170              
171             package Bio::Tools::Run::YourPkg::Config;
172             ...
173             our $program_name = '*blast+';
174              
175             and C<_run> will know what to do. Specify the rest of the globals as
176             if the desired programs were commands. Use the basename of the
177             programs for the command names.
178              
179             If all the programs can be found in a single directory, just specify
180             that directory in C. If not, use C to set the paths to each program explicitly:
181              
182             foreach (keys %cmdpaths) {
183             $self->executables($_, $cmdpaths{$_});
184             }
185              
186             =head2 Config Globals
187              
188             Here is an example config file. Further details in prose are below.
189              
190             package Dummy::Config;
191             use strict;
192             use warnings;
193             no warnings qw(qw);
194             use Exporter;
195             our (@ISA, @EXPORT, @EXPORT_OK);
196             push @ISA, 'Exporter';
197             @EXPORT = qw(
198             $program_name
199             $program_dir
200             $use_dash
201             $join
202             @program_commands
203             %command_prefixes
204             @program_params
205             @program_switches
206             %param_translation
207             %command_files
208             %composite_commands
209             );
210              
211             our $program_name = '*flurb';
212             our $program_dir = 'C:\cygwin\usr\local\bin';
213             our $use_dash = 'mixed';
214             our $join = ' ';
215              
216             our @program_commands = qw(
217             rpsblast
218             find
219             goob
220             blorb
221             multiglob
222             );
223              
224             our %command_prefixes = (
225             blastp => 'blp',
226             tblastn => 'tbn',
227             goob => 'g',
228             blorb => 'b',
229             multiglob => 'm'
230             );
231              
232             our @program_params = qw(
233             command
234             g|narf
235             g|schlurb
236             b|scroob
237             b|frelb
238             m|trud
239             );
240              
241             our @program_switches = qw(
242             g|freen
243             b|klep
244             );
245              
246             our %param_translation = (
247             'g|narf' => 'n',
248             'g|schlurb' => 'schlurb',
249             'g|freen' => 'f',
250             'b|scroob' => 's',
251             'b|frelb' => 'frelb'
252             );
253              
254             our %command_files = (
255             'goob' => [qw( fas faq )],
256             );
257              
258             our %composite_commands = (
259             'multiglob' => [qw( blorb goob )]
260             );
261             1;
262              
263             C<$use_dash> can be one of C, C, or C. See L.
264              
265             There is a syntax for the C<%command_files> specification. The token
266             matching C<[a-zA-Z0-9_]+> in each element of each arrayref becomes the
267             named filespec parameter for the C<_run()> method in the wrapper
268             class. Additional symbols surrounding this token indicate how this
269             argument should be handled. Some examples:
270              
271             >out : stdout is redirected into the file
272             specified by (..., -out => $file,... )
273            
274             specified by (..., -in => $file,... )
275             2>log : stderr is redirected into the file
276             specified by (..., -log => $file,... )
277             #opt : this filespec argument is optional
278             (no throw if -opt => $option is missing)
279             2>#log: if -log is not specified in the arguments, the stderr()
280             method will capture stderr
281             *lst : this filespec can take multiple arguments,
282             specify using an arrayref (..., -lst => [$file1, $file2], ...)
283             *#lst : an optional list
284              
285             The tokens above are examples; they can be anything matching the above regexp.
286              
287             =head1 USER INTERFACE
288              
289             Using a wrapper created with C:
290              
291             =over
292              
293             =item * Getting a list of available commands, parameters, and filespecs:
294              
295             To get a list of commands, simply:
296              
297             @commands = Bio::Tools::Run::ThePkg->available_commands;
298              
299             The wrapper will generally have human-readable aliases for each of the
300             command-line options for the wrapped program and commands. To obtain a
301             list of the parameters and switches available for a particular
302             command, do
303              
304             $factory = Bio::Tools::Run::ThePkg->new( -command => 'glurb' );
305             @params = $factory->available_parameters('params');
306             @switches = $factory->available_parameters('switches');
307             @filespec = $factory->available_parameters('filespec');
308             @filespec = $factory->filespec; # alias
309              
310             =item * Create factories
311              
312             The factory is a handle on the program and command you wish to
313             run. Create a factory using C to set command-line parameters:
314              
315             $factory = Bio::Tools::Run::ThePkg->new( -command => 'glurb',
316             -freen => 1,
317             -furschlugginer => 'vreeble' );
318              
319             A shorthand for this is:
320              
321             $factory = Bio::Tools::Run::ThePkg->new_glurb(
322             -freen => 1,
323             -furschlugginer => 'vreeble' );
324              
325             =item * Running programs
326              
327             To run the program, use the C method, providing filespecs as arguments
328              
329             $factory = Bio::Tools::Run::ThePkg->new_assemble( -min_qual => 63 );
330             $factory->run( -faq1 => 'read1.fq', -faq2 => 'read2.fq',
331             -ref => 'refseq.fas', -out => 'new.sam' );
332             # do another
333             $factory->run( -faq1 => 'read-old1.fq', -faq2 => 'read-old2.fq',
334             -ref => 'refseq.fas', -out => 'old.sam' );
335              
336             Messages on STDOUT and STDERR are dumped into their respective attributes:
337              
338             $stdout = $factory->stdout;
339             $stderr = $factory->stderr;
340              
341             unless STDOUT and/or STDERR are part of the named files in the filespec.
342              
343             =item * Setting/getting/resetting/polling parameters.
344              
345             A C-based factory is always L
346             compliant. That means that you may set, get, and reset parameters
347             using C, C, and
348             C. You can ask whether parameters have changed since
349             they were last accessed by using the predicate
350             C. See L for more details.
351              
352             Once set, parameters become attributes of the factory. Thus, you can get their values as follows:
353              
354             if ($factory->freen) {
355             $furs = $factory->furshlugginer;
356             #...
357             }
358              
359             =back
360              
361             =head1 FEEDBACK
362              
363             =head2 Mailing Lists
364              
365             User feedback is an integral part of the evolution of this and other
366             Bioperl modules. Send your comments and suggestions preferably to
367             the Bioperl mailing list. Your participation is much appreciated.
368              
369             bioperl-l@bioperl.org - General discussion
370             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
371              
372             =head2 Support
373              
374             Please direct usage questions or support issues to the mailing list:
375              
376             L
377              
378             rather than to the module maintainer directly. Many experienced and
379             reponsive experts will be able look at the problem and quickly
380             address it. Please include a thorough description of the problem
381             with code and data examples if at all possible.
382              
383             =head2 Reporting Bugs
384              
385             Report bugs to the Bioperl bug tracking system to help us keep track
386             of the bugs and their resolution. Bug reports can be submitted via
387             the web:
388              
389             https://github.com/bioperl/bioperl-live/issues
390              
391             =head1 AUTHOR - Mark A. Jensen
392              
393             Email maj -at- fortinbras -dot- us
394              
395             Describe contact details here
396              
397             =head1 CONTRIBUTORS
398              
399             Dan Kortschak ( dan -dot- kortschak -at- adelaide -dot- edu -dot- au )
400              
401             =head1 APPENDIX
402              
403             The rest of the documentation details each of the object methods.
404             Internal methods are usually preceded with a _
405              
406             =cut
407              
408             # Let the code begin...
409              
410             package Bio::Tools::Run::WrapperBase; # need these methods in WrapperBase/maj
411 5     5   15 use strict;
  5         8  
  5         119  
412 5     5   17 use warnings;
  5         4  
  5         137  
413 5     5   15 no warnings qw(redefine);
  5         5  
  5         134  
414              
415 5     5   15 use Bio::Root::Root;
  5         5  
  5         36  
416 5     5   61 use File::Spec;
  5         4  
  5         26  
417 5     5   840 use IPC::Run;
  5         24117  
  5         165  
418 5     5   28 use base qw(Bio::Root::Root Bio::ParameterBaseI);
  5         4  
  5         2042  
419              
420             our $AUTOLOAD;
421              
422             =head2 new()
423              
424             Title : new
425             Usage :
426             Function: constructor for WrapperBase::CommandExts ;
427             correctly binds configuration variables
428             to the WrapperBase object
429             Returns : Bio::Tools::Run::WrapperBase object with command extensions
430             Args :
431             Note : this method subsumes the old _register_program_commands and
432             _set_program_options, leaving out the assembler-specific
433             parms ($qual_param and out_type())
434              
435             =cut
436              
437             sub new {
438 4     4 1 10 my ($class, @args) = @_;
439 4         8 my $self = bless ({}, $class);
440             # pull in *copies* of the Config variables from the caller namespace:
441 4         18 my ($pkg, @goob) = caller();
442 4         69 my ($commands,
443             $prefixes,
444             $params,
445             $switches,
446             $translation,
447             $use_dash,
448             $join,
449             $name,
450             $dir,
451             $composite_commands,
452             $files);
453 4         12 for (qw( @program_commands
454             %command_prefixes
455             @program_params
456             @program_switches
457             %param_translation
458             $use_dash
459             $join
460             $program_name
461             $program_dir
462             %composite_commands
463             %command_files ) ) {
464 44         118 my ($sigil, $var) = m/(.)(.*)/;
465 44         68 my $qualvar = "${sigil}${pkg}::${var}";
466 44         43 for ($sigil) {
467 44 100       85 /\@/ && do { $qualvar = "\[$qualvar\]" };
  12         18  
468 44 100       79 /\%/ && do { $qualvar = "\{$qualvar\}" };
  16         28  
469             }
470 44         52 my $locvar = "\$${var}";
471 44         126 $locvar =~ s/program_|command_|param_//g;
472 44         1783 eval "$locvar = $qualvar";
473             }
474             # set up the info registry hash
475 4         7 my %registry;
476 4 50       11 if ($composite_commands) {
477 4         23 $self->_register_composite_commands($composite_commands,
478             $params,
479             $switches,
480             $prefixes);
481             }
482 4         15 @registry{qw( _commands _prefixes _files
483             _params _switches _translation
484             _composite_commands )} =
485             ($commands, $prefixes, $files,
486             $params, $switches, $translation,
487             $composite_commands);
488 4         34 $self->{_options} = \%registry;
489 4 50       12 if (not defined $use_dash) {
490 0         0 $self->{'_options'}->{'_dash'} = 1;
491             } else {
492 4         11 $self->{'_options'}->{'_dash'} = $use_dash;
493             }
494 4 50       9 if (not defined $join) {
495 0         0 $self->{'_options'}->{'_join'} = ' ';
496             } else {
497 4         6 $self->{'_options'}->{'_join'} = $join;
498             }
499 4 100       16 if ($name =~ /^\*/) {
500 3         12 $self->is_pseudo(1);
501 3         8 $name =~ s/^\*//;
502             }
503 4 50       16 $self->program_name($name) if not defined $self->program_name();
504 4 50       13 $self->program_dir($dir) if not defined $self->program_dir();
505 4         16 $self->set_parameters(@args);
506 4         12 $self->parameters_changed(1); # set on instantiation, per Bio::ParameterBaseI
507 4         80 return $self;
508             }
509              
510             =head2 program_name
511              
512             Title : program_name
513             Usage : $factory->program_name($name)
514             Function: get/set the executable name
515             Returns: string
516             Args : string
517              
518             =cut
519              
520             sub program_name {
521 10     10 1 13 my ($self, $val) = @_;
522 10 100       19 $self->{'_program_name'} = $val if $val;
523 10         28 return $self->{'_program_name'};
524             }
525              
526             =head2 program_dir
527              
528             Title : program_dir
529             Usage : $factory->program_dir($dir)
530             Function: get/set the program dir
531             Returns: string
532             Args : string
533              
534             =cut
535              
536             sub program_dir {
537 32     32 1 28 my ($self, $val) = @_;
538 32 50       50 $self->{'_program_dir'} = $val if $val;
539 32         57 return $self->{'_program_dir'};
540             }
541              
542             =head2 _register_program_commands()
543              
544             Title : _register_program_commands
545             Usage : $factory->_register_program_commands( \@commands, \%prefixes )
546             Function: Register the commands a program accepts (for programs that act
547             as frontends for a set of commands, each command having its own
548             set of params/switches)
549             Returns : true on success
550             Args : arrayref to a list of commands (scalar strings),
551             hashref to a translation table of the form
552             { $prefix1 => $command1, ... } [optional]
553             Note : To implement a program with this kind of calling structure,
554             include a parameter called 'command' in the
555             @program_params global
556             Note : The translation table is used to associate parameters and
557             switches specified in _set_program_options with the correct
558             program command. In the globals @program_params and
559             @program_switches, specify elements as 'prefix1|param' and
560             'prefix1|switch', etc.
561              
562             =cut
563              
564             =head2 _set_program_options
565              
566             Title : _set_program_options
567             Usage : $factory->_set_program_options( \@ args );
568             Function: Register the parameters and flags that an assembler takes.
569             Returns : 1 for success
570             Args : - arguments passed by the user
571             - parameters that the program accepts, optional (default: none)
572             - switches that the program accepts, optional (default: none)
573             - parameter translation, optional (default: no translation occurs)
574             - dash option for the program parameters, [1|single|double|mixed],
575             optional (default: yes, use single dashes only)
576             - join, optional (default: ' ')
577              
578             =cut
579              
580             =head2 _translate_params
581              
582             Title : _translate_params
583             Usage : @options = @{$assembler->_translate_params( )};
584             Function: Translate the Bioperl arguments into the arguments to pass to the
585             program on the command line
586             Returns : Arrayref of arguments
587             Args : none
588              
589             =cut
590              
591             sub _translate_params {
592 2     2   3282 my ($self) = @_;
593             # Get option string
594             my ($params, $switches, $join, $dash, $translat) =
595 2         4 @{$self->{_options}}{qw(_params _switches _join _dash _translation)};
  2         9  
596              
597             # access the multiple dash choices of _setparams...
598 2         3 my @dash_args;
599 2   50     6 $dash ||= 1; # default as advertised
600 2         5 for ($dash) {
601 2 100       8 $_ eq '1' && do {
602 1         4 @dash_args = ( -dash => 1 );
603 1         2 last;
604             };
605 1 50       4 /^s/ && do { #single dash only
606 0         0 @dash_args = ( -dash => 1);
607 0         0 last;
608             };
609 1 50       3 /^d/ && do { # double dash only
610 0         0 @dash_args = ( -double_dash => 1);
611 0         0 last;
612             };
613 1 50       100 /^m/ && do { # mixed dash: one-letter opts get -,
614             # long opts get --
615 1         7 @dash_args = ( -mixed_dash => 1);
616 1         1 last;
617             };
618 0         0 do {
619 0         0 $self->warn( "Dash spec '$dash' not recognized; using 'single'" );
620 0         0 @dash_args = ( -dash => 1 );
621             };
622             }
623 2         18 my $options = $self->_setparams(
624             -params => $params,
625             -switches => $switches,
626             -join => $join,
627             @dash_args
628             );
629              
630             # Translate options
631             # parse more carefully - bioperl-run issue #12
632 2         12 $options =~ s/^\s+//;
633 2         10 $options =~ s/\s+$//;
634 2         3 my @options;
635             my $in_quotes;
636 2         70 for (split(/(\s|$join)/, $options)) {
637 24 100       52 if (/^-/) {
    50          
    50          
638 8         11 push @options, $_;
639             }
640             elsif (s/^"//) {
641 0 0       0 $in_quotes=1 unless (s/["']$//);
642 0         0 push @options, $_;
643             }
644             elsif (s/"$//) {
645 0         0 $options[-1] .= $_;
646 0         0 $in_quotes=0;
647             }
648             else {
649 16 50       21 $in_quotes ? $options[-1] .= $_ :
650             push(@options, $_);
651             }
652             }
653 2 50       13 $self->throw("Unmatched quote in option value") if $in_quotes;
654 2         8 for (my $i = 0; $i < scalar @options; $i++) {
655 20         41 my ($prefix, $name) = ( $options[$i] =~ m/^(-{0,2})(.+)$/ );
656 20 50       23 if (defined $name) {
657 20 100       53 if ($name =~ /command/i) {
    100          
658 2         3 $name = $options[$i+2]; # get the command
659 2         6 splice @options, $i, 4;
660 2         2 $i--;
661             # don't add the command if this is a pseudo-program
662 2 100       11 unshift @options, $name unless ($self->is_pseudo); # put command first
663             }
664             elsif (defined $$translat{$name}) {
665 6         16 $options[$i] = $prefix.$$translat{$name};
666             }
667             }
668             else {
669 0         0 splice @options, $i, 1;
670 0         0 $i--;
671             }
672             }
673              
674 2         38 @options = grep (!/^\s*$/,@options);
675             # this is a kludge for mixed options: the reason mixed doesn't
676             # work right on the pass through _setparams is that the
677             # *aliases* and not the actual params are passed to it.
678             # here we just rejigger the dashes
679 2 100       8 if ($dash =~ /^m/) {
680 1         13 s/--([a-z0-9](?:\s|$))/-$1/gi for @options;
681             }
682             # Now arrayify the options
683              
684 2         13 return \@options;
685             }
686              
687             =head2 executable()
688              
689             Title : executable
690             Usage :
691             Function: find the full path to the main executable,
692             or to the command executable for pseudo-programs
693             Returns : full path, if found
694             Args : [optional] explicit path to the executable
695             (will set the appropriate command exec if
696             applicable)
697             [optional] boolean flag whether or not to warn when exe no found
698             Note : overrides WrapperBase.pm
699              
700             =cut
701              
702             sub executable {
703 3     3 1 1567 my $self = shift;
704 3         6 my ($exe, $warn) = @_;
705 3 100       6 if ($self->is_pseudo) {
706 2         43 return $self->{_pathtoexe} = $self->executables($self->command,$exe);
707             }
708              
709             # otherwise
710             # setter
711 1 50       3 if (defined $exe) {
712 0 0       0 $self->throw("binary '$exe' does not exist") unless -e $exe;
713 0 0       0 $self->throw("'$exe' is not executable") unless -x $exe;
714 0         0 return $self->{_pathtoexe} = $exe;
715             }
716              
717             # getter
718 1 50       3 return $self->{_pathtoexe} if defined $self->{_pathstoexe};
719              
720             # finder
721 1         6 return $self->{_pathtoexe} = $self->_find_executable($exe, $warn);
722             }
723              
724             =head2 executables()
725              
726             Title : executables
727             Usage :
728             Function: find the full path to a command's executable
729             Returns : full path (scalar string)
730             Args : command (scalar string),
731             [optional] explicit path to this command exe
732             [optional] boolean flag whether or not to warn when exe no found
733              
734             =cut
735              
736             sub executables {
737 12     12 0 22 my $self = shift;
738 12         16 my ($cmd, $exe, $warn) = @_;
739             # for now, barf if this is not a pseudo program
740 12 50       19 $self->throw("This wrapper represents a single program with commands, not multiple programs; can't use executables()") unless $self->is_pseudo;
741 12 50       20 $self->throw("Command name required at arg 1") unless defined $cmd;
742 12 50       9 $self->throw("The desired executable '$cmd' is not registered as a command") unless grep /^$cmd$/, @{$self->{_options}->{_commands}};
  12         189  
743              
744             # setter
745 12 50       22 if (defined $exe) {
746 0 0       0 $self->throw("binary '$exe' does not exist") unless -e $exe;
747 0 0       0 $self->throw("'$exe' is not executable") unless -x $exe;
748 0 0       0 $self->{_pathstoexe} = {} unless defined $self->{_pathstoexe};
749 0         0 return $self->{_pathstoexe}->{$cmd} = $exe;
750             }
751              
752             # getter
753 12 50       27 return $self->{_pathstoexe}->{$cmd} if defined $self->{_pathstoexe}->{$cmd};
754              
755 12   33     37 $exe ||= $cmd;
756             # finder
757 12         24 return $self->{_pathstoexe}->{$cmd} = $self->_find_executable($exe, $warn);
758             }
759              
760             =head2 _find_executable()
761              
762             Title : _find_executable
763             Usage : my $exe_path = $fac->_find_executable($exe, $warn);
764             Function: find the full path to a named executable,
765             Returns : full path, if found
766             Args : name of executable to find
767             [optional] boolean flag whether or not to warn when exe no found
768             Note : differs from executable and executables in not
769             setting any object attributes
770              
771             =cut
772              
773             sub _find_executable {
774 23     23   19 my $self = shift;
775 23         24 my ($exe, $warn) = @_;
776              
777 23 50 66     32 if ($self->is_pseudo && !$exe) {
778 0 0       0 if (!$self->command) {
779             # this throw probably appropriate
780             # the rest are now warns if $warn.../maj
781 0         0 $self->throw(
782             "The ".__PACKAGE__." wrapper represents several different programs;".
783             "arg1 to _find_executable must be specified explicitly,".
784             "or the command() attribute set");
785             }
786             else {
787 0         0 $exe = $self->command;
788             }
789             }
790 23   66     43 $exe ||= $self->program_path;
791              
792 23         16 my $path;
793 23 50       33 if ($self->program_dir) {
794 0         0 $path = File::Spec->catfile($self->program_dir, $exe);
795             } else {
796 23         27 $path = $exe;
797 23 50       39 $self->warn('Program directory not specified; use program_dir($path).') if $warn;
798             }
799              
800             # use provided info - we are allowed to follow symlinks, but refuse directories
801 23 50 33     41 map { return $path.$_ if ( -x $path.$_ && !(-d $path.$_) ) } ('', '.exe') if defined $path;
  46 50       478  
802              
803             # couldn't get path to executable from provided info, so use system path
804 23 50       51 $path = $path ? " in $path" : undef;
805 23 50       32 $self->warn("Executable $exe not found$path, trying system path...") if $warn;
806 23 50       63 if ($path = $self->io->exists_exe($exe)) {
807 0         0 return $path;
808             } else {
809 23 0       2633 $self->warn("Cannot find executable for program '".($self->is_pseudo ? $self->command : $self->program_name)."'") if $warn;
    50          
810 23         74 return;
811             }
812             }
813              
814             =head2 _register_composite_commands()
815              
816             Title : _register_composite_commands
817             Usage :
818             Function: adds subcomand params and switches for composite commands
819             Returns : true on success
820             Args : \%composite_commands,
821             \@program_params,
822             \@program_switches
823              
824             =cut
825              
826             sub _register_composite_commands {
827 4     4   7 my $self = shift;
828 4         6 my ($composite_commands, $program_params,
829             $program_switches, $command_prefixes) = @_;
830 4         4 my @sub_params;
831             my @sub_switches;
832 4         9 foreach my $cmd (keys %$composite_commands) {
833 0   0     0 my $pfx = $command_prefixes->{$cmd} || $cmd;
834 0         0 foreach my $subcmd ( @{$$composite_commands{$cmd}} ) {
  0         0  
835 0   0     0 my $spfx = $command_prefixes->{$subcmd} || $subcmd;
836 0         0 my @sub_program_params = grep /^$spfx\|/, @$program_params;
837 0         0 my @sub_program_switches = grep /^$spfx\|/, @$program_switches;
838 0         0 for (@sub_program_params) {
839 0         0 m/^$spfx\|(.*)/;
840 0         0 push @sub_params, "$pfx\|${spfx}_".$1;
841             }
842 0         0 for (@sub_program_switches) {
843 0         0 m/^$spfx\|(.*)/;
844 0         0 push @sub_switches, "$pfx\|${spfx}_".$1;
845             }
846             }
847             }
848 4         29 push @$program_params, @sub_params;
849 4         5 push @$program_switches, @sub_switches;
850             # translations for subcmd params/switches not necessary
851 4         7 return 1;
852             }
853              
854             =head2 _create_factory_set()
855              
856             Title : _create_factory_set
857             Usage : @facs = $self->_create_factory_set
858             Function: instantiate a set of individual command factories for
859             a given composite command
860             Factories will have the correct parameter fields set for
861             their own subcommand
862             Returns : hash of factories: ( $subcmd_prefix => $subcmd_factory, ... )
863             Args : none
864              
865             =cut
866              
867             sub _create_factory_set {
868 0     0   0 my $self = shift;
869 0 0       0 $self->throw('command not set') unless $self->command;
870 0         0 my $cmd = $self->command;
871             $self->throw('_create_factory_set only works on composite commands')
872 0 0       0 unless grep /^$cmd$/, keys %{$self->{_options}->{_composite_commands}};
  0         0  
873 0         0 my %ret;
874 0         0 my $class = ref $self;
875 0         0 my $subargs_hash = $self->_collate_subcmd_args($cmd);
876 0         0 for (keys %$subargs_hash) {
877 0         0 $ret{$_} = $class->new( -command => $_, @{$$subargs_hash{$_}} );
  0         0  
878             }
879 0         0 return %ret;
880             }
881              
882             =head2 _collate_subcmd_args()
883              
884             Title : _collate_subcmd_args
885             Usage : $args_hash = $self->_collate_subcmd_args
886             Function: collate parameters and switches into command-specific
887             arg lists for passing to new()
888             Returns : hash of named argument lists
889             Args : [optional] composite cmd prefix (scalar string)
890             [default is 'run']
891              
892             =cut
893              
894             sub _collate_subcmd_args {
895 0     0   0 my $self = shift;
896 0         0 my $cmd = shift;
897 0         0 my %ret;
898             # default command is 'run'
899 0   0     0 $cmd ||= 'run';
900 0 0       0 return unless $self->{'_options'}->{'_composite_commands'};
901 0 0       0 return unless $self->{'_options'}->{'_composite_commands'}->{$cmd};
902 0         0 my @subcmds = @{$self->{'_options'}->{'_composite_commands'}->{$cmd}};
  0         0  
903              
904 0         0 my $cur_options = $self->{'_options'};
905             # collate
906 0         0 foreach my $subcmd (@subcmds) {
907             # find the composite cmd form of the argument in
908             # the current params and switches
909             # e.g., map_max_mismatches
910 0   0     0 my $pfx = $self->{_options}->{_prefixes}->{$subcmd} || $subcmd;
911 0         0 my @params = grep /^${pfx}_/, @{$$cur_options{'_params'}};
  0         0  
912 0         0 my @switches = grep /^${pfx}_/, @{$$cur_options{'_switches'}};
  0         0  
913 0         0 $ret{$subcmd} = [];
914             # create an argument list suitable for passing to new() of
915             # the subcommand factory...
916 0         0 foreach my $opt (@params, @switches) {
917 0         0 my $subopt = $opt;
918 0         0 $subopt =~ s/^${pfx}_//;
919 0 0       0 push(@{$ret{$subcmd}}, '-'.$subopt => $self->$opt) if defined $self->$opt;
  0         0  
920             }
921             }
922 0         0 return \%ret;
923             }
924              
925             =head2 _run
926              
927             Title : _run
928             Usage : $fac->_run( @file_args )
929             Function: Run a command as specified during object contruction
930             Returns : true on success
931             Args : a specification of the files to operate on according
932             to the filespec
933              
934             =cut
935              
936             sub _run {
937 0     0   0 my ($self, @args) = @_;
938             # _translate_params will provide an array of command/parameters/switches
939             # -- these are set at object construction
940             # to set up the run, need to add the files to the call
941             # -- provide these as arguments to this function
942 0 0       0 my $cmd = $self->command if $self->can('command');
943 0         0 my $opts = $self->{_options};
944 0         0 my %args;
945 0 0       0 $self->throw("No command specified for the object") unless $cmd;
946             # setup files necessary for this command
947 0         0 my $filespec = $opts->{'_files'}->{$cmd};
948 0         0 my @switches;
949 0         0 my ($in, $out, $err);
950             # some applications rely completely on switches
951 0 0 0     0 if (defined $filespec && @$filespec) {
952             # parse args based on filespec
953             # require named args
954 0 0       0 $self->throw("Named args are required") unless !(@args % 2);
955 0         0 s/^-// for @args;
956 0         0 %args = @args;
957             # validate
958             my @req = map {
959 0         0 my $s = $_;
  0         0  
960 0         0 $s =~ s/^-.*\|//;
961 0         0 $s =~ s/^[012]?[<>]//;
962 0         0 $s =~ s/[^a-zA-Z0-9_]//g;
963 0         0 $s
964             } grep !/[#]/, @$filespec;
965 0   0     0 !defined($args{$_}) && $self->throw("Required filearg '$_' not specified") for @req;
966             # set up redirects and file switches
967 0         0 for (@$filespec) {
968 0 0       0 m/^1?>#?(.*)/ && do {
969 0 0 0     0 defined($args{$1}) && ( open $out, '>', $args{$1} or $self->throw("Could not write file '$args{$1}': $!") );
970 0         0 next;
971             };
972 0 0       0 m/^2>#?(.*)/ && do {
973 0 0 0     0 defined($args{$1}) && ( open $err, '>', $args{$1} or $self->throw("Could not write file '$args{$1}': $!") );
974 0         0 next;
975             };
976 0 0       0 m/^<#?(.*)/ && do {
977 0 0 0     0 defined($args{$1}) && ( open $in, '<', $args{$1} or $self->throw("Could not read file '$args{$1}': $!") );
978 0         0 next;
979             };
980 0 0       0 if (m/^-(.*)\|/) {
981 0         0 push @switches, $self->_dash_switch($1);
982             } else {
983 0         0 push @switches, undef;
984             }
985             }
986             }
987 0         0 my $dum;
988 0 0       0 $in || ($in = \$dum);
989 0 0       0 $out || ($out = \$self->{'stdout'});
990 0 0       0 $err || ($err = \$self->{'stderr'});
991              
992             # Get program executable
993 0         0 my $exe = $self->executable;
994 0 0       0 $self->throw("Can't find executable for '".($self->is_pseudo ? $self->command : $self->program_name)."'; can't continue") unless $exe;
    0          
995              
996             # Get command-line options
997 0         0 my $options = $self->_translate_params();
998             # Get file specs sans redirects in correct order
999             my @specs = map {
1000 0         0 my $s = $_;
  0         0  
1001 0         0 $s =~ s/^-.*\|//;
1002 0         0 $s =~ s/[^a-zA-Z0-9_]//g;
1003 0         0 $s
1004             } grep !/[<>]/, @$filespec;
1005 0         0 my @files = @args{@specs};
1006             # expand arrayrefs
1007 0         0 my $l = $#files;
1008              
1009             # Note: below code block may be brittle, see link on this:
1010             # http://lists.open-bio.org/pipermail/bioperl-l/2010-June/033439.html
1011              
1012 0         0 for (0..$l) {
1013 0 0       0 if (ref($files[$_]) eq 'ARRAY') {
1014 0         0 splice(@switches, $_, 1, ($switches[$_]) x @{$files[$_]});
  0         0  
1015 0         0 splice(@files, $_, 1, @{$files[$_]});
  0         0  
1016             }
1017             }
1018              
1019             @files = map {
1020 0         0 my $s = shift @switches;
  0         0  
1021 0 0       0 defined $_ ? ($s, $_): ()
1022             } @files;
1023 0 0       0 @files = map { defined $_ ? $_ : () } @files; # squish undefs
  0         0  
1024 0         0 my @ipc_args = ( $exe, @$options, @files );
1025 0         0 $self->{_last_execution} = join( $self->{'_options'}->{'_join'}, @ipc_args );
1026 0         0 eval {
1027 0 0       0 IPC::Run::run(\@ipc_args, $in, $out, $err) or
1028             die ("There was a problem running $exe : ".$$err);
1029             };
1030              
1031 0 0       0 if ($@) {
1032 0 0       0 $self->throw("$exe call crashed: $@") unless $self->no_throw_on_crash;
1033 0         0 return 0;
1034             }
1035              
1036 0         0 return 1;
1037             }
1038              
1039              
1040              
1041             =head2 no_throw_on_crash()
1042              
1043             Title : no_throw_on_crash
1044             Usage :
1045             Function: prevent throw on execution error
1046             Returns :
1047             Args : [optional] boolean
1048              
1049             =cut
1050              
1051             sub no_throw_on_crash {
1052 0     0 0 0 my $self = shift;
1053 0 0       0 return $self->{'_no_throw'} = shift if @_;
1054 0         0 return $self->{'_no_throw'};
1055             }
1056              
1057             =head2 last_execution()
1058              
1059             Title : last_execution
1060             Usage :
1061             Function: return the last executed command with options
1062             Returns : string of command line sent to IPC::Run
1063             Args :
1064              
1065             =cut
1066              
1067             sub last_execution {
1068 0     0 0 0 my $self = shift;
1069 0         0 return $self->{'_last_execution'};
1070             }
1071              
1072             =head2 _dash_switch()
1073              
1074             Title : _dash_switch
1075             Usage : $version = $fac->_dash_switch( $switch )
1076             Function: Returns an appropriately dashed switch for the executable
1077             Args : A string containing a switch without dashes
1078             Returns : string containing an appropriately dashed switch for the current executable
1079              
1080             =cut
1081              
1082             sub _dash_switch {
1083 0     0   0 my ($self, $switch) = @_;
1084              
1085 0         0 my $dash = $self->{'_options'}->{'_dash'};
1086 0         0 for ($dash) {
1087 0 0       0 $_ eq '1' && do {
1088 0         0 $switch = '-'.$switch;
1089 0         0 last;
1090             };
1091 0 0       0 /^s/ && do { #single dash only
1092 0         0 $switch = '-'.$switch;
1093 0         0 last;
1094             };
1095 0 0       0 /^d/ && do { # double dash only
1096 0         0 $switch = '--'.$switch;
1097 0         0 last;
1098             };
1099 0 0       0 /^m/ && do { # mixed dash: one-letter opts get -,
1100 0         0 $switch = '-'.$switch;
1101 0         0 $switch =~ s/^(-[a-z0-9](?:\w+))$/-$1/i;
1102 0         0 last;
1103             };
1104 0         0 do {
1105 0         0 $self->warn( "Dash spec '$dash' not recognized; using 'single'" );
1106 0         0 $switch = '-'.$switch;
1107             };
1108             }
1109              
1110 0         0 return $switch;
1111             }
1112              
1113             =head2 stdout()
1114              
1115             Title : stdout
1116             Usage : $fac->stdout()
1117             Function: store the output from STDOUT for the run,
1118             if no file specified in _run arguments
1119             Example :
1120             Returns : scalar string
1121             Args : on set, new value (a scalar or undef, optional)
1122              
1123             =cut
1124              
1125             sub stdout {
1126 0     0 0 0 my $self = shift;
1127 0 0       0 return $self->{'stdout'} = shift if @_;
1128 0         0 return $self->{'stdout'};
1129             }
1130              
1131             =head2 stderr()
1132              
1133             Title : stderr
1134             Usage : $fac->stderr()
1135             Function: store the output from STDERR for the run,
1136             if no file is specified in _run arguments
1137             Example :
1138             Returns : scalar string
1139             Args : on set, new value (a scalar or undef, optional)
1140              
1141             =cut
1142              
1143             sub stderr {
1144 0     0 0 0 my $self = shift;
1145 0 0       0 return $self->{'stderr'} = shift if @_;
1146 0         0 return $self->{'stderr'};
1147             }
1148              
1149             =head2 is_pseudo()
1150              
1151             Title : is_pseudo
1152             Usage : $obj->is_pseudo($newval)
1153             Function: returns true if this factory represents
1154             a pseudo-program
1155             Example :
1156             Returns : value of is_pseudo (boolean)
1157             Args : on set, new value (a scalar or undef, optional)
1158              
1159             =cut
1160              
1161             sub is_pseudo {
1162 43     43 0 36 my $self = shift;
1163              
1164 43 100       66 return $self->{'is_pseudo'} = shift if @_;
1165 40         123 return $self->{'is_pseudo'};
1166             }
1167              
1168             =head2 AUTOLOAD
1169              
1170             AUTOLOAD permits
1171              
1172             $class->new_yourcommand(@args);
1173              
1174             as an alias for
1175              
1176             $class->new( -command => 'yourcommand', @args );
1177              
1178             =cut
1179              
1180             sub AUTOLOAD {
1181 0     0   0 my $class = shift;
1182 0         0 my $tok = $AUTOLOAD;
1183 0         0 my @args = @_;
1184 0         0 $tok =~ s/.*:://;
1185 0 0       0 unless ($tok =~ /^new_/) {
1186 0 0       0 $class->throw("Can't locate object method '$tok' via package '".ref($class)?ref($class):$class);
1187             }
1188 0         0 my ($cmd) = $tok =~ m/new_(.*)/;
1189 0         0 return $class->new( -command => $cmd, @args );
1190             }
1191              
1192             =head1 Bio:ParameterBaseI compliance
1193              
1194             =head2 set_parameters()
1195              
1196             Title : set_parameters
1197             Usage : $pobj->set_parameters(%params);
1198             Function: sets the parameters listed in the hash or array
1199             Returns : true on success
1200             Args : [optional] hash or array of parameter/values.
1201              
1202             =cut
1203              
1204             sub set_parameters {
1205 14     14 1 453 my ($self, @args) = @_;
1206              
1207             # currently stored stuff
1208 14         17 my $opts = $self->{'_options'};
1209 14         15 my $params = $opts->{'_params'};
1210 14         13 my $switches = $opts->{'_switches'};
1211 14         11 my $translation = $opts->{'_translation'};
1212 14         16 my $use_dash = $opts->{'_dash'};
1213 14         14 my $join = $opts->{'_join'};
1214 14 50 100     312 unless (($self->can('command') && $self->command)
      66        
1215             || (grep /command/, @args)) {
1216 0         0 push @args, '-command', 'run';
1217             }
1218 14         110 my %args = @args;
1219 14   66     133 my $cmd = $args{'-command'} || $args{'command'} || ($self->can('command') && $self->command);
1220 14 50       49 if ($cmd) {
1221 14         11 my (@p,@s, %x);
1222 14 50       29 $self->warn('Command present, but no commands registered') unless $self->{'_options'}->{'_commands'};
1223 14 50       12 $self->throw("Command '$cmd' not registered") unless grep /^$cmd$/, @{$self->{'_options'}->{'_commands'}};
  14         167  
1224 14   33     36 $cmd = $self->{_options}->{_prefixes}->{$cmd} || $cmd;
1225              
1226 14         554 @p = (grep(!/^.*?\|/, @$params), grep(/^${cmd}\|/, @$params));
1227 14         431 @s = (grep(!/^.*?\|/, @$switches), grep(/^${cmd}\|/, @$switches));
1228 14         123 s/.*?\|// for @p;
1229 14         106 s/.*?\|// for @s;
1230 14         337 @x{@p, @s} = @{$translation}{
1231 14         868 grep( !/^.*?\|/, @$params, @$switches),
1232             grep(/^${cmd}\|/, @$params, @$switches) };
1233 14         40 $opts->{_translation} = $translation = \%x;
1234 14         38 $opts->{_params} = $params = \@p;
1235 14         27 $opts->{_switches} = $switches = \@s;
1236             }
1237             $self->_set_from_args(
1238 14         133 \@args,
1239             -methods => [ @$params, @$switches, 'program_name', 'program_dir', 'out_type' ],
1240             -create => 1,
1241             # when our parms are accessed, signal parameters are unchanged for
1242             # future reads (until set_parameters is called)
1243             -code =>
1244             ' my $self = shift;
1245             $self->parameters_changed(0);
1246             return $self->{\'_\'.$method} = shift if @_;
1247             return $self->{\'_\'.$method};'
1248             );
1249             # the question is, are previously-set parameters left alone when
1250             # not specified in @args?
1251 14         264 $self->parameters_changed(1);
1252 14         75 return 1;
1253             }
1254              
1255             =head2 reset_parameters()
1256              
1257             Title : reset_parameters
1258             Usage : resets values
1259             Function: resets parameters to either undef or value in passed hash
1260             Returns : none
1261             Args : [optional] hash of parameter-value pairs
1262              
1263             =cut
1264              
1265             sub reset_parameters {
1266 2     2 1 784 my ($self, @args) = @_;
1267              
1268 2         4 my @reset_args;
1269             # currently stored stuff
1270 2         3 my $opts = $self->{'_options'};
1271 2         4 my $params = $opts->{'_params'};
1272 2         3 my $switches = $opts->{'_switches'};
1273 2         4 my $translation = $opts->{'_translation'};
1274 2         3 my $qual_param = $opts->{'_qual_param'};
1275 2         4 my $use_dash = $opts->{'_dash'};
1276 2         3 my $join = $opts->{'_join'};
1277              
1278             # handle command name
1279 2         5 my %args = @args;
1280 2   33     50 my $cmd = $args{'-command'} || $args{'command'} || $self->command;
1281 2         13 $args{'command'} = $cmd;
1282 2         4 delete $args{'-command'};
1283 2         6 @args = %args;
1284             # don't like this, b/c _set_program_args will create a bunch of
1285             # accessors with undef values, but oh well for now /maj
1286              
1287 2         22 for my $p (@$params) {
1288 42 100       461 push(@reset_args, $p => undef) unless grep /^[-]?$p$/, @args;
1289             }
1290 2         4 for my $s (@$switches) {
1291 40 50       360 push(@reset_args, $s => undef) unless grep /^[-]?$s$/, @args;
1292             }
1293 2         14 push @args, @reset_args;
1294 2         13 $self->set_parameters(@args);
1295 2         7 $self->parameters_changed(1);
1296             }
1297              
1298             =head2 parameters_changed()
1299              
1300             Title : parameters_changed
1301             Usage : if ($pobj->parameters_changed) {...}
1302             Function: Returns boolean true (1) if parameters have changed
1303             Returns : Boolean (0 or 1)
1304             Args : [optional] Boolean
1305              
1306             =cut
1307              
1308             sub parameters_changed {
1309 339     339 1 21064 my $self = shift;
1310 339 100       4259 return $self->{'_parameters_changed'} = shift if @_;
1311 11         40 return $self->{'_parameters_changed'};
1312             }
1313              
1314             =head2 available_parameters()
1315              
1316             Title : available_parameters
1317             Usage : @params = $pobj->available_parameters()
1318             Function: Returns a list of the available parameters
1319             Returns : Array of parameters
1320             Args : 'params' for settable program parameters
1321             'switches' for boolean program switches
1322             default: all
1323              
1324             =cut
1325              
1326             sub available_parameters {
1327 9     9 1 12 my $self = shift;
1328 9         12 my $subset = shift;
1329 9         10 my $opts = $self->{'_options'};
1330 9         9 my @ret;
1331 9         14 for ($subset) {
1332 9 100 66     71 (!defined || /^a/) && do {
1333 3         4 @ret = (@{$opts->{'_params'}}, @{$opts->{'_switches'}});
  3         5  
  3         19  
1334 3         5 last;
1335             };
1336 6 100       22 m/^p/i && do {
1337 3         3 @ret = @{$opts->{'_params'}};
  3         14  
1338 3         4 last;
1339             };
1340 3 50       12 m/^s/i && do {
1341 3         4 @ret = @{$opts->{'_switches'}};
  3         12  
1342 3         6 last;
1343             };
1344 0 0       0 m/^c/i && do {
1345 0         0 @ret = @{$opts->{'_commands'}};
  0         0  
1346 0         0 last;
1347             };
1348 0 0       0 m/^f/i && do { # get file spec
1349 0         0 return @{$opts->{'_files'}->{$self->command}};
  0         0  
1350             };
1351 0         0 do { #fail
1352 0         0 $self->throw("available_parameters: unrecognized subset");
1353             };
1354             }
1355 9         38 return @ret;
1356             }
1357              
1358 0     0 0 0 sub available_commands { shift->available_parameters('commands') }
1359 0     0 0 0 sub filespec { shift->available_parameters('filespec') }
1360              
1361             =head2 get_parameters()
1362              
1363             Title : get_parameters
1364             Usage : %params = $pobj->get_parameters;
1365             Function: Returns list of key-value pairs of parameter => value
1366             Returns : List of key-value pairs
1367             Args : [optional] A string is allowed if subsets are wanted or (if a
1368             parameter subset is default) 'all' to return all parameters
1369              
1370             =cut
1371              
1372             sub get_parameters {
1373 2     2 1 5 my $self = shift;
1374 2         3 my $subset = shift;
1375 2   50     13 $subset ||= 'all';
1376 2         2 my @ret;
1377 2         4 my $opts = $self->{'_options'};
1378 2         6 for ($subset) {
1379 2 50       9 m/^p/i && do { #params only
1380 0         0 for (@{$opts->{'_params'}}) {
  0         0  
1381 0 0 0     0 push(@ret, $_, $self->$_) if $self->can($_) && defined $self->$_;
1382             }
1383 0         0 last;
1384             };
1385 2 50       6 m/^s/i && do { #switches only
1386 0         0 for (@{$opts->{'_switches'}}) {
  0         0  
1387 0 0 0     0 push(@ret, $_, $self->$_) if $self->can($_) && defined $self->$_;
1388             }
1389 0         0 last;
1390             };
1391 2 50       7 m/^a/i && do { # all
1392 2         3 for ((@{$opts->{'_params'}},@{$opts->{'_switches'}})) {
  2         5  
  2         3  
1393 74 100 66     1467 push(@ret, $_, $self->$_) if $self->can($_) && defined $self->$_;
1394             }
1395 2         14 last;
1396             };
1397 0         0 do {
1398 0         0 $self->throw("get_parameters: unrecognized subset");
1399             };
1400             }
1401 2         12 return @ret;
1402             }
1403              
1404             1;