Mercurial > repos > mahtabm > ensembl
diff variant_effect_predictor/Bio/Root/Vector.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/Vector.pm Thu Apr 11 02:01:53 2013 -0400 @@ -0,0 +1,1050 @@ +#----------------------------------------------------------------------------- +# PACKAGE : Bio::Root::Vector.pm +# AUTHOR : Steve Chervitz (sac@bioperl.org) +# CREATED : 15 April 1997 +# REVISION: $Id: Vector.pm,v 1.10 2002/10/22 07:38:37 lapp Exp $ +# STATUS : Alpha +# +# WARNING: This is considered an experimental module. +# +# For documentation, run this module through pod2html +# (preferably from Perl v5.004 or better). +# +# MODIFIED: +# sac --- Fri Nov 6 14:24:48 1998 +# * Added destroy() method (experimental). +# 0.023, 20 Jul 1998, sac: +# * Improved memory management (_destroy_master()). +# +# Copyright (c) 1997 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::Vector; + +use Bio::Root::Global qw(:devel); +use Bio::Root::Object (); + +# @ISA = qw(Bio::Root::Object); # Eventually perhaps... + +use vars qw($ID $VERSION); +$ID = 'Bio::Root::Vector'; +$VERSION = 0.04; + +use strict; +my @SORT_BY = ('rank','name'); + +## POD Documentation: + +=head1 NAME + +Bio::Root::Vector - Interface for managing linked lists of Perl5 objects. + +=head1 SYNOPSIS + +=head2 Object Creation + +B<At present, Vector objects cannot be instantiated.> This +package is currently designed to be inherited along with another class +that provides a constructor (e.g., B<Bio::Root::Object.pm>). +The Vector provides a set of methods that can then be used for managing +sets of objects. + +See L<the USAGE section | USAGE>. + +=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 + +Bio::Root::Vector.pm provides an interface for creating and manipulating +dynamic sets (linked lists) of Perl5 objects. This is an abstract class (ie., +there is no constructor) and as such is expected to be inherited along with +some other class (see note above). + +Vectors are handy when, for example, an object may contain one or more +other objects of a certain class. The container object knows only +that is has at least one such object; the multiplex nature of the contained +object is managed by the contained object via its Vector interface. +The methods for adding, removing, counting, listing, and sorting all objects +are bundled together in Vector.pm. + +Thus, the current Bio::Root::Vector class is somewhat of a cross between an +interator and a composite design pattern. At present, a number of classes +utilize Bio::Root::Vector's composite-like behavior to implement a composite +pattern (Bio::SeqManager.pm, for example). +This is not necessarily ideal and is expected to change. + +=head1 USAGE + +For a usage demo of Bio::Root::Vector.pm see the scripts in the +examples/root_object/vector directory. + + +=head1 DEPENDENCIES + +Bio::Root::Vector.pm does not directly inherit from B<Bio::Root::Object.pm> but +creates an manager object which does. + +=head1 BUGS/FEATURES + +By default, all Vectors are doubly-linked lists. This relieves one from +the burden of worrying about whether a given Vector is single- or doubly-linked. +However, when generating lots of Vectors or extremely large vectors, memory +becomes an issue. In particular, signaling the GC to free the memory for +an object when you want to remove it. B<Until this memory issue is resolved, +the use of Vector.pm is not recommended for large projects.> + +Although it is not required, all objects within a vector are expected +to derive from the same class (package). Support for heterogeneous +Vectors has not been explicitly added (but they should work fine, as long +as you know what you're doing). + +=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::Vector.pm, 0.04 + +=head1 TODO + +=over 4 + +=item * (Maybe) create an container class version of this module + +to permit Vectors to be instantiated. Thus, instead of inherited +from both Object.pm and Vector.pm, you could create a Vector.pm object. + +=item * Improve documentation. + +=back + +=head1 SEE ALSO + + Bio::Root::Object.pm - Core object + Bio::Root::Err.pm - Error/Exception 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 + +=head1 ACKNOWLEDGEMENTS + +This module was developed under the auspices of the Saccharomyces Genome +Database: + http://genome-www.stanford.edu/Saccharomyces + +=head1 COPYRIGHT + +Copyright (c) 1996-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 # +######################################################## + +## No constructor. See _set_master() for construction of {Master} data member. + +## Destructor: Use remove_all() or remove(). + +# New Idea for destructor +#------------- +sub destroy { +#------------- + my $self = shift; + local($^W) = 0; + undef $self->{'_prev'}; + undef $self->{'_next'}; + undef $self->{'_rank'}; + undef $self->{'_master'}; +} + +##################################################################################### +## ACCESSORS ## +##################################################################################### + + +=head2 set_rank + + Purpose : To set an object's rank to an arbitrary numeric + : value to be used for sorting the objects of the Vector. + Usage : $self->set_rank(-RANK =>numeric_ranking_data, + : -RANK_BY =>ranking_criterion_string); + : or without the named parameters as (rank, rank_by). + Throws : warning (if rank is set without also setting RANK_BY) + Comments : It is redundant for every object to store RANK_BY data. + : For this reason, the RANK_BY data is stored with the master + : object associated with the vector. + +See Also : L<rank>(), L<rank_by>() + +=cut + +#-------------' +sub set_rank { +#------------- + my( $self, %param) = @_; + + $self->_set_master($self) unless $self->{'_master'}->{'_set'}; + + my($rank, $rank_by) = $self->master->_rearrange([qw(RANK RANK_BY)], %param); + + $DEBUG==1 and do{ print STDERR "$ID:set_rank() = $rank; Criteria: $rank_by."; <STDIN>; }; + + $self->{'_rank'} = ($rank || undef); + $self->{'_master'}->{'_rankBy'} = ($rank_by || undef); + if( defined $self->{'_rank'} and not defined $self->{'_master'}->{'_rankBy'} ) { + return $self->master->warn('Rank defined without ranking criteria.'); + } + 1; +} + +sub _set_rank_by { + my( $self, $arg) = @_; + $self->{'_master'}->{'_rankBy'} = $arg || 'unknown'; +} + +sub _set_master { + ## A vector does not need a master object unless it needs to grow. + my($self,$obj) = @_; + +# print "$ID: _set_master() new Master object for ${\$obj->name}."; <STDIN>; + + require Bio::Root::Object; + my $master = {}; + bless $master, 'Bio::Root::Object'; + + $master->{'_set'} = 1; ## Special member indicating that this method has been called. + ## Necessary since perl will generate an anonymous {Master} + ## hash ref on the fly. This ref will not be blessed however. + $master->{'_first'} = $obj; + $master->{'_last'} = $obj; + $master->{'_size'} = 1; + $master->{'_index'}->{$obj->name()} = $obj; + $self->{'_master'} = $master; + + $self->{'_rank'} = 1; + $self->{'_prev'} = undef; + $self->{'_next'} = undef; +# $self->{'_master'}->{'_rankBy'} = undef; # Default rank is the order of addition to Vector. +} + +sub _destroy_master { +# This is called when the last object in the vector is being remove()d + my $self = shift; + + return if !$self->master or !$self->master->{'_set'}; + + my $master = $self->master; + + ## Get rid of the Vector master object. + ref $master->{'_first'} and (%{$master->{'_first'}} = (), undef $master->{'_first'}); + ref $master->{'_last'} and (%{$master->{'_last'}} = (), undef $master->{'_last'}); + ref $master->{'_index'} and (%{$master->{'_index'}} = (), undef $master->{'_index'}); + %{$master} = (); + undef $master; +} + + +=head2 clone_vector + + Purpose : Call this method to clone the whole vector. + : NOT calling this method will extract the vector element. + Usage : $self->clone_vector(); + Throws : Exception if argument is not an object reference. + Comments : This method is usually called from within a module's + : _set_clone() method for modules that inherit from + : Bio::Root::Vector.pm. + +=cut + +#-----------------' +sub clone_vector { +#----------------- + my($self, $obj) = @_; + + ref($obj) || throw($self, "Can't clone $ID object: Not an object ref ($obj)"); + + $self->{'_prev'} = $obj->{'_prev'}; + $self->{'_next'} = $obj->{'_next'}; + $self->{'_rank'} = $obj->{'_rank'}; + $self->{'_master'} = $obj->{'_master'}; +} + + +=head2 prev + + Purpose : Returns the previous object in the Vector or undef + : if on first object. + Usage : $self->prev + +=cut + +#-------- +sub prev { my $self = shift; $self->{'_prev'}; } +#-------- + + + +=head2 next + + Purpose : Returns the next object in the Vector or undef + : if on last object. + Usage : $self->next + +=cut + +#-------- +sub next { my $self = shift; $self->{'_next'}; } +#-------- + + + +=head2 first + + Purpose : Returns the first object in the Vector or $self + : if Vector size = 1. + Usage : $self->first + +=cut + +#---------- +sub first { +#---------- + my $self = shift; + defined $self->{'_master'} ? $self->{'_master'}->{'_first'} : $self; +} + + +=head2 last + + Purpose : Returns the last object in the Vector or + : $self if Vector size = 1. + Usage : $self->last + +=cut + +#------- +sub last { +#------- + my $self = shift; + defined $self->{'_master'} ? $self->{'_master'}->{'_last'} : $self; +} + + + +=head2 rank + + Purpose : Returns the rank of the current object or 1 + : if rank is not defined. + Usage : $self->rank + +See Also : L<set_rank>() + +=cut + +#--------- +sub rank { my $self = shift; $self->{'_rank'} || 1; } +#--------- + + + +=head2 rank_by + + Purpose : Returns the ranking criterion or the string 'order of addition' + : if rankBy has not been explicitly set. + Usage : $self->rank_by + +See Also : L<set_rank>() + +=cut + +#----------- +sub rank_by { +#----------- + my $self = shift; + defined $self->{'_master'} ? ($self->{'_master'}->{'_rankBy'}||'order of addition') + : 'unranked'; +} + + + +=head2 size + + Purpose : Returns the number of objects currently in the Vector. + Usage : $self->size + +=cut + +#--------- +sub size { +#--------- + my $self = shift; + defined $self->{'_master'} ? $self->{'_master'}->{'_size'} : 1; +} + + +=head2 master + + Purpose : Returns the master object associated with the Vector. + : (should probably be a private method). + Usage : $self->master + +=cut + +#----------- +sub master { my $self = shift; $self->{'_master'}; } +#----------- + + +## Not sure what these potentially dangerous methods are used for. +## Should be unnecessary and probably can be removed. +sub set_prev { my($self,$obj) = @_; $self->{'_prev'} = $obj; } +sub set_next { my($self,$obj) = @_; $self->{'_next'} = $obj; } + +############################################################################# +# INSTANCE METHODS ## +############################################################################# + + +=head2 is_first + + Purpose : Test whether the current object is the first in the Vector. + Usage : $self->is_first + +=cut + +#------------ +sub is_first { my($self) = shift; return not defined $self->{'_prev'}; } +#------------ + + +=head2 is_last + + Purpose : Test whether the current object is the last in the Vector. + Usage : $self->is_last + +=cut + +#------------ +sub is_last { my($self) = shift; return not defined $self->{'_next'}; } +#------------ + + + + +=head2 get + + Purpose : Retrives an object from the Vector given its name. + : Returns undef if the object cannot be found. + Usage : $self->get(object_name) + Examples : $self->get($obj->name) + +See Also : L<list>() + +=cut + +#-------- +sub get { +#-------- + my($self,$name) = @_; + + my ($obj); +# print "$ID get(): getting $name\n"; + + if($self->{'_master'}->{'_set'}) { +# my @names = keys %{$self->{'_master'}->{'_index'}}; +# print "$ID: names in hash:\n@names";<STDIN>; +# print " returning $self->{'_master'}->{'_index'}->{$name}\n"; + local($^W) = 0; + $obj = $self->{'_master'}->{'_index'}->{$name}; + } + + elsif($self->name =~ /$name/i) { +# print " returning self\n"; + $obj = $self; + } + + if(not ref $obj) { + $self->throw("Can't get object named \"$name\": object not set or name undefined."); + } + $obj; +} + +## Former strategy: hunt through the list for the object. +## No longer needed since master indexes all objects. +# do{ +# if($obj->name eq $name) { return $obj; } +# +# } while($obj = $current->prev()); + + + + +=head2 add + + Purpose : Add an object to the end of a Vector. + Usage : $self->add(object_reference) + +See also : L<insert>(), L<remove>() + +=cut + +#-------- +sub add { +#-------- + my($self,$new,$index) = @_; + + $self->_set_master($self) unless $self->{'_master'}->{'_set'}; + +# print "\n\nADDING TO VECTOR ${\ref $self} ${\$self->name}\nFOR PARENT: ${\ref $self->parent} ${\$self->parent->name}\n\n"; + + $self->{'_next'} = $new; + $new->{'_prev'} = $self; + $self->{'_master'}->{'_last'} = $new; + $self->{'_master'}->{'_size'}++; + $new->{'_master'} = $self->{'_master'}; + $new->_incrementRank(); + $new->Bio::Root::Vector::_index(); + +# printf "NEW CONTENTS: (n=%s)\n", $self->size; +# my $obj = $self->first; +# my $count=0; +# do { print "\n","Object #",++$count,"\n"; +# $obj->display; +# } while($obj=$obj->next); +# <STDIN>; +} + + +sub _index { + my($self) = @_; + my $name = $self->name; + + # Generate unique name, if necessary, for indexing purposes. + if( not $name or $name =~ /anonymous/) { + $name ||= ''; + $name .= $self->size(); + } +# print "$ID: _index() called for $name\n"; + + $self->{'_master'}->{'_index'}->{$name} = $self; +} + +sub _incrementRank { + my $self = shift; + return if not defined $self->{'_prev'}; + $self->{'_rank'} = $self->{'_prev'}->rank() + 1; +} + + +=head2 remove + + Purpose : Remove the current object from the Vector. + Usage : $self->remove([-RET=>'first'|'last'|'next'|'prev'], [-UPDATE => 0|1]) + Returns : The first, last, next, or previous object in the Vector + : depending on the value of the -RET parameter. + : Default = next. + Argument : Named parameters: (TAGS CAN BE ALL UPPER OR ALL LOWER CASE) + : -RET => string: 'first', 'last', 'prev' 'next' + : THis indicates the object to be returned. + : -UPDATE => boolean, if non-zero all objects in the vector + : will be re-ranked. + Comments : The -UPDATE parameter should be set to true to force a re-updating + : of the rank data for each object. (default = 0, no update). + +See Also : L<add>(), L<insert>(), L<shift>(), L<chop>() + +=cut + +#----------- +sub remove { +#----------- + my($self,%param) = @_; + my $updateRank = $param{-UPDATE} || $param{'-update'} || 0; + my $ret = $param{-RET} || $param{'-ret'} || 'next'; + + $DEBUG==2 && do{ print STDERR "$ID: removing ${\$self->name}; ret = $ret";<STDIN>; }; + + ## This set of conditionals involves primarily pointer shuffling. + ## The special case of destroying a vector of size 1 is handled. + + if($self->is_first()) { + $DEBUG==2 && print STDERR "---> removing first object: ${\$self->name()}.\n"; + if($self->is_last) { +# print "Removing only object in vector: ${\$self->name}.\n"; + $self->_destroy_master(); + return $self->destroy; + } else { + undef ($self->{'_next'}->{'_prev'}); + $self->_update_first($self->{'_next'}); + } + + } elsif($self->is_last()) { + $DEBUG==2 && print STDERR "---> removing last object: ${\$self->name()}.\n"; + undef ($self->{'_prev'}->{'_next'}); + $self->_update_last($self->{'_prev'}); + + } else { + $DEBUG==2 && print STDERR "---> removing internal object.\n"; + $self->{'_prev'}->{'_next'} = $self->{'_next'}; + $self->{'_next'}->{'_prev'} = $self->{'_prev'}; + } + + $updateRank && $self->_update_rank(); + $self->{'_master'}->{'_size'}--; + +# print "new vector size = ",$self->size,"\n"; <STDIN>; + + my($retObj); + + if( $self->size) { + if($ret eq 'first') { $retObj = $self->first(); } + elsif($ret eq 'last') { $retObj = $self->last(); } + elsif($ret eq 'next') { $retObj = $self->next(); } + elsif($ret eq 'prev') { $retObj = $self->prev(); } + } + + ## Destroy the object. +# $self->destroy; + + $DEBUG && do{ print STDERR "$ID: returning ${\$retObj->name}";<STDIN>; }; + + $retObj; +} + +sub _update_first { + my($self,$first) = @_; + $DEBUG && print STDERR "Updating first.\n"; + undef ($first->{'_prev'}); + $self->{'_master'}->{'_first'} = $first; +} + +sub _update_last { + my($self,$last) = @_; + $DEBUG && print STDERR "Updating last.\n"; + undef ($last->{'_next'}); + $self->{'_master'}->{'_last'} = $last; +} + + +=head2 remove_all + + Purpose : Remove all objects currently in the Vector. + Usage : $self->remove_all + +See Also : L<remove>(), L<shift>(), L<chop>() + +=cut + +#--------------- +sub remove_all { +#--------------- + my($self,%param) = @_; + + $DEBUG==2 && print STDERR "DESTROYING VECTOR $self ${\$self->name}"; + +# print "$ID Removing all."; + + $self = $self->first(); + + while(ref $self) { +# print "$ID: removing ${\$self->name}\n"; + $self = $self->remove(-RET=>'next'); + } +} + + +=head2 shift + + Purpose : Remove the first object from the Vector. + : This is a wrapper for remove(). + Usage : $self->shift([-RET=>'first'|'last'|'next'|'prev']) + Returns : The object returned by remove(). + +See Also : L<remove>(), L<chop>() + +=cut + +#--------- +sub shift { +#--------- + my($self,%param) = @_; + $self = $self->first(); + $self = $self->remove(%param); +} + + +=head2 chop + + Purpose : Remove the last object from the Vector. + : This is a wrapper for remove(). + Usage : $self->chop([-RET=>'first'|'last'|'next'|'prev']) + Returns : The object returned by remove(). + +See Also : L<remove>(), L<shift>() + +=cut + +#---------- +sub chop { +#---------- + my($self,%param) = @_; + $self = $self->last(); + $self = $self->remove(%param); +} + + + +=head2 insert + + Purpose : Insert a new object into the vector relative to the current object. + Usage : $self->insert(object_ref, ['before'|'after']) + Examples : $self->insert($obj) # Default insert after $self + : $self->insert($obj,'before') + Returns : The new number of objects in the vector (int). + Throws : exception if the first argument is not a reference. + +See Also : L<add>(), L<remove>() + +=cut + +#----------- +sub insert { +#----------- + my($self,$object,$where) = @_; + my($first); + $where ||= 'after'; + + $self->_set_master($self) unless $self->{'_master'}->{'_set'}; + + ref($object) || return $self->master->throw("Can't insert. Not an object: $object"); + + if($where eq 'before') { + $object->{'_next'} = $self; + $object->{'_prev'} = $self->{'_prev'}; + $object->{'_master'} = $self->{'_master'}; + $self->{'_prev'}->{'_next'} = $object; + $self->{'_prev'} = $object; + } else { + $object->{'_prev'} = $self; + $object->{'_next'} = $self->{'_next'}; + $object->{'_master'} = $self->{'_master'}; + $self->{'_next'}->{'_prev'} = $object; + $self->{'_next'} = $object; + } + $self->{'_master'}->{'_size'}++; + $object->Bio::Root::Vector::_index(); ##Fully qualified to disambiguate a potentially common method name. + $self->_update_rank(); +} + +sub _update_rank { + my($self) = @_; + my $current = $self->first(); + my $count = 0; + $DEBUG && print STDERR "$ID: Updating rank.\n"; + do{ + $count++; + $current->{'_rank'} = $count; + + } while($current = $current->next()); +} + + +=head2 list + + Purpose : Returns objects in the Vector as an array or array slice. + Usage : $self->list([starting_object|'first'] [,ending_object|'last']) + Examples : $self->list + : $self->list('first',$self->prev) + +See Also : L<get>() + +=cut + +#---------- +sub list { +#---------- + my($self,$start,$stop) = @_; + my(@list); + + $start ||= 1; + $stop ||= 'last'; + + if( $start =~ /first|beg|start/i or $start <= 1 ) { + $start = $self->first(); + } + + if( $stop =~ /last|end|stop/i ) { + $stop = $self->last(); + } + + ref($start) || ($start = $self->first()); + ref($stop) || ($stop = $self->last()); + + my $obj = $start; + my $fini = 0; + do{ + push @list, $obj; + if($obj eq $stop) { $fini = 1; } + } while( $obj = $obj->next() and !$fini); + + @list; +} + + +=head2 sort + + Purpose : Sort the objects in the Vector. + Usage : $self->sort(['rank'|'name'], [reverse]) + Returns : The last object of the sorted Vector. + Argument : First argument can be 'name' or 'rank' to sort on + : the object's name or rank data member, respectively. + : If reverse is non-zero, sort will be in reverse order. + Example : $self->sort() # Default sort by rank, not reverse. + : $self->sort('name','reverse') + +=cut + +#---------' +sub sort { +#--------- + my ($self,$sortBy,$reverse) = @_; + my (@unsortedList,@sortedList); + + $sortBy ||= 'rank'; + my $rankBy = $self->rank_by; + + ### Build the initial unsorted list. + my $obj = $self->first(); + do{ + push @unsortedList, $obj; + } while( $obj = $obj->next()); + +# print "UNSORTED LIST:\n"; +# foreach(@unsortedList) {print $_->name().' '};<STDIN>; + + ### Sort it. + if( $sortBy =~ /rank/i) { +# print "sorting by rank"; + if($reverse) { +# print " (reverse).\n"; + @sortedList = reverse sort _sort_by_rank @unsortedList; + } else { + @sortedList = sort _sort_by_rank @unsortedList; + } + } elsif( $sortBy =~ /name/i) { +# print "sorting by name"; + if($reverse) { +# print "(reverse).\n"; + @sortedList = reverse sort _sort_by_name @unsortedList; + } else { + @sortedList = sort _sort_by_name @unsortedList; + } + } else { +# print "unknown sort criteria: $sortBy\n"; + $self->warn("Invalid sorting criteria: $sortBy.", + "Sorting by rank."); + @sortedList = sort _sort_by_rank @unsortedList; + } + + +# if($reverse) { @sortedList = reverse sort @sortedList; } + +# print "SORTED LIST:\n"; +# foreach(@sortedList) {print $_->name().' '};<STDIN>; + + ### Re-load the Vector with the sorted list. + my $count=0; + + $self = $sortedList[0]; + $self->_set_master($self); + $self->_set_rank_by($rankBy); + + my($i); + my $current = $self; + for($i=1; $i<@sortedList; $current=$sortedList[$i], $i++) { + $current->add($sortedList[$i]); + if($i==$#sortedList) { $sortedList[$i]->{'_next'} = undef;} + } + + $self->last(); +} + +sub _sort_by_rank { my $aRank = $a->rank(); my $bRank = $b->rank(); $aRank <=> $bRank; } + +sub _sort_by_name { my $aName = $a->name(); my $bName = $b->name(); $aName cmp $bName; } + + + +=head2 valid_any + + Purpose : Determine if at least one object in the Vector is valid. + Usage : $self->valid_any + Status : Deprecated. + Comments : A non-valid object should throw an exception that must be + : be caught an dealt with on the spot. + +See Also : B<Bio::Root::Object::valid()> + +=cut + +#------------- +sub valid_any { +#------------- + my $self = &shift(@_); + + my $obj = $self->first(); + do{ + return 1 if $obj->valid(); + } while( $obj = $obj->next()); + + return undef; +} + + +=head2 valid_all + + Purpose : Determine if all objects in the Vector are valid. + Usage : $self->valid_all + Comments : A non-valid object should throw an exception that must be + : be caught an dealt with on the spot. + +See Also : B<Bio::Root::Object::valid()> + +=cut + +#-------------- +sub valid_all { +#-------------- + my $self = &shift(@_); + + my $obj = $self->first(); + do{ + return unless $obj->valid(); + } while( $obj = $obj->next()); + + return 1; +} + +sub _display_stats { +# This could be fleshed out a bit... + + my( $self, $OUT ) = @_; + + printf ( $OUT "%-11s %s\n","RANK:", $self->rank()); + printf ( $OUT "%-11s %s\n","RANK BY:", $self->rank_by()); +} + +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 + +Bio::Root::Vector.pm objects currently cannot be instantiated. Vector.pm must be inherited +along with Bio::Root::Object.pm (or an object that provides a constructor). +Vector.pm defines the following fields: + + FIELD VALUE + ------------------------------------------------------------------------ + _prev Reference to the previous object in the Vector. + + _next Reference to the next object in the Vector. + + _rank Rank relative to other objects in the Vector. + Default rank = chronological order of addition to the Vector. + + _master A reference to an Bio::Root::Object that acts as a manager for + the given Vector. There is only one master per Vector. + A master object is only needed when the Vector size is >1. + The master object manages the following Vector data: + + _first - Reference to the first object in the Vector. + _last - Reference to the last object in the Vector. + _size - Total number of objects in the Vector. + _rankBy - Criteria used to rank the object. + Default: chronological order of addition. + _index - Hash reference for quick access to any object + based on its name. + Bio::Root::Object{'_err'} - Holds any errors affecting the + Vector as a whole. + +=cut + +1;