diff variant_effect_predictor/Bio/Root/IOManager.pm @ 0:1f6dce3d34e0

Uploaded
author mahtabm
date Thu, 11 Apr 2013 02:01:53 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/variant_effect_predictor/Bio/Root/IOManager.pm	Thu Apr 11 02:01:53 2013 -0400
@@ -0,0 +1,1149 @@
+#-----------------------------------------------------------------------------
+# PACKAGE : Bio::Root::IOManager.pm
+# AUTHOR  : Steve Chervitz (sac@bioperl.org)
+# CREATED : 26 Mar 1997
+# REVISION: $Id: IOManager.pm,v 1.13 2002/10/22 07:38:37 lapp Exp $
+# STATUS  : Alpha
+#
+# For documentation, run this module through pod2html
+# (preferably from Perl v5.004 or better).
+#
+# MODIFICATION NOTES: See bottom of file.
+#
+# Copyright (c) 1997-2000 Steve Chervitz. All Rights Reserved.
+#           This module is free software; you can redistribute it and/or
+#           modify it under the same terms as Perl itself.
+#-----------------------------------------------------------------------------
+
+package Bio::Root::IOManager;
+
+use Bio::Root::Global     qw(:devel $CGI $TIMEOUT_SECS);
+use Bio::Root::Object     ();
+use Bio::Root::Utilities  qw(:obj);
+use FileHandle            ();
+
+@ISA   = qw(Bio::Root::Object);
+
+use strict;
+use vars qw($ID $VERSION $revision);
+$ID = 'Bio::Root::IOManager';
+$VERSION = 0.043;
+
+## POD Documentation:
+
+=head1 NAME
+
+Bio::Root::IOManager - Input and output manager for Perl5 objects.
+
+=head1 SYNOPSIS
+
+=head2 Object Creation
+
+The creation of Bio::Root::IOManager.pm objects is handled by Bio::Root::Object.pm
+which delegates various I/O tasks to this module.
+
+    use Bio::Root::IOManager;
+
+    $myIO = new Bio::Root::IOManager(-WHERE   =>'/usr/tmp/data.out',
+   				     -PARENT =>$self);
+
+
+=head1 INSTALLATION
+
+This module is included with the central Bioperl distribution:
+
+   http://bio.perl.org/Core/Latest
+   ftp://bio.perl.org/pub/DIST
+
+Follow the installation instructions included in the README file.
+
+
+=head1 DESCRIPTION
+
+This module encapsulates the data and methods necessary for regulating
+input/output (I/O) of data from Perl objects.
+It is concerned with "where" to get input or send output as opposed to "what" to get.
+IOManager.pm is intended to consolidate various I/O issues for
+Perl objects and provide an object-oriented way to do I/O things such as:
+
+=over 4
+
+=item * passing filehandles between objects,
+
+=item * opening and reading input from files or STDIN,
+
+=item * routine file management (compressing, uncompressing, and deleting).
+
+=back
+
+Subclasses of B<Bio::Root::Object.pm> have access to all methods defined in
+IOManager.pm since B<Bio::Root::Object.pm> employs Bio::Root::IOManager.pm
+by a delegation mechanism.
+
+It is not clear yet how much objects really need to do the fancy I/O gymnastics as
+supported by IOManager. Most of the time, objects simply send output to STDOUT
+which is managed at the script/program level. The fancy I/O manipulations are
+considered experimental and have not been adequately tested or utilized.
+I'm not really satisfied with the current L<display()|display>/L<set_display()|set_display> strategy.
+The additional functionality is not often utilized in typical
+applications. Is the extra complexity worth it?
+
+B<The API for this module is under development.>
+
+
+=head2 Generic Data Access & Manipulation
+
+The L<read()|read> method provided permits the following:
+
+=over 4
+
+=item * read from a file or STDIN.
+
+=item * read a single record or a stream containing multiple records.
+
+=item * specify a record separator.
+
+=item * store all input data in memory or process the data stream as it is being read.
+
+=back
+
+=head1 DEPENDENCIES
+
+Bio::Root::IOManager.pm inherits from B<Bio::Root::Object.pm> and uses B<FileHandle.pm>.
+B<Bio::Root::Utilities.pm> is also used for routine file manipulations
+compression/uncompression/deletion.
+
+=head1 SEE ALSO
+
+  Bio::Root::Object.pm       - Core object
+  Bio::Root::Utilities.pm    - Generic utilty object
+  Bio::Root::Global.pm       - Manages global variables/constants
+
+  http://bio.perl.org/Projects/modules.html  - Online module documentation
+  http://bio.perl.org/                       - Bioperl Project Homepage
+
+ FileHandle.pm (included in the Perl distribution or CPAN).
+
+=head1 TODO
+
+Experiment with using the newer B<IO.pm> included in the Perl distribution,
+instead of FileHandle.pm.
+
+=head1 FEEDBACK
+
+=head2 Mailing Lists
+
+User feedback is an integral part of the evolution of this and other Bioperl modules.
+Send your comments and suggestions preferably to one of the Bioperl mailing lists.
+Your participation is much appreciated.
+
+  bioperl-l@bioperl.org             - General discussion
+  http://bioperl.org/MailList.shtml - About the mailing lists
+
+=head2 Reporting Bugs
+
+Report bugs to the Bioperl bug tracking system to help us keep track the bugs and
+their resolution. Bug reports can be submitted via email or the web:
+
+    bioperl-bugs@bio.perl.org
+    http://bugzilla.bioperl.org/
+
+=head1 AUTHOR 
+
+Steve Chervitz E<lt>sac@bioperl.orgE<gt>
+
+See L<the FEEDBACK section | FEEDBACK> for where to send bug reports and comments.
+
+=head1 VERSION
+
+Bio::Root::IOManager.pm, 0.043
+
+=head1 ACKNOWLEDGEMENTS
+
+This module was developed under the auspices of the Saccharomyces Genome
+Database:
+    http://genome-www.stanford.edu/Saccharomyces
+
+=head1 COPYRIGHT
+
+Copyright (c) 1997-98 Steve Chervitz. All Rights Reserved.
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
+
+#
+##
+###
+#### END of main POD documentation.
+###
+##
+#'
+
+
+=head1 APPENDIX
+
+Methods beginning with a leading underscore are considered private
+and are intended for internal use by this module. They are
+B<not> considered part of the public interface and are described here
+for documentation purposes only.
+
+=cut
+
+
+
+#####################################################################################
+##                                 CONSTRUCTOR                                     ##
+#####################################################################################
+
+
+## Using default constructor and destructor inherited from Bio::Root::Object.pm
+
+## Could perhaps set the file data member.
+
+
+#####################################################################################
+##                                 ACCESSORS                                       ##
+#####################################################################################
+
+
+=head2 file
+
+ Usage     : $object->file([filename]);
+ Purpose   : Set/Get name of a file associated with an object.
+ Example   : $object->file('/usr/home/me/data.txt');
+ Returns   : String (full path name)
+ Argument  : String (full path name) OR a FileHandle or TypeGlob reference
+           : (argument only required for setting)
+ Throws    : Exception if the file appears to be empty or non-existent
+ Comments  : File can be text or binary.
+
+See Also   : L<compress_file()|compress_file>, L<uncompress_file()|uncompress_file>, L<delete_file()|delete_file>
+
+=cut
+
+#--------
+sub file {
+#--------
+    my $self = shift;
+    if($_[0]) {
+	my $file = $_[0];
+	if(not ref $file and not -s $file) {
+	    $self->throw("File is empty or non-existent: $file");
+	}	
+	$self->{'_file'} = $file;
+    }
+    $self->{'_file'};
+}
+
+
+
+=head2 set_fh
+
+ Usage     : $self->set_fh( named_parameters )
+ Purpose   : Sets various FileHandle data members ('fh', 'fherr').
+           : Provides a public interface for _open_fh().
+ Returns   : n/a
+ Argument  : Named parameters:  (TAGS CAN BE UPPER OR LOWER CASE)
+           :   -PATH  => string (filename) or a FileHandle object ref.
+           :   -PRE   => string, prefix for opening (e.g., '>', '>>').
+           :   -POST  => string, postfix for opening (e.g., '|'), for commands.
+           :   -WHICH => string, 'err' for setting output path for errors.
+           :
+ Throws    : Exception propagated from _open_fh()
+ Examples  : $self->set_fh();                   # Create anonymous FileHandle object
+           : $self->set_fh(-PATH =>'fileName',  # Open for writing
+	   :		   -PRE =>'>');
+           : $self->set_fh(-PATH =>'fileName',  # Open error log file in append mode.
+	   :		   -PRE  =>'>>',
+	   :		   -WHICH =>'err');
+           : $self->set_fh(-PATH =>$obj->fh()); # Copy a file handle from another object.
+           :
+ Comments  : set_read() and set_display() provide
+           : interfaces for set_fh().
+ Status    : Experimental
+
+See also   : L<set_read()|set_read>, L<set_display()|set_display>.
+
+=cut
+
+#-----------
+sub set_fh {
+#-----------
+    my( $self, %param) = @_;
+
+    no strict 'subs';
+    my( $path, $prefix, $postfix, $which) =
+	$self->_rearrange([PATH,PRE,POST,WHICH],%param);
+    use strict 'subs';
+    $prefix  ||= '';
+    $postfix ||= '';
+    $which   ||= '';
+    my $fullpath = "$prefix$path$postfix";
+    my($fh);
+
+    $DEBUG and print STDERR "set_fh($fullpath) for ${\$self->name()}\n";
+
+    if($which eq 'err') {
+	if(ref($path) =~ /FileHandle|GLOB/ ) {
+	    $fh = $path;
+	} else {
+	    if(defined $self->{'_fherr'}) { $self->_close_fh('err');}
+	    if( not $fh = $self->_open_fh("$fullpath")) {
+		$fh = $self->_open_fh("errors.$$");
+		$fh || return;
+		$self->warn("Couldn't set error output to $fullpath",
+			    "Set to file errors.$$");
+	    }
+	}
+	$self->{'_fherr_name'} = $fullpath;
+	$self->{'_fherr'} = $fh;
+
+    } else {
+	if(ref($path) =~ /FileHandle|GLOB/ ) {
+	    $fh = $path;
+	} else {
+	    if(defined $self->{'_fh'}) { $self->_close_fh();}
+	    if( not $fh = $self->_open_fh("$fullpath")) {
+		$fh = $self->_open_fh("out.$$");
+		$fh || return;
+		$self->warn("Couldn't set output to $fullpath",
+			    "Set to file out.$$");
+	    }
+	}
+	$self->{'_fh_name'} = $fullpath;
+	$self->{'_fh'} = $fh;
+	$DEBUG && print STDERR "$ID: set fh to: $fh";
+    }
+}
+
+
+
+#=head2 _open_fh
+#
+# Purpose   : Creates a new FileHandle object and returns it.
+#           : This method can be used when you need to
+#           : pass FileHandles between objects.
+# Returns   : The new FileHandle object.
+# Throws    : Exception: if the call to new FileHandle fails.
+# Examples  : $self->_open_fh();            # Create anonymous FileHandle object
+#           : $self->_open_fh('fileName');  # Open for reading
+#           : $self->_open_fh('>fileName'); # Open for writing
+# Status    : Experimental
+#
+#See also   : L<set_fh()|set_fh>, L<fh()|fh>, L<set_read()|set_read>, L<set_display()|set_display>
+#
+#=cut
+
+#-------------
+sub _open_fh {
+#-------------
+    my( $self, $arg) = @_;
+    my( $filehandle);
+
+    $DEBUG and print STDERR "_open_fh() $arg\n";
+
+    $filehandle = new FileHandle $arg;
+
+#    if($arg =~ /STD[IO]/) {
+#	$filehandle = new FileHandle;
+#	$filehandle = *$arg;
+#    } else {
+#	 $filehandle = new FileHandle $arg;
+#    }
+
+    (ref $filehandle) || $self->throw("Can't create new FileHandle $arg",
+				      "Cause: $!");
+    return $filehandle;
+}
+
+
+
+#=head2 _close_fh
+#
+# Purpose   : Destroy a FileHandle object.
+# Returns   : n/a
+# Status    : Experimental
+#
+#See also   : L<_open_fh()|_open_fh>, L<set_fh()|set_fh>
+#
+#=cut
+
+#--------------
+sub _close_fh {
+#--------------
+    my( $self, $arg) = @_;
+    $arg ||= '';
+    if($arg eq 'err') {
+	close $self->{'_fherr'};
+	undef $self->{'_fherr'};
+    } else {
+	close $self->{'_fh'};
+	undef $self->{'_fh'};
+    }
+}	
+
+
+=head2 set_display
+
+ Usage     : $self->set_display([-WHERE=>'path'],
+	   :			[-SHOW =>'what is to be displayed'],
+	   :			[-MODE =>'file open mode'])
+ Purpose   : Sets a new FileHandle object for output.
+           : - Sets the objects 'show' data member to 'default' if it is not defined.
+           : - Is a wrapper for setting an object's STDOUT filehandle:
+           :   Checks the -WHERE parameter and the status of the object's current
+           :   filehandle {'_fh'} and does one of three things:
+           :    1. If $param{-WHERE} is defined and is not 'STDOUT', it is sent to
+           :       set_fh() to open a new fh,
+           :    2. else, if 'fh' has already been defined, it is returned,
+           :    3. else, if where equals 'STDOUT', \*STDOUT is returned.
+           :    4. else, \*STDOUT is returned.
+           :
+           : Thus, if an object has already set its 'fh' to some location,
+           : it can still print to 'STDOUT' by explicitly passing -WHERE='STDOUT'
+           : to display().
+           :
+ Arguments : Named parameters: (TAGS CAN BE UPPER OR LOWER CASE).
+           : (all are optional).
+           :    -WHERE => full path name of file to write to or 'STDOUT'.
+           :    -SHOW  => what data is to be displayed. Becomes $self->{'_show'}
+           :                     Default = 'default'. This results in a call to
+           :                     _display_stats() method when display() is called
+           :    -MODE  => mode for opening file. Default is overwrite '>'.
+           :
+ Returns   : FileHandle object reference or typglob reference (\*STDOUT).
+ Throws    : Exception propagated from set_fh().
+ Example   : $self->set_display();
+           : $self->set_display(-WHERE=>'./data.out');
+           : $self->set_display(-WHERE=>$obj->fh());
+ Status    : Experimental
+ Comments  : I'm not satisfied with the current display()/set_display() strategy.
+
+See also   : L<display()|display>, L<set_fh()|set_fh>
+
+=cut
+
+#----------------'
+sub set_display {
+#----------------
+    my( $self, @param ) = @_;
+    my ($show, $where, $mode) = $self->_rearrange([qw(SHOW WHERE MODE)], @param);
+
+    ## Default mode: overwrite any existing file.
+    $mode  ||= '>';
+    $where ||= 'STDOUT';
+
+    $self->{'_show'} = ($show || 'default');
+
+    $DEBUG and print STDERR "$ID set_display() show: $self->{'_show'}\twhere: -->$where<--\n";
+
+    if( defined $where and $where !~ /STDOUT/) {
+#	print "setting file handle object\n";
+	$self->set_fh(-PATH =>$where,
+		      -PRE  =>$mode);
+    } elsif( not defined $self->{'_fh'} or $where =~ /STDOUT/)  {	
+	return \*STDOUT;
+    } else  {
+#	print STDERR "filehandle already set for this object: ${\$self->fh('name')}\n";
+    }
+
+    return $self->{'_fh'};
+}
+
+
+
+=head2 set_read
+
+ Purpose   : Sets a new FileHandle object for input.
+           : Same logic as set_display() but creates filehandle for read only.
+ Returns   : The input FileHandle object or \*STDIN.
+ Arguments : Named parameters: (TAGS CAN BE UPPER OR LOWER CASE).
+           :    $param{-WHERE} = full path name of file to write to.
+ Access    : Public
+ Status    : Experimental, Deprecated
+           :
+ WARNING   : THIS METHOD HAS NOT BEEN TESTED AND IS LIKELY UNNECESSARY.
+           : USE THE read() METHOD INSTEAD.
+           :
+           : Note also that set_read() uses the same data member as set_display()
+           : so it is currently not possible to simultaneously have
+           : different displaying and reading filehandles. This degree of
+           : I/O control has not been necessary.
+
+See also   : L<read()|read>, L<set_display()|set_display>
+
+=cut
+
+#-------------
+sub set_read {
+#-------------
+    my( $self, @param ) = @_;
+    my ($where, $mode) = $self->_rearrange([qw(WHERE MODE)], @param);
+
+    ## Default mode: read only.
+    $mode  ||= '<';
+    $where ||= 'STDIN';
+
+    if( ref($where) and $where !~ /STDIN/) {
+#	print "setting file handle object\n";
+	$self->set_fh(-PATH =>$where,
+		      -PRE  =>$mode);
+    } elsif( not defined $self->{'_fh'} or $where =~ /STDIN/)  {	
+	return \*STDIN;
+    } else  {
+#	print STDERR "filehandle already set for this object: ${\$self->fh('name')}\n";
+    }
+
+    return $self->{'_fh'};
+}
+
+
+
+=head2 set_display_err
+
+ Purpose   : Sets a new FileHandle object for outputing error information.
+           : Same logic as set_display() but creates a filehandle in
+           : append mode.
+ Returns   : The output FileHandle object for saving errors or \*STDERR.
+ Status    : Experimental
+ WARNING   : NOT TESTED
+
+See also   : L<set_display()|set_display>, L<set_read()|set_read>
+
+=cut
+
+#--------------------
+sub set_display_err {
+#--------------------
+    my( $self, @param ) = @_;
+    my ($where, $mode) = $self->_rearrange([qw(WHERE MODE)], @param);
+
+    ## Default mode: read only.
+    $mode  ||= '>>';
+    $where ||= 'STDERR';
+
+    $DEBUG and print STDERR "set_display_err() object: ${\$self->name()}\n";
+
+    if( ref($where) and $where !~ /STDERR/) {
+#	print "setting file handle object\n";
+	$self->set_fh(-PATH =>$where,
+		      -PRE  =>$mode);
+    } elsif( not defined $self->{'_fherr'} or $where =~ /STDERR/)  {	
+	return \*STDERR;
+    } else  {
+#	print STDERR "filehandle already set for this object: ${\$self->fh('name')}\n";
+    }
+
+    return $self->{'_fherr'};
+}
+
+
+#####################################
+#    GET ACCESSORS
+#####################################
+
+
+=head2 show
+
+ Usage     : $self->show()
+ Purpose   : Get the string used to specify what to display
+           : using the display() method.
+ Returns   : String or undef if no show data member is defined.
+ Arguments : n/a
+
+See also   : L<set_display()|set_display>
+
+=cut
+
+#----------
+sub show { my $self= shift; $self->{'_show'}; }
+#----------
+
+
+
+=head2 fh
+
+ Usage     : $object->fh(['name'])
+ Purpose   : Accessor for an object's FileHandle object or the argument used
+           : to create that object.
+ Returns   : One of the following:
+           :   1. The arguments used when the filehandle was created ('fh_name').
+           :   2. The FileHandle object reference previously assigned to $self->{'_fh'}.
+           :   3. Typeglob reference \*STDIN,  \*STDOUT or \*STDERR.
+ Example   : $self->fh();          # returns filehandle for the STDIN/STDOUT path.
+           : $self->fh('err');     # returns filehandle for the err file.
+           : $self->fh('name');    # returns fh creation arguments.
+           : $self->fh('errname'); # returns fh creation arguments for the err file.
+ Status    : Experimental
+
+See also   : L<set_display()|set_display>, L<set_read()|set_read>, L<set_fh()|set_fh>, L<set_display_err()|set_display_err>
+
+=cut
+
+#--------'
+sub fh {
+#--------
+    my( $self, $type, $stream) = @_;
+    $stream ||= 'out';
+    $stream = ($stream eq 'in') ? \*STDIN : \*STDOUT;
+
+    ## Problem: Without named parameters, how do you know if
+    ## a single argument is to be assigned to $type or $stream?
+    ## Function prototypes could be used, or separate methods:
+    ## fh_out(), fh_in(), fh_err().
+    $type or return ($self->{'_fh'} || $stream);
+
+    if( $type =~ /name/){
+	if($type =~ /err/ ) { return $self->{'_fherr_name'}; }
+	else                { return $self->{'_fh_name'}; }
+
+    } else {
+	if($type =~ /err/ ) { return ($self->{'_fherr'} || \*STDERR); }
+	else                { return ($self->{'_fh'}    || $stream); }
+    }
+}
+
+
+#####################################################################################
+##                             INSTANCE METHODS                                    ##
+#####################################################################################
+
+
+##
+##  INPUT METHODS:
+##
+
+
+=head2 read
+
+ Usage     : $object->read(<named parameters>);
+ Purpose   : Read raw textual data from a file or STDIN.
+           : Optionally process each record it as it is read.
+ Example   : $data = $object->read(-FILE    =>'usr/people/me/data.txt',
+	   :			   -REC_SEP =>"\n:",
+	   :			   -FUNC    =>\&process_rec);
+           : $data = $object->read(-FILE  =>\*FILEHANDLE);
+           : $data = $object->read(-FILE  =>new FileHandle $file, 'r');
+           :
+ Argument  : Named parameters: (TAGS CAN BE UPPER OR LOWER CASE)
+           :  (all optional)
+           :    -FILE    => string (full path to file) or a reference
+           :                to a FileHandle object or typeglob. This is an
+           :                optional parameter (if not defined, STDIN is used).
+           :    -REC_SEP => record separator to be used
+           :                when reading in raw data. If none is supplied,
+           :                the default record separator is used ($/).
+           :                $/ is localized to this method but be careful if
+           :                you do any additional file reading in functions
+           :                called by this method (see the -FUNC parameter).
+           :                Such methods will use the value of $/ set
+           :                by read() (if a -RE_SEP is supplied).
+           :    -FUNC    => reference to a function to be called for each
+           :                record. The return value of this function is now checked:
+           :                if false, the reading is terminated.
+           :                Typically -FUNC supplies a closure.
+           :    -HANDLE  => reference to a FileHandle object or a
+           :                typeglob to be use for reading input.
+           :                The FileHandle object should be configured to
+           :                read from a desired file before calling this
+           :                method. If both -handle and -file are defined,
+           :                -handle takes precedence.
+           :                (The -HANDLE parameter is no longer necessary
+           :                 since -FILE can now contain a FileHandle ref.)
+           :    -WAIT    => integer (number of seconds to wait for input
+           :                before timing out. Default = 20 seconds).
+           :
+ Returns   : string, array, or undef depending on the arguments.
+           : If a function reference is supplied, this function will be
+           : called using the contents of each record as it is read in.
+           : If no function reference is supplied, the data are returned as a
+           : string in scalar context or as a list in array context.
+           : The data are not altered; blank lines are not removed.
+           :
+ Throws    : Exception if no input is read from source.
+           : Exception if no input is read within WAIT seconds.
+           : Exception if FUNC is not a function reference.
+           : Propagates any exceptions thrown by create_filehandle()
+           :
+ Comments  : Gets the file name from the current file data member.
+           : If no file has been defined, this method will attempt to
+           : read from STDIN.
+           :
+           : COMPRESSED FILES:
+           :    read() will attempt to use gzip -cd to read the file
+           : if it appears to be compressed (binary file test).
+           :
+           : If the raw data is to be returned, wantarray is used to
+           : determine how the data are to be returned (list or string).
+           :
+           : Sets the file data member to be the supplied file name.
+           : (if any is supplied).
+
+           : The read() method is a fairly new implementation
+           : and uses a different approach than display().
+           : For example, set_read() is not used.
+
+ Bugs      : The following error is generated by Perl's FileHandle.pm module
+           : when using the -w switch. It can be ignored for now:
+  "Close on unopened file <GEN0> at /tools/perl/5.003/lib/FileHandle.pm line 255."
+
+See Also   : L<file()|file>, L<Bio::Root::Utilities::create_filehandle()|Bio::Root::Utilities>
+
+=cut
+
+#----------'
+sub read {
+#----------
+    my($self, @param) = @_;
+    my( $rec_sep, $func_ref, $wait ) =
+	$self->_rearrange([qw( REC_SEP FUNC WAIT)], @param);
+
+    my $fmt = (wantarray ? 'list' : 'string');
+    $wait ||= $TIMEOUT_SECS;  # seconds to wait before timing out.
+
+    my $FH = $Util->create_filehandle( -client => $self, @param);
+
+    # Set the record separator (if necessary) using dynamic scope.
+    my $prev_rec_sep;
+    $prev_rec_sep = $/  if scalar $rec_sep;  # save the previous rec_sep
+    local $/ = $rec_sep if scalar $rec_sep;
+
+    # Verify that we have a proper reference to a function.
+    if($func_ref) {
+	if(not ref($func_ref) =~ /CODE/) {
+	    $self->throw("Not a function reference: $func_ref, ${\ref $func_ref}");
+	}
+    }
+
+    $DEBUG && printf STDERR "$ID: read(): rec_sep = %s; func = %s\n",$/, ($func_ref?'defined':'none');
+
+    my($data, $lines, $alarm_available);
+
+    $alarm_available = 1;
+
+    eval {
+        alarm(0);
+    };
+    if($@) {
+        # alarm() not available (ActiveState perl for win32 doesn't have it.
+        # See jitterbug PR#98)
+        $alarm_available = 0;
+    }
+
+    $SIG{ALRM} = sub { die "Timed out!"; };
+
+    eval {
+        $alarm_available and alarm($wait);
+
+      READ_LOOP:
+	while(<$FH>) {
+	    # Default behavior: read all lines.
+	    # If &$func_ref returns false, exit this while loop.
+	    # Uncomment to skip lines with only white space or record separators
+#	    next if m@^(\s*|$/*)$@;
+	
+	    $lines++;
+            $alarm_available and alarm(0);  # Deactivate the alarm as soon as we start reading.
+	    my($result);
+	    if($func_ref) {
+		# Need to reset $/ for any called function.
+		local $/ = $prev_rec_sep if defined $prev_rec_sep;
+		$result = &$func_ref($_) or last READ_LOOP;
+	    } else {
+		$data .= $_;
+	    }
+	}
+    };
+    if($@ =~ /Timed out!/) {
+	 $self->throw("Timed out while waiting for input from $self->{'_input_type'}.", "Timeout period = $wait seconds.\nFor a longer time out period, supply a -wait => <seconds> parameter\n".
+		     "or edit \$TIMEOUT_SECS in Bio::Root::Global.pm.");
+    } elsif($@ =~ /\S/) {
+        my $err = $@;
+        $self->throw("Unexpected error during read: $err");
+    }
+
+    close ($FH) unless $self->{'_input_type'} eq 'STDIN';
+
+    if($data) {
+	$DEBUG && do{
+	    print STDERR "$ID: $lines records read.\nReturning $fmt.\n" };
+
+	return ($fmt eq 'list') ? split("$/", $data) : $data;
+
+    } elsif(not $func_ref) {
+	$self->throw("No data input from $self->{'_input_type'}");
+    }
+    delete $self->{'_input_type'};
+    undef;
+}
+
+
+##
+##  OUTPUT METHODS:
+##
+
+
+=head2 display
+
+ Usage     : $self->set_display(named parameters)
+ Purpose   : Provides a default display method which calls set_display()
+           : and also invokes methods to display an object's stats
+           : if necessary ( _print_stats_header() and _displayStats() ).
+ Returns   : True (1).
+ Throws    : Propagates any exceptions thrown by set_display().
+ Arguments : Named parameters for set_display().
+ Comments  : I'm not satisfied with the current display()/set_display() strategy.
+
+See also   : L<set_display()|set_display>
+
+=cut
+
+#-------------
+sub display {
+#-------------
+    my( $self, %param ) = @_;
+
+    $DEBUG && print STDERR "$ID display for ${\ref($self)}\n";
+
+    my $OUT = $self->set_display(%param);
+#    my $OUT = $self->set_display( %param );
+#    print "$ID: OUT = $OUT";<STDIN>;
+
+    $DEBUG && do{ print STDERR "display(): WHERE = $OUT;\nSHOW = $self->{'_show'}";<STDIN>;};
+
+    if($self->{'_show'} =~ /stats|default/i) {
+	if($param{-HEADER}) {
+	    $self->_print_stats_header($OUT);
+	}
+	$self->parent->_display_stats($OUT);
+    }
+    1;
+}
+
+
+
+=head2 _print_stats_header
+
+ Usage     : n/a; internal method.
+           : $obj->_print_stats_header(filehandle);
+ Purpose   : Prints a header containing basic info about the object
+           : such as the class and name of the object followed by a
+           : line of hyphens.
+ Status    : Experimental
+
+=cut
+
+#------------------------
+sub _print_stats_header {
+#------------------------
+    my($self, $OUT) = @_;
+
+    printf $OUT "\nSTATS FOR %s \"%s\"\n",ref($self->parent),$self->parent->name();
+    printf $OUT "%s\n", '-'x60;
+}
+
+
+
+
+##
+##  FILE MANIPULATION METHODS:
+##
+
+
+
+=head2 file_date
+
+ Usage     : $object->file_date( %named_parameters);
+ Purpose   : Get the last modified date of a file.
+ Example   : $object->file_date();
+           : $object->file_date(-FMT =>'yyyy-mmm-dd',
+				-FILE =>'/usr/people/me/data.txt');
+           : $object->file_date(-FMT =>'yyyy-mmm-dd');
+ Returns   : String (date)
+ Argument  : Named parameters:  (TAGS CAN BE UPPER OR LOWER CASE)
+           :   -FILE  => string (filename full path)
+           :   -FMT   => string (format for the returned date string)
+           :
+ Throws    : Exception if no file is specified or the file is non-existent
+           : (Propagated from Utilities::file_date())
+ Comments  : File can be text or binary.
+
+See Also   : L<file()|file>, L<Bio::Root::Utilities::file_date()|Bio::Root::Utilities>
+
+=cut
+
+#---------------
+sub file_date {
+#---------------
+    my ($self, @param) = @_;
+    my ($file, $fmt) = $self->_rearrange([qw(FILE FMT)], @param);
+
+    if(not $file ||= $self->{'_file'}) {
+	$self->throw("Can't get file date: no file specified");
+    }
+    $fmt ||= '';
+    $Util->file_date($file, $fmt);
+}
+
+
+
+=head2 compress_file
+
+ Usage     : $object->compress_file([filename]);
+ Purpose   : Compresses a file if not already compressed.
+           : Compresses to a temorary file if user is not owner of supplied file.
+ Example   : $object->file('/usr/home/me/data.txt');
+           : $object->compress_file();
+ Argument  : String (full path name) (optional).
+           : If no argument is provided, the file data member is used.
+ Returns   : String (compressed file name, full path).
+           : Sets the file data member to the compressed name
+           : when not operating on a file supplied as an argument.
+           : Returns false (undef) if the file is already compressed
+           : (binary test).
+ Throws    : Exception if no file is specified.
+           : Propagates any exception thrown by Bio::Root::Utilities::compress()
+           : if the file cannot be compressed().
+           : Tests if file is already compressed to avoid trivial error due to
+           : the file already being compressed.
+           :
+ Comments  : Relies on the compress() method of Bio::Root::Utilities.pm
+           : to implement the file compression functionality.
+           : (Currently, Bio::Root::Utilities::compress() uses gzip.)
+           :
+           : If the user is not the owner of the file, the file is
+           : compressed to a tmp file.
+           :
+           : All file compressing/uncompressing requests should go through
+           : compress_file()/uncompress_file(). This serves to confine the
+           : dependency between IOManager.pm module and Utilities.pm
+           : which helps maintainability.
+           :
+ Bugs      : Only compresses text files. This obviates a dependency on
+           : particular file suffixes but is not good if you
+           : want to compress a binary file.
+           :
+           : May not be taint-safe.
+
+See Also   : L<uncompress_file()|uncompress_file>, L<file()|file>, L<Bio::Root::Utilities::compress()|Bio::Root::Utilities>
+
+=cut
+
+#-----------------
+sub compress_file {
+#-----------------
+    my ($self, $file) = @_;
+    my $myfile = 0;
+
+    if(!$file) {
+	$file = $self->{'_file'};
+	$myfile = 1;
+    }
+
+    $file or $self->throw("Can't compress data file: no file specified");
+
+    #printf STDERR "$ID: Compressing data file for %s\n  $file\n",$self->name();
+
+    my ($newfile);
+    if (-T $file) {
+	$newfile = -o $file ? $Util->compress($file) : $Util->compress($file, 1);
+	# set the current file to the new name.
+	$self->file($newfile) if $myfile;
+    }
+    $newfile;
+}
+
+
+
+=head2 uncompress_file
+
+ Usage     : $object->uncompress_file([filename]);
+ Purpose   : Uncompresses the file containing the raw report.
+           : Uncompresses to a temorary file if user is not owner of supplied file.
+ Example   : $object->file('/usr/home/me/data.txt.gz');
+           : $object->uncompress_file();
+ Argument  : String (full path name) (optional).
+           : If no argument is provided, the file data member is used.
+ Returns   : String (uncompressed file name, full path).
+           : Sets the file data member to the uncompressed name
+           : when not operating on a file supplied as an argument.
+           : Returns false (undef) if the file is already uncompressed.
+           :
+ Throws    : Exception if no file is specified.
+           : Propagates any exception thrown by Bio::Root::Utilities::compress()
+           : if the file cannot be uncompressed().
+           : Tests if file is already uncompressed to avoid trivial error due to
+           : the file already being uncompressed.
+ Comments  : See comments for compress_file(). They apply here as well.
+           :
+ Bugs      : Considers all binary files to be compressed. This obviates
+           : a dependency on particular file suffixes.
+           : May not be taint safe.
+
+See Also   : L<compress_file()|compress_file>, L<file()|file>, L<Bio::Root::Utilities::uncompress()|Bio::Root::Utilities>
+
+=cut
+
+#--------------------
+sub uncompress_file {
+#--------------------
+    my ($self, $file) = @_;
+    my $myfile = 0;
+
+    if(!$file) {
+	$file = $self->{'_file'};
+	$myfile = 1;
+    }
+
+    $file or $self->throw("Can't compress file: no file specified");
+
+    #printf STDERR "$ID: Uncompressing data file for %s\n  $file",$self->name();
+
+    my ($newfile);
+    if (-B $file) {
+	$newfile = -o $file ? $Util->uncompress($file) : $Util->uncompress($file, 1);
+	# set the current file to the new name & return it.
+	$self->file($newfile) if $myfile;
+    }
+    $newfile;
+}
+
+
+=head2 delete_file
+
+ Usage     : $object->delete_file([filename]);
+ Purpose   : Delete a file.
+ Example   : $object->delete_file('/usr/people/me/data.txt');
+ Returns   : String (name of file which was deleted) if successful,
+           : undef if file does not exist.
+           : Sets the file data member to undef
+           : when not operating on a file supplied as an argument.
+ Argument  : String (full path name) (optional).
+           : If no argument is provided, the file data member is used.
+ Throws    : Exception if the user is not the owner of the file.
+           : Propagates any exception thrown by Bio::Root::Utilities::delete().
+           : if the file cannot be deleted.
+ Comments  : Be careful with this method: there is no undelete().
+           : Relies on the delete() method provided by Bio::Root::Utilities.pm
+           : to implement the file deletion functionality.
+           : This method is not taint-safe.
+           : It is intended for off-line maintenance use only.
+
+See Also   : L<file()|file>, L<Bio::Root::Utilities::delete()|Bio::Root::Utilities>
+
+=cut
+
+#-----------------
+sub delete_file {
+#-----------------
+    my ($self, $file) = @_;
+    my $myfile = 0;
+
+    if(!$file) {
+	$file = $self->{'_file'};
+	$myfile = 1;
+    }
+    return undef unless -e $file;
+
+    -o $file or
+	$self->throw("Can't delete file $file: Not owner.");
+
+#    $DEBUG and print STDERR "$ID: Deleting data file for ",$self->name();
+
+    eval{ $Util->delete($file); };
+
+    if(!$@ and $myfile) {
+	$self->{'_file'} = undef;
+    }
+    $file;
+}
+
+
+
+1;
+__END__
+
+#####################################################################################
+#                                  END OF CLASS                                     #
+#####################################################################################
+
+=head1 FOR DEVELOPERS ONLY
+
+=head2 Data Members
+
+Information about the various data members of this module is provided for those
+wishing to modify or understand the code. Two things to bear in mind:
+
+=over 4
+
+=item 1 Do NOT rely on these in any code outside of this module.
+
+All data members are prefixed with an underscore to signify that they are private.
+Always use accessor methods. If the accessor doesn't exist or is inadequate,
+create or modify an accessor (and let me know, too!).
+
+=item 2 This documentation may be incomplete and out of date.
+
+It is easy for this documentation to become obsolete as this module is still evolving.
+Always double check this info and search for members not described here.
+
+=back
+
+An instance of Bio::Root::IOManager.pm is a blessed reference to a hash containing
+all or some of the following fields:
+
+ FIELD          VALUE
+ ------------------------------------------------------------------------
+  _show         Selects display options.
+
+  _fh           FileHandle object for redirecting STDIN or STDOUT.
+
+  _fherr        FileHandle object for error data. Append mode.
+
+  _fh_name      The arguments used to create fh.
+
+  _fherr_name   The arguments used to create fherr.
+
+  INHERITED DATA MEMBERS
+
+  _parent       (From Bio::Root::Object.pm> Object reference for the owner of this IOManager.
+
+=cut
+
+
+MODIFICATION NOTES:
+-------------------
+
+17 Feb 1999, sac:
+   * Using $Global::TIMEOUT_SECS
+
+3 Feb 1999, sac:
+   * Added timeout support to read().
+   * Moved the FileHandle creation code out of read() and into
+     Bio::Root::Utilties since it's of more general use.
+
+ 24 Nov 1998, sac:
+   * Modified read(), compress(), and uncompress() to properly
+     deal with file ownership issues.
+
+ 19 Aug 1998, sac:
+   * Fixed bug in display(), which wasn't returning true (1).
+
+ 0.023, 20 Jul 1998, sac:
+   * read() can now use a supplied FileHandle or GLOB ref (\*IN).
+   * A few other touch-ups in read().
+
+ 0.022, 16 Jun 1998, sac:
+   * read() now terminates reading when a supplied &$func_ref
+     returns false.
+
+ 0.021, May 1998, sac:
+   * Refined documentation to use 5.004 pod2html.
+   * Properly using typglob refs as necessary
+     (e.g., set_display(), set_fh()).
+
+0.031, 2 Sep 1998, sac:
+   * Doc changes only
+
+