Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/Root/Vector.pm @ 0:1f6dce3d34e0
Uploaded
author | mahtabm |
---|---|
date | Thu, 11 Apr 2013 02:01:53 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1f6dce3d34e0 |
---|---|
1 #----------------------------------------------------------------------------- | |
2 # PACKAGE : Bio::Root::Vector.pm | |
3 # AUTHOR : Steve Chervitz (sac@bioperl.org) | |
4 # CREATED : 15 April 1997 | |
5 # REVISION: $Id: Vector.pm,v 1.10 2002/10/22 07:38:37 lapp Exp $ | |
6 # STATUS : Alpha | |
7 # | |
8 # WARNING: This is considered an experimental module. | |
9 # | |
10 # For documentation, run this module through pod2html | |
11 # (preferably from Perl v5.004 or better). | |
12 # | |
13 # MODIFIED: | |
14 # sac --- Fri Nov 6 14:24:48 1998 | |
15 # * Added destroy() method (experimental). | |
16 # 0.023, 20 Jul 1998, sac: | |
17 # * Improved memory management (_destroy_master()). | |
18 # | |
19 # Copyright (c) 1997 Steve Chervitz. All Rights Reserved. | |
20 # This module is free software; you can redistribute it and/or | |
21 # modify it under the same terms as Perl itself. | |
22 #----------------------------------------------------------------------------- | |
23 | |
24 package Bio::Root::Vector; | |
25 | |
26 use Bio::Root::Global qw(:devel); | |
27 use Bio::Root::Object (); | |
28 | |
29 # @ISA = qw(Bio::Root::Object); # Eventually perhaps... | |
30 | |
31 use vars qw($ID $VERSION); | |
32 $ID = 'Bio::Root::Vector'; | |
33 $VERSION = 0.04; | |
34 | |
35 use strict; | |
36 my @SORT_BY = ('rank','name'); | |
37 | |
38 ## POD Documentation: | |
39 | |
40 =head1 NAME | |
41 | |
42 Bio::Root::Vector - Interface for managing linked lists of Perl5 objects. | |
43 | |
44 =head1 SYNOPSIS | |
45 | |
46 =head2 Object Creation | |
47 | |
48 B<At present, Vector objects cannot be instantiated.> This | |
49 package is currently designed to be inherited along with another class | |
50 that provides a constructor (e.g., B<Bio::Root::Object.pm>). | |
51 The Vector provides a set of methods that can then be used for managing | |
52 sets of objects. | |
53 | |
54 See L<the USAGE section | USAGE>. | |
55 | |
56 =head1 INSTALLATION | |
57 | |
58 This module is included with the central Bioperl distribution: | |
59 | |
60 http://bio.perl.org/Core/Latest | |
61 ftp://bio.perl.org/pub/DIST | |
62 | |
63 Follow the installation instructions included in the README file. | |
64 | |
65 | |
66 =head1 DESCRIPTION | |
67 | |
68 Bio::Root::Vector.pm provides an interface for creating and manipulating | |
69 dynamic sets (linked lists) of Perl5 objects. This is an abstract class (ie., | |
70 there is no constructor) and as such is expected to be inherited along with | |
71 some other class (see note above). | |
72 | |
73 Vectors are handy when, for example, an object may contain one or more | |
74 other objects of a certain class. The container object knows only | |
75 that is has at least one such object; the multiplex nature of the contained | |
76 object is managed by the contained object via its Vector interface. | |
77 The methods for adding, removing, counting, listing, and sorting all objects | |
78 are bundled together in Vector.pm. | |
79 | |
80 Thus, the current Bio::Root::Vector class is somewhat of a cross between an | |
81 interator and a composite design pattern. At present, a number of classes | |
82 utilize Bio::Root::Vector's composite-like behavior to implement a composite | |
83 pattern (Bio::SeqManager.pm, for example). | |
84 This is not necessarily ideal and is expected to change. | |
85 | |
86 =head1 USAGE | |
87 | |
88 For a usage demo of Bio::Root::Vector.pm see the scripts in the | |
89 examples/root_object/vector directory. | |
90 | |
91 | |
92 =head1 DEPENDENCIES | |
93 | |
94 Bio::Root::Vector.pm does not directly inherit from B<Bio::Root::Object.pm> but | |
95 creates an manager object which does. | |
96 | |
97 =head1 BUGS/FEATURES | |
98 | |
99 By default, all Vectors are doubly-linked lists. This relieves one from | |
100 the burden of worrying about whether a given Vector is single- or doubly-linked. | |
101 However, when generating lots of Vectors or extremely large vectors, memory | |
102 becomes an issue. In particular, signaling the GC to free the memory for | |
103 an object when you want to remove it. B<Until this memory issue is resolved, | |
104 the use of Vector.pm is not recommended for large projects.> | |
105 | |
106 Although it is not required, all objects within a vector are expected | |
107 to derive from the same class (package). Support for heterogeneous | |
108 Vectors has not been explicitly added (but they should work fine, as long | |
109 as you know what you're doing). | |
110 | |
111 =head1 FEEDBACK | |
112 | |
113 =head2 Mailing Lists | |
114 | |
115 User feedback is an integral part of the evolution of this and other Bioperl modules. | |
116 Send your comments and suggestions preferably to one of the Bioperl mailing lists. | |
117 Your participation is much appreciated. | |
118 | |
119 bioperl-l@bioperl.org - General discussion | |
120 http://bioperl.org/MailList.shtml - About the mailing lists | |
121 | |
122 =head2 Reporting Bugs | |
123 | |
124 Report bugs to the Bioperl bug tracking system to help us keep track the bugs and | |
125 their resolution. Bug reports can be submitted via email or the web: | |
126 | |
127 bioperl-bugs@bio.perl.org | |
128 http://bugzilla.bioperl.org/ | |
129 | |
130 =head1 AUTHOR | |
131 | |
132 Steve Chervitz E<lt>sac@bioperl.orgE<gt> | |
133 | |
134 See L<the FEEDBACK section | FEEDBACK> for where to send bug reports and comments. | |
135 | |
136 =head1 VERSION | |
137 | |
138 Bio::Root::Vector.pm, 0.04 | |
139 | |
140 =head1 TODO | |
141 | |
142 =over 4 | |
143 | |
144 =item * (Maybe) create an container class version of this module | |
145 | |
146 to permit Vectors to be instantiated. Thus, instead of inherited | |
147 from both Object.pm and Vector.pm, you could create a Vector.pm object. | |
148 | |
149 =item * Improve documentation. | |
150 | |
151 =back | |
152 | |
153 =head1 SEE ALSO | |
154 | |
155 Bio::Root::Object.pm - Core object | |
156 Bio::Root::Err.pm - Error/Exception object | |
157 Bio::Root::Global.pm - Manages global variables/constants | |
158 | |
159 http://bio.perl.org/Projects/modules.html - Online module documentation | |
160 http://bio.perl.org/ - Bioperl Project Homepage | |
161 | |
162 =head1 ACKNOWLEDGEMENTS | |
163 | |
164 This module was developed under the auspices of the Saccharomyces Genome | |
165 Database: | |
166 http://genome-www.stanford.edu/Saccharomyces | |
167 | |
168 =head1 COPYRIGHT | |
169 | |
170 Copyright (c) 1996-98 Steve Chervitz. All Rights Reserved. | |
171 This module is free software; you can redistribute it and/or | |
172 modify it under the same terms as Perl itself. | |
173 | |
174 =cut | |
175 | |
176 | |
177 #' | |
178 ## | |
179 ### | |
180 #### END of main POD documentation. | |
181 ### | |
182 ## | |
183 # | |
184 | |
185 =head1 APPENDIX | |
186 | |
187 Methods beginning with a leading underscore are considered private | |
188 and are intended for internal use by this module. They are | |
189 B<not> considered part of the public interface and are described here | |
190 for documentation purposes only. | |
191 | |
192 =cut | |
193 | |
194 ######################################################## | |
195 # CONSTRUCTOR # | |
196 ######################################################## | |
197 | |
198 ## No constructor. See _set_master() for construction of {Master} data member. | |
199 | |
200 ## Destructor: Use remove_all() or remove(). | |
201 | |
202 # New Idea for destructor | |
203 #------------- | |
204 sub destroy { | |
205 #------------- | |
206 my $self = shift; | |
207 local($^W) = 0; | |
208 undef $self->{'_prev'}; | |
209 undef $self->{'_next'}; | |
210 undef $self->{'_rank'}; | |
211 undef $self->{'_master'}; | |
212 } | |
213 | |
214 ##################################################################################### | |
215 ## ACCESSORS ## | |
216 ##################################################################################### | |
217 | |
218 | |
219 =head2 set_rank | |
220 | |
221 Purpose : To set an object's rank to an arbitrary numeric | |
222 : value to be used for sorting the objects of the Vector. | |
223 Usage : $self->set_rank(-RANK =>numeric_ranking_data, | |
224 : -RANK_BY =>ranking_criterion_string); | |
225 : or without the named parameters as (rank, rank_by). | |
226 Throws : warning (if rank is set without also setting RANK_BY) | |
227 Comments : It is redundant for every object to store RANK_BY data. | |
228 : For this reason, the RANK_BY data is stored with the master | |
229 : object associated with the vector. | |
230 | |
231 See Also : L<rank>(), L<rank_by>() | |
232 | |
233 =cut | |
234 | |
235 #-------------' | |
236 sub set_rank { | |
237 #------------- | |
238 my( $self, %param) = @_; | |
239 | |
240 $self->_set_master($self) unless $self->{'_master'}->{'_set'}; | |
241 | |
242 my($rank, $rank_by) = $self->master->_rearrange([qw(RANK RANK_BY)], %param); | |
243 | |
244 $DEBUG==1 and do{ print STDERR "$ID:set_rank() = $rank; Criteria: $rank_by."; <STDIN>; }; | |
245 | |
246 $self->{'_rank'} = ($rank || undef); | |
247 $self->{'_master'}->{'_rankBy'} = ($rank_by || undef); | |
248 if( defined $self->{'_rank'} and not defined $self->{'_master'}->{'_rankBy'} ) { | |
249 return $self->master->warn('Rank defined without ranking criteria.'); | |
250 } | |
251 1; | |
252 } | |
253 | |
254 sub _set_rank_by { | |
255 my( $self, $arg) = @_; | |
256 $self->{'_master'}->{'_rankBy'} = $arg || 'unknown'; | |
257 } | |
258 | |
259 sub _set_master { | |
260 ## A vector does not need a master object unless it needs to grow. | |
261 my($self,$obj) = @_; | |
262 | |
263 # print "$ID: _set_master() new Master object for ${\$obj->name}."; <STDIN>; | |
264 | |
265 require Bio::Root::Object; | |
266 my $master = {}; | |
267 bless $master, 'Bio::Root::Object'; | |
268 | |
269 $master->{'_set'} = 1; ## Special member indicating that this method has been called. | |
270 ## Necessary since perl will generate an anonymous {Master} | |
271 ## hash ref on the fly. This ref will not be blessed however. | |
272 $master->{'_first'} = $obj; | |
273 $master->{'_last'} = $obj; | |
274 $master->{'_size'} = 1; | |
275 $master->{'_index'}->{$obj->name()} = $obj; | |
276 $self->{'_master'} = $master; | |
277 | |
278 $self->{'_rank'} = 1; | |
279 $self->{'_prev'} = undef; | |
280 $self->{'_next'} = undef; | |
281 # $self->{'_master'}->{'_rankBy'} = undef; # Default rank is the order of addition to Vector. | |
282 } | |
283 | |
284 sub _destroy_master { | |
285 # This is called when the last object in the vector is being remove()d | |
286 my $self = shift; | |
287 | |
288 return if !$self->master or !$self->master->{'_set'}; | |
289 | |
290 my $master = $self->master; | |
291 | |
292 ## Get rid of the Vector master object. | |
293 ref $master->{'_first'} and (%{$master->{'_first'}} = (), undef $master->{'_first'}); | |
294 ref $master->{'_last'} and (%{$master->{'_last'}} = (), undef $master->{'_last'}); | |
295 ref $master->{'_index'} and (%{$master->{'_index'}} = (), undef $master->{'_index'}); | |
296 %{$master} = (); | |
297 undef $master; | |
298 } | |
299 | |
300 | |
301 =head2 clone_vector | |
302 | |
303 Purpose : Call this method to clone the whole vector. | |
304 : NOT calling this method will extract the vector element. | |
305 Usage : $self->clone_vector(); | |
306 Throws : Exception if argument is not an object reference. | |
307 Comments : This method is usually called from within a module's | |
308 : _set_clone() method for modules that inherit from | |
309 : Bio::Root::Vector.pm. | |
310 | |
311 =cut | |
312 | |
313 #-----------------' | |
314 sub clone_vector { | |
315 #----------------- | |
316 my($self, $obj) = @_; | |
317 | |
318 ref($obj) || throw($self, "Can't clone $ID object: Not an object ref ($obj)"); | |
319 | |
320 $self->{'_prev'} = $obj->{'_prev'}; | |
321 $self->{'_next'} = $obj->{'_next'}; | |
322 $self->{'_rank'} = $obj->{'_rank'}; | |
323 $self->{'_master'} = $obj->{'_master'}; | |
324 } | |
325 | |
326 | |
327 =head2 prev | |
328 | |
329 Purpose : Returns the previous object in the Vector or undef | |
330 : if on first object. | |
331 Usage : $self->prev | |
332 | |
333 =cut | |
334 | |
335 #-------- | |
336 sub prev { my $self = shift; $self->{'_prev'}; } | |
337 #-------- | |
338 | |
339 | |
340 | |
341 =head2 next | |
342 | |
343 Purpose : Returns the next object in the Vector or undef | |
344 : if on last object. | |
345 Usage : $self->next | |
346 | |
347 =cut | |
348 | |
349 #-------- | |
350 sub next { my $self = shift; $self->{'_next'}; } | |
351 #-------- | |
352 | |
353 | |
354 | |
355 =head2 first | |
356 | |
357 Purpose : Returns the first object in the Vector or $self | |
358 : if Vector size = 1. | |
359 Usage : $self->first | |
360 | |
361 =cut | |
362 | |
363 #---------- | |
364 sub first { | |
365 #---------- | |
366 my $self = shift; | |
367 defined $self->{'_master'} ? $self->{'_master'}->{'_first'} : $self; | |
368 } | |
369 | |
370 | |
371 =head2 last | |
372 | |
373 Purpose : Returns the last object in the Vector or | |
374 : $self if Vector size = 1. | |
375 Usage : $self->last | |
376 | |
377 =cut | |
378 | |
379 #------- | |
380 sub last { | |
381 #------- | |
382 my $self = shift; | |
383 defined $self->{'_master'} ? $self->{'_master'}->{'_last'} : $self; | |
384 } | |
385 | |
386 | |
387 | |
388 =head2 rank | |
389 | |
390 Purpose : Returns the rank of the current object or 1 | |
391 : if rank is not defined. | |
392 Usage : $self->rank | |
393 | |
394 See Also : L<set_rank>() | |
395 | |
396 =cut | |
397 | |
398 #--------- | |
399 sub rank { my $self = shift; $self->{'_rank'} || 1; } | |
400 #--------- | |
401 | |
402 | |
403 | |
404 =head2 rank_by | |
405 | |
406 Purpose : Returns the ranking criterion or the string 'order of addition' | |
407 : if rankBy has not been explicitly set. | |
408 Usage : $self->rank_by | |
409 | |
410 See Also : L<set_rank>() | |
411 | |
412 =cut | |
413 | |
414 #----------- | |
415 sub rank_by { | |
416 #----------- | |
417 my $self = shift; | |
418 defined $self->{'_master'} ? ($self->{'_master'}->{'_rankBy'}||'order of addition') | |
419 : 'unranked'; | |
420 } | |
421 | |
422 | |
423 | |
424 =head2 size | |
425 | |
426 Purpose : Returns the number of objects currently in the Vector. | |
427 Usage : $self->size | |
428 | |
429 =cut | |
430 | |
431 #--------- | |
432 sub size { | |
433 #--------- | |
434 my $self = shift; | |
435 defined $self->{'_master'} ? $self->{'_master'}->{'_size'} : 1; | |
436 } | |
437 | |
438 | |
439 =head2 master | |
440 | |
441 Purpose : Returns the master object associated with the Vector. | |
442 : (should probably be a private method). | |
443 Usage : $self->master | |
444 | |
445 =cut | |
446 | |
447 #----------- | |
448 sub master { my $self = shift; $self->{'_master'}; } | |
449 #----------- | |
450 | |
451 | |
452 ## Not sure what these potentially dangerous methods are used for. | |
453 ## Should be unnecessary and probably can be removed. | |
454 sub set_prev { my($self,$obj) = @_; $self->{'_prev'} = $obj; } | |
455 sub set_next { my($self,$obj) = @_; $self->{'_next'} = $obj; } | |
456 | |
457 ############################################################################# | |
458 # INSTANCE METHODS ## | |
459 ############################################################################# | |
460 | |
461 | |
462 =head2 is_first | |
463 | |
464 Purpose : Test whether the current object is the first in the Vector. | |
465 Usage : $self->is_first | |
466 | |
467 =cut | |
468 | |
469 #------------ | |
470 sub is_first { my($self) = shift; return not defined $self->{'_prev'}; } | |
471 #------------ | |
472 | |
473 | |
474 =head2 is_last | |
475 | |
476 Purpose : Test whether the current object is the last in the Vector. | |
477 Usage : $self->is_last | |
478 | |
479 =cut | |
480 | |
481 #------------ | |
482 sub is_last { my($self) = shift; return not defined $self->{'_next'}; } | |
483 #------------ | |
484 | |
485 | |
486 | |
487 | |
488 =head2 get | |
489 | |
490 Purpose : Retrives an object from the Vector given its name. | |
491 : Returns undef if the object cannot be found. | |
492 Usage : $self->get(object_name) | |
493 Examples : $self->get($obj->name) | |
494 | |
495 See Also : L<list>() | |
496 | |
497 =cut | |
498 | |
499 #-------- | |
500 sub get { | |
501 #-------- | |
502 my($self,$name) = @_; | |
503 | |
504 my ($obj); | |
505 # print "$ID get(): getting $name\n"; | |
506 | |
507 if($self->{'_master'}->{'_set'}) { | |
508 # my @names = keys %{$self->{'_master'}->{'_index'}}; | |
509 # print "$ID: names in hash:\n@names";<STDIN>; | |
510 # print " returning $self->{'_master'}->{'_index'}->{$name}\n"; | |
511 local($^W) = 0; | |
512 $obj = $self->{'_master'}->{'_index'}->{$name}; | |
513 } | |
514 | |
515 elsif($self->name =~ /$name/i) { | |
516 # print " returning self\n"; | |
517 $obj = $self; | |
518 } | |
519 | |
520 if(not ref $obj) { | |
521 $self->throw("Can't get object named \"$name\": object not set or name undefined."); | |
522 } | |
523 $obj; | |
524 } | |
525 | |
526 ## Former strategy: hunt through the list for the object. | |
527 ## No longer needed since master indexes all objects. | |
528 # do{ | |
529 # if($obj->name eq $name) { return $obj; } | |
530 # | |
531 # } while($obj = $current->prev()); | |
532 | |
533 | |
534 | |
535 | |
536 =head2 add | |
537 | |
538 Purpose : Add an object to the end of a Vector. | |
539 Usage : $self->add(object_reference) | |
540 | |
541 See also : L<insert>(), L<remove>() | |
542 | |
543 =cut | |
544 | |
545 #-------- | |
546 sub add { | |
547 #-------- | |
548 my($self,$new,$index) = @_; | |
549 | |
550 $self->_set_master($self) unless $self->{'_master'}->{'_set'}; | |
551 | |
552 # print "\n\nADDING TO VECTOR ${\ref $self} ${\$self->name}\nFOR PARENT: ${\ref $self->parent} ${\$self->parent->name}\n\n"; | |
553 | |
554 $self->{'_next'} = $new; | |
555 $new->{'_prev'} = $self; | |
556 $self->{'_master'}->{'_last'} = $new; | |
557 $self->{'_master'}->{'_size'}++; | |
558 $new->{'_master'} = $self->{'_master'}; | |
559 $new->_incrementRank(); | |
560 $new->Bio::Root::Vector::_index(); | |
561 | |
562 # printf "NEW CONTENTS: (n=%s)\n", $self->size; | |
563 # my $obj = $self->first; | |
564 # my $count=0; | |
565 # do { print "\n","Object #",++$count,"\n"; | |
566 # $obj->display; | |
567 # } while($obj=$obj->next); | |
568 # <STDIN>; | |
569 } | |
570 | |
571 | |
572 sub _index { | |
573 my($self) = @_; | |
574 my $name = $self->name; | |
575 | |
576 # Generate unique name, if necessary, for indexing purposes. | |
577 if( not $name or $name =~ /anonymous/) { | |
578 $name ||= ''; | |
579 $name .= $self->size(); | |
580 } | |
581 # print "$ID: _index() called for $name\n"; | |
582 | |
583 $self->{'_master'}->{'_index'}->{$name} = $self; | |
584 } | |
585 | |
586 sub _incrementRank { | |
587 my $self = shift; | |
588 return if not defined $self->{'_prev'}; | |
589 $self->{'_rank'} = $self->{'_prev'}->rank() + 1; | |
590 } | |
591 | |
592 | |
593 =head2 remove | |
594 | |
595 Purpose : Remove the current object from the Vector. | |
596 Usage : $self->remove([-RET=>'first'|'last'|'next'|'prev'], [-UPDATE => 0|1]) | |
597 Returns : The first, last, next, or previous object in the Vector | |
598 : depending on the value of the -RET parameter. | |
599 : Default = next. | |
600 Argument : Named parameters: (TAGS CAN BE ALL UPPER OR ALL LOWER CASE) | |
601 : -RET => string: 'first', 'last', 'prev' 'next' | |
602 : THis indicates the object to be returned. | |
603 : -UPDATE => boolean, if non-zero all objects in the vector | |
604 : will be re-ranked. | |
605 Comments : The -UPDATE parameter should be set to true to force a re-updating | |
606 : of the rank data for each object. (default = 0, no update). | |
607 | |
608 See Also : L<add>(), L<insert>(), L<shift>(), L<chop>() | |
609 | |
610 =cut | |
611 | |
612 #----------- | |
613 sub remove { | |
614 #----------- | |
615 my($self,%param) = @_; | |
616 my $updateRank = $param{-UPDATE} || $param{'-update'} || 0; | |
617 my $ret = $param{-RET} || $param{'-ret'} || 'next'; | |
618 | |
619 $DEBUG==2 && do{ print STDERR "$ID: removing ${\$self->name}; ret = $ret";<STDIN>; }; | |
620 | |
621 ## This set of conditionals involves primarily pointer shuffling. | |
622 ## The special case of destroying a vector of size 1 is handled. | |
623 | |
624 if($self->is_first()) { | |
625 $DEBUG==2 && print STDERR "---> removing first object: ${\$self->name()}.\n"; | |
626 if($self->is_last) { | |
627 # print "Removing only object in vector: ${\$self->name}.\n"; | |
628 $self->_destroy_master(); | |
629 return $self->destroy; | |
630 } else { | |
631 undef ($self->{'_next'}->{'_prev'}); | |
632 $self->_update_first($self->{'_next'}); | |
633 } | |
634 | |
635 } elsif($self->is_last()) { | |
636 $DEBUG==2 && print STDERR "---> removing last object: ${\$self->name()}.\n"; | |
637 undef ($self->{'_prev'}->{'_next'}); | |
638 $self->_update_last($self->{'_prev'}); | |
639 | |
640 } else { | |
641 $DEBUG==2 && print STDERR "---> removing internal object.\n"; | |
642 $self->{'_prev'}->{'_next'} = $self->{'_next'}; | |
643 $self->{'_next'}->{'_prev'} = $self->{'_prev'}; | |
644 } | |
645 | |
646 $updateRank && $self->_update_rank(); | |
647 $self->{'_master'}->{'_size'}--; | |
648 | |
649 # print "new vector size = ",$self->size,"\n"; <STDIN>; | |
650 | |
651 my($retObj); | |
652 | |
653 if( $self->size) { | |
654 if($ret eq 'first') { $retObj = $self->first(); } | |
655 elsif($ret eq 'last') { $retObj = $self->last(); } | |
656 elsif($ret eq 'next') { $retObj = $self->next(); } | |
657 elsif($ret eq 'prev') { $retObj = $self->prev(); } | |
658 } | |
659 | |
660 ## Destroy the object. | |
661 # $self->destroy; | |
662 | |
663 $DEBUG && do{ print STDERR "$ID: returning ${\$retObj->name}";<STDIN>; }; | |
664 | |
665 $retObj; | |
666 } | |
667 | |
668 sub _update_first { | |
669 my($self,$first) = @_; | |
670 $DEBUG && print STDERR "Updating first.\n"; | |
671 undef ($first->{'_prev'}); | |
672 $self->{'_master'}->{'_first'} = $first; | |
673 } | |
674 | |
675 sub _update_last { | |
676 my($self,$last) = @_; | |
677 $DEBUG && print STDERR "Updating last.\n"; | |
678 undef ($last->{'_next'}); | |
679 $self->{'_master'}->{'_last'} = $last; | |
680 } | |
681 | |
682 | |
683 =head2 remove_all | |
684 | |
685 Purpose : Remove all objects currently in the Vector. | |
686 Usage : $self->remove_all | |
687 | |
688 See Also : L<remove>(), L<shift>(), L<chop>() | |
689 | |
690 =cut | |
691 | |
692 #--------------- | |
693 sub remove_all { | |
694 #--------------- | |
695 my($self,%param) = @_; | |
696 | |
697 $DEBUG==2 && print STDERR "DESTROYING VECTOR $self ${\$self->name}"; | |
698 | |
699 # print "$ID Removing all."; | |
700 | |
701 $self = $self->first(); | |
702 | |
703 while(ref $self) { | |
704 # print "$ID: removing ${\$self->name}\n"; | |
705 $self = $self->remove(-RET=>'next'); | |
706 } | |
707 } | |
708 | |
709 | |
710 =head2 shift | |
711 | |
712 Purpose : Remove the first object from the Vector. | |
713 : This is a wrapper for remove(). | |
714 Usage : $self->shift([-RET=>'first'|'last'|'next'|'prev']) | |
715 Returns : The object returned by remove(). | |
716 | |
717 See Also : L<remove>(), L<chop>() | |
718 | |
719 =cut | |
720 | |
721 #--------- | |
722 sub shift { | |
723 #--------- | |
724 my($self,%param) = @_; | |
725 $self = $self->first(); | |
726 $self = $self->remove(%param); | |
727 } | |
728 | |
729 | |
730 =head2 chop | |
731 | |
732 Purpose : Remove the last object from the Vector. | |
733 : This is a wrapper for remove(). | |
734 Usage : $self->chop([-RET=>'first'|'last'|'next'|'prev']) | |
735 Returns : The object returned by remove(). | |
736 | |
737 See Also : L<remove>(), L<shift>() | |
738 | |
739 =cut | |
740 | |
741 #---------- | |
742 sub chop { | |
743 #---------- | |
744 my($self,%param) = @_; | |
745 $self = $self->last(); | |
746 $self = $self->remove(%param); | |
747 } | |
748 | |
749 | |
750 | |
751 =head2 insert | |
752 | |
753 Purpose : Insert a new object into the vector relative to the current object. | |
754 Usage : $self->insert(object_ref, ['before'|'after']) | |
755 Examples : $self->insert($obj) # Default insert after $self | |
756 : $self->insert($obj,'before') | |
757 Returns : The new number of objects in the vector (int). | |
758 Throws : exception if the first argument is not a reference. | |
759 | |
760 See Also : L<add>(), L<remove>() | |
761 | |
762 =cut | |
763 | |
764 #----------- | |
765 sub insert { | |
766 #----------- | |
767 my($self,$object,$where) = @_; | |
768 my($first); | |
769 $where ||= 'after'; | |
770 | |
771 $self->_set_master($self) unless $self->{'_master'}->{'_set'}; | |
772 | |
773 ref($object) || return $self->master->throw("Can't insert. Not an object: $object"); | |
774 | |
775 if($where eq 'before') { | |
776 $object->{'_next'} = $self; | |
777 $object->{'_prev'} = $self->{'_prev'}; | |
778 $object->{'_master'} = $self->{'_master'}; | |
779 $self->{'_prev'}->{'_next'} = $object; | |
780 $self->{'_prev'} = $object; | |
781 } else { | |
782 $object->{'_prev'} = $self; | |
783 $object->{'_next'} = $self->{'_next'}; | |
784 $object->{'_master'} = $self->{'_master'}; | |
785 $self->{'_next'}->{'_prev'} = $object; | |
786 $self->{'_next'} = $object; | |
787 } | |
788 $self->{'_master'}->{'_size'}++; | |
789 $object->Bio::Root::Vector::_index(); ##Fully qualified to disambiguate a potentially common method name. | |
790 $self->_update_rank(); | |
791 } | |
792 | |
793 sub _update_rank { | |
794 my($self) = @_; | |
795 my $current = $self->first(); | |
796 my $count = 0; | |
797 $DEBUG && print STDERR "$ID: Updating rank.\n"; | |
798 do{ | |
799 $count++; | |
800 $current->{'_rank'} = $count; | |
801 | |
802 } while($current = $current->next()); | |
803 } | |
804 | |
805 | |
806 =head2 list | |
807 | |
808 Purpose : Returns objects in the Vector as an array or array slice. | |
809 Usage : $self->list([starting_object|'first'] [,ending_object|'last']) | |
810 Examples : $self->list | |
811 : $self->list('first',$self->prev) | |
812 | |
813 See Also : L<get>() | |
814 | |
815 =cut | |
816 | |
817 #---------- | |
818 sub list { | |
819 #---------- | |
820 my($self,$start,$stop) = @_; | |
821 my(@list); | |
822 | |
823 $start ||= 1; | |
824 $stop ||= 'last'; | |
825 | |
826 if( $start =~ /first|beg|start/i or $start <= 1 ) { | |
827 $start = $self->first(); | |
828 } | |
829 | |
830 if( $stop =~ /last|end|stop/i ) { | |
831 $stop = $self->last(); | |
832 } | |
833 | |
834 ref($start) || ($start = $self->first()); | |
835 ref($stop) || ($stop = $self->last()); | |
836 | |
837 my $obj = $start; | |
838 my $fini = 0; | |
839 do{ | |
840 push @list, $obj; | |
841 if($obj eq $stop) { $fini = 1; } | |
842 } while( $obj = $obj->next() and !$fini); | |
843 | |
844 @list; | |
845 } | |
846 | |
847 | |
848 =head2 sort | |
849 | |
850 Purpose : Sort the objects in the Vector. | |
851 Usage : $self->sort(['rank'|'name'], [reverse]) | |
852 Returns : The last object of the sorted Vector. | |
853 Argument : First argument can be 'name' or 'rank' to sort on | |
854 : the object's name or rank data member, respectively. | |
855 : If reverse is non-zero, sort will be in reverse order. | |
856 Example : $self->sort() # Default sort by rank, not reverse. | |
857 : $self->sort('name','reverse') | |
858 | |
859 =cut | |
860 | |
861 #---------' | |
862 sub sort { | |
863 #--------- | |
864 my ($self,$sortBy,$reverse) = @_; | |
865 my (@unsortedList,@sortedList); | |
866 | |
867 $sortBy ||= 'rank'; | |
868 my $rankBy = $self->rank_by; | |
869 | |
870 ### Build the initial unsorted list. | |
871 my $obj = $self->first(); | |
872 do{ | |
873 push @unsortedList, $obj; | |
874 } while( $obj = $obj->next()); | |
875 | |
876 # print "UNSORTED LIST:\n"; | |
877 # foreach(@unsortedList) {print $_->name().' '};<STDIN>; | |
878 | |
879 ### Sort it. | |
880 if( $sortBy =~ /rank/i) { | |
881 # print "sorting by rank"; | |
882 if($reverse) { | |
883 # print " (reverse).\n"; | |
884 @sortedList = reverse sort _sort_by_rank @unsortedList; | |
885 } else { | |
886 @sortedList = sort _sort_by_rank @unsortedList; | |
887 } | |
888 } elsif( $sortBy =~ /name/i) { | |
889 # print "sorting by name"; | |
890 if($reverse) { | |
891 # print "(reverse).\n"; | |
892 @sortedList = reverse sort _sort_by_name @unsortedList; | |
893 } else { | |
894 @sortedList = sort _sort_by_name @unsortedList; | |
895 } | |
896 } else { | |
897 # print "unknown sort criteria: $sortBy\n"; | |
898 $self->warn("Invalid sorting criteria: $sortBy.", | |
899 "Sorting by rank."); | |
900 @sortedList = sort _sort_by_rank @unsortedList; | |
901 } | |
902 | |
903 | |
904 # if($reverse) { @sortedList = reverse sort @sortedList; } | |
905 | |
906 # print "SORTED LIST:\n"; | |
907 # foreach(@sortedList) {print $_->name().' '};<STDIN>; | |
908 | |
909 ### Re-load the Vector with the sorted list. | |
910 my $count=0; | |
911 | |
912 $self = $sortedList[0]; | |
913 $self->_set_master($self); | |
914 $self->_set_rank_by($rankBy); | |
915 | |
916 my($i); | |
917 my $current = $self; | |
918 for($i=1; $i<@sortedList; $current=$sortedList[$i], $i++) { | |
919 $current->add($sortedList[$i]); | |
920 if($i==$#sortedList) { $sortedList[$i]->{'_next'} = undef;} | |
921 } | |
922 | |
923 $self->last(); | |
924 } | |
925 | |
926 sub _sort_by_rank { my $aRank = $a->rank(); my $bRank = $b->rank(); $aRank <=> $bRank; } | |
927 | |
928 sub _sort_by_name { my $aName = $a->name(); my $bName = $b->name(); $aName cmp $bName; } | |
929 | |
930 | |
931 | |
932 =head2 valid_any | |
933 | |
934 Purpose : Determine if at least one object in the Vector is valid. | |
935 Usage : $self->valid_any | |
936 Status : Deprecated. | |
937 Comments : A non-valid object should throw an exception that must be | |
938 : be caught an dealt with on the spot. | |
939 | |
940 See Also : B<Bio::Root::Object::valid()> | |
941 | |
942 =cut | |
943 | |
944 #------------- | |
945 sub valid_any { | |
946 #------------- | |
947 my $self = &shift(@_); | |
948 | |
949 my $obj = $self->first(); | |
950 do{ | |
951 return 1 if $obj->valid(); | |
952 } while( $obj = $obj->next()); | |
953 | |
954 return undef; | |
955 } | |
956 | |
957 | |
958 =head2 valid_all | |
959 | |
960 Purpose : Determine if all objects in the Vector are valid. | |
961 Usage : $self->valid_all | |
962 Comments : A non-valid object should throw an exception that must be | |
963 : be caught an dealt with on the spot. | |
964 | |
965 See Also : B<Bio::Root::Object::valid()> | |
966 | |
967 =cut | |
968 | |
969 #-------------- | |
970 sub valid_all { | |
971 #-------------- | |
972 my $self = &shift(@_); | |
973 | |
974 my $obj = $self->first(); | |
975 do{ | |
976 return unless $obj->valid(); | |
977 } while( $obj = $obj->next()); | |
978 | |
979 return 1; | |
980 } | |
981 | |
982 sub _display_stats { | |
983 # This could be fleshed out a bit... | |
984 | |
985 my( $self, $OUT ) = @_; | |
986 | |
987 printf ( $OUT "%-11s %s\n","RANK:", $self->rank()); | |
988 printf ( $OUT "%-11s %s\n","RANK BY:", $self->rank_by()); | |
989 } | |
990 | |
991 1; | |
992 __END__ | |
993 | |
994 ##################################################################################### | |
995 # END OF CLASS # | |
996 ##################################################################################### | |
997 | |
998 =head1 FOR DEVELOPERS ONLY | |
999 | |
1000 =head2 Data Members | |
1001 | |
1002 Information about the various data members of this module is provided for those | |
1003 wishing to modify or understand the code. Two things to bear in mind: | |
1004 | |
1005 =over 4 | |
1006 | |
1007 =item 1 Do NOT rely on these in any code outside of this module. | |
1008 | |
1009 All data members are prefixed with an underscore to signify that they are private. | |
1010 Always use accessor methods. If the accessor doesn't exist or is inadequate, | |
1011 create or modify an accessor (and let me know, too!). | |
1012 | |
1013 =item 2 This documentation may be incomplete and out of date. | |
1014 | |
1015 It is easy for this documentation to become obsolete as this module is still evolving. | |
1016 Always double check this info and search for members not described here. | |
1017 | |
1018 =back | |
1019 | |
1020 Bio::Root::Vector.pm objects currently cannot be instantiated. Vector.pm must be inherited | |
1021 along with Bio::Root::Object.pm (or an object that provides a constructor). | |
1022 Vector.pm defines the following fields: | |
1023 | |
1024 FIELD VALUE | |
1025 ------------------------------------------------------------------------ | |
1026 _prev Reference to the previous object in the Vector. | |
1027 | |
1028 _next Reference to the next object in the Vector. | |
1029 | |
1030 _rank Rank relative to other objects in the Vector. | |
1031 Default rank = chronological order of addition to the Vector. | |
1032 | |
1033 _master A reference to an Bio::Root::Object that acts as a manager for | |
1034 the given Vector. There is only one master per Vector. | |
1035 A master object is only needed when the Vector size is >1. | |
1036 The master object manages the following Vector data: | |
1037 | |
1038 _first - Reference to the first object in the Vector. | |
1039 _last - Reference to the last object in the Vector. | |
1040 _size - Total number of objects in the Vector. | |
1041 _rankBy - Criteria used to rank the object. | |
1042 Default: chronological order of addition. | |
1043 _index - Hash reference for quick access to any object | |
1044 based on its name. | |
1045 Bio::Root::Object{'_err'} - Holds any errors affecting the | |
1046 Vector as a whole. | |
1047 | |
1048 =cut | |
1049 | |
1050 1; |