File Coverage

blib/lib/Bio/DB/SeqFeature/Store/LoadHelper.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Bio::DB::SeqFeature::Store::LoadHelper;
2              
3             # NOTE: This overwrites the version in bioperl-live!!
4              
5             =head1 NAME
6              
7             Bio::DB::SeqFeature::Store::LoadHelper -- Internal utility for Bio::DB::SeqFeature::Store
8              
9             =head1 SYNOPSIS
10              
11             # For internal use only.
12              
13             =head1 DESCRIPTION
14              
15             For internal use only
16              
17             =head1 SEE ALSO
18              
19             L,
20             L,
21             L,
22             L,
23             L,
24             L,
25             L
26              
27             =head1 AUTHOR
28              
29             Lincoln Stein Elstein@cshl.orgE.
30              
31             Copyright (c) 2006 Cold Spring Harbor Laboratory.
32              
33             This library is free software; you can redistribute it and/or modify
34             it under the same terms as Perl itself.
35              
36             =cut
37              
38 1     1   1807 use strict;
  1         1  
  1         23  
39 1     1   207 use DB_File;
  0            
  0            
40             use File::Path 'rmtree';
41             use File::Temp 'tempdir';
42             use File::Spec;
43             use Fcntl qw(O_CREAT O_RDWR);
44              
45             our $VERSION = '1.10';
46              
47             my %DBHandles;
48              
49             sub new {
50             my $class = shift;
51             my $tmpdir = shift;
52              
53             my $template = 'SeqFeatureLoadHelper_XXXXXX';
54              
55             my @tmpargs = $tmpdir ? ($template,DIR=>$tmpdir) : ($template);
56             my $tmppath = tempdir(@tmpargs,CLEANUP=>1);
57             my $self = $class->create_dbs($tmppath);
58             $self->{tmppath} = $tmppath;
59             return bless $self,$class;
60             }
61              
62             sub DESTROY {
63             my $self = shift;
64             rmtree $self->{tmppath};
65             # File::Temp::cleanup() unless $self->{keep};
66             }
67              
68             sub create_dbs {
69             my $self = shift;
70             my $tmp = shift;
71             my %self;
72             # experiment with caching these handles in memory
73             my $hash_options = DB_File::HASHINFO->new();
74             # Each of these hashes allow only unique keys
75             for my $dbname (qw(IndexIt TopLevel Local2Global)) {
76             unless ($DBHandles{$dbname}) {
77             my %h;
78             tie(%h,'DB_File',File::Spec->catfile($tmp,$dbname),
79             O_CREAT|O_RDWR,0666,$hash_options);
80             $DBHandles{$dbname} = \%h;
81             }
82             $self{$dbname} = $DBHandles{$dbname};
83             %{$self{$dbname}} = ();
84             }
85              
86             # The Parent2Child hash allows duplicate keys, so we
87             # create it with the R_DUP flag.
88             my $btree_options = DB_File::BTREEINFO->new();
89             $btree_options->{flags} = R_DUP;
90             unless ($DBHandles{'Parent2Child'}) {
91             my %h;
92             tie(%h,'DB_File',File::Spec->catfile($tmp,'Parent2Child'),
93             O_CREAT|O_RDWR,0666,$btree_options);
94             $DBHandles{'Parent2Child'} = \%h;
95             }
96             $self{Parent2Child} = $DBHandles{'Parent2Child'};
97             %{$self{Parent2Child}} = ();
98             return \%self;
99             }
100              
101             sub indexit {
102             my $self = shift;
103             my $id = shift;
104             $self->{IndexIt}{$id} = shift if @_;
105             return $self->{IndexIt}{$id};
106             }
107              
108             sub toplevel {
109             my $self = shift;
110             my $id = shift;
111             $self->{TopLevel}{$id} = shift if @_;
112             return $self->{TopLevel}{$id};
113             }
114              
115             sub each_toplevel {
116             my $self = shift;
117             my ($id) = each %{$self->{TopLevel}};
118             $id;
119             }
120              
121             sub local2global {
122             my $self = shift;
123             my $id = shift;
124             $self->{Local2Global}{$id} = shift if @_;
125             return $self->{Local2Global}{$id};
126             }
127              
128             sub add_children {
129             my $self = shift;
130             my $parent_id = shift;
131             # (@children) = @_;
132             $self->{Parent2Child}{$parent_id} = shift while @_;
133             }
134              
135             sub children {
136             my $self = shift;
137             my $parent_id = shift;
138              
139             my @children;
140              
141             my $db = tied(%{$self->{Parent2Child}});
142             my $key = $parent_id;
143             my $value = '';
144             for (my $status = $db->seq($key,$value,R_CURSOR);
145             $status == 0 && $key eq $parent_id;
146             $status = $db->seq($key,$value,R_NEXT)
147             ) {
148             push @children,$value;
149             }
150             return wantarray ? @children: \@children;
151             }
152              
153             # this acts like each() and returns each parent id and an array ref of children
154             sub each_family {
155             my $self = shift;
156              
157             my $db = tied(%{$self->{Parent2Child}});
158              
159             if ($self->{_cursordone}) {
160             undef $self->{_cursordone};
161             undef $self->{_parent};
162             undef $self->{_child};
163             return;
164             }
165              
166             # do a slightly tricky cursor search
167             unless (defined $self->{_parent}) {
168             return unless $db->seq($self->{_parent},$self->{_child},R_FIRST) == 0;
169             }
170              
171             my $parent = $self->{_parent};
172             my @children = $self->{_child};
173              
174             my $status;
175             while (($status = $db->seq($self->{_parent},$self->{_child},R_NEXT)) == 0
176             && $self->{_parent} eq $parent
177             ) {
178             push @children,$self->{_child};
179             }
180              
181             $self->{_cursordone}++ if $status != 0;
182            
183             return ($parent,\@children);
184             }
185              
186             sub local_ids {
187             my $self = shift;
188             my @ids = keys %{$self->{Local2Global}}
189             if $self->{Local2Global};
190             return \@ids;
191             }
192              
193             sub loaded_ids {
194             my $self = shift;
195             my @ids = values %{$self->{Local2Global}}
196             if $self->{Local2Global};
197             return \@ids;
198             }
199              
200             1;