sync w/ main trunk
[bioperl-live.git] / Bio / DB / SeqFeature / Store / LoadHelper.pm
blobbd9d66d46498fe0d012e2379a071595230ce9baa
1 package Bio::DB::SeqFeature::Store::LoadHelper;
3 # $Id$
5 =head1 NAME
7 Bio::DB::SeqFeature::Store::LoadHelper -- Internal utility for Bio::DB::SeqFeature::Store
9 =head1 SYNOPSIS
11 # For internal use only.
13 =head1 DESCRIPTION
15 For internal use only
17 =head1 SEE ALSO
19 L<bioperl>,
20 L<Bio::DB::SeqFeature::Store>,
21 L<Bio::DB::SeqFeature::Segment>,
22 L<Bio::DB::SeqFeature::NormalizedFeature>,
23 L<Bio::DB::SeqFeature::GFF2Loader>,
24 L<Bio::DB::SeqFeature::Store::DBI::mysql>,
25 L<Bio::DB::SeqFeature::Store::berkeleydb>
27 =head1 AUTHOR
29 Lincoln Stein E<lt>lstein@cshl.orgE<gt>.
31 Copyright (c) 2006 Cold Spring Harbor Laboratory.
33 This library is free software; you can redistribute it and/or modify
34 it under the same terms as Perl itself.
36 =cut
38 use strict;
39 use DB_File;
40 use File::Path 'rmtree';
41 use File::Temp 'tempdir';
42 use File::Spec;
43 use Fcntl qw(O_CREAT O_RDWR);
45 sub new {
46 my $class = shift;
47 my $tmpdir = shift;
49 my $template = 'SeqFeatureLoadHelper_XXXXXX';
51 my @tmpargs = $tmpdir ? ($template,DIR=>$tmpdir) : ($template);
52 my $tmppath = tempdir(@tmpargs,CLEANUP=>1);
53 my $self = $class->create_dbs($tmppath);
54 $self->{tmppath} = $tmppath;
55 return bless $self,$class;
58 sub DESTROY {
59 my $self = shift;
60 rmtree $self->{tmppath};
61 # File::Temp::cleanup() unless $self->{keep};
64 sub create_dbs {
65 my $self = shift;
66 my $tmp = shift;
67 my %self;
69 my $hash_options = DB_File::HASHINFO->new();
71 # Each of these hashes allow only unique keys
72 for my $dbname qw(IndexIt TopLevel Local2Global) {
73 my %h;
74 tie(%h,'DB_File',File::Spec->catfile($tmp,$dbname),
75 O_CREAT|O_RDWR,0666,$hash_options);
76 $self{$dbname} = \%h;
79 # The Parent2Child hash allows duplicate keys, so we
80 # create it with the R_DUP flag.
81 my $btree_options = DB_File::BTREEINFO->new();
82 $btree_options->{flags} = R_DUP;
83 my %h;
84 tie(%h,'DB_File',File::Spec->catfile($tmp,'Parent2Child'),
85 O_CREAT|O_RDWR,0666,$btree_options);
86 $self{Parent2Child} = \%h;
88 return \%self;
91 sub indexit {
92 my $self = shift;
93 my $id = shift;
94 $self->{IndexIt}{$id} = shift if @_;
95 return $self->{IndexIt}{$id};
98 sub toplevel {
99 my $self = shift;
100 my $id = shift;
101 $self->{TopLevel}{$id} = shift if @_;
102 return $self->{TopLevel}{$id};
105 sub each_toplevel {
106 my $self = shift;
107 my ($id) = each %{$self->{TopLevel}};
108 $id;
111 sub local2global {
112 my $self = shift;
113 my $id = shift;
114 $self->{Local2Global}{$id} = shift if @_;
115 return $self->{Local2Global}{$id};
118 sub add_children {
119 my $self = shift;
120 my $parent_id = shift;
121 # (@children) = @_;
122 $self->{Parent2Child}{$parent_id} = shift while @_;
125 sub children {
126 my $self = shift;
127 my $parent_id = shift;
129 my @children;
131 my $db = tied(%{$self->{Parent2Child}});
132 my $key = $parent_id;
133 my $value = '';
134 for (my $status = $db->seq($key,$value,R_CURSOR);
135 $status == 0 && $key eq $parent_id;
136 $status = $db->seq($key,$value,R_NEXT)
138 push @children,$value;
140 return wantarray ? @children: \@children;
143 # this acts like each() and returns each parent id and an array ref of children
144 sub each_family {
145 my $self = shift;
147 my $db = tied(%{$self->{Parent2Child}});
149 if ($self->{_cursordone}) {
150 undef $self->{_cursordone};
151 undef $self->{_parent};
152 undef $self->{_child};
153 return;
156 # do a slightly tricky cursor search
157 unless (defined $self->{_parent}) {
158 return unless $db->seq($self->{_parent},$self->{_child},R_FIRST) == 0;
161 my $parent = $self->{_parent};
162 my @children = $self->{_child};
164 my $status;
165 while (($status = $db->seq($self->{_parent},$self->{_child},R_NEXT)) == 0
166 && $self->{_parent} eq $parent
168 push @children,$self->{_child};
171 $self->{_cursordone}++ if $status != 0;
173 return ($parent,\@children);
176 sub local_ids {
177 my $self = shift;
178 my @ids = keys %{$self->{Local2Global}}
179 if $self->{Local2Global};
180 return \@ids;
183 sub loaded_ids {
184 my $self = shift;
185 my @ids = values %{$self->{Local2Global}}
186 if $self->{Local2Global};
187 return \@ids;