00001
00002 =head1 LICENSE
00003
00004 Copyright [1999-2016] EMBL-European Bioinformatics Institute
00005
00006 Licensed under the Apache License, Version 2.0 (the "License");
00007 you may not use this file except in compliance with the License.
00008 You may obtain a copy of the License at
00009
00010 http:
00011
00012 Unless required by applicable law or agreed to in writing, software
00013 distributed under the License is distributed on an "AS IS" BASIS,
00014 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 See the License for the specific language governing permissions and
00016 limitations under the License.
00017
00018 =cut
00019
00020 =pod
00021
00022 =head1 NAME
00023
00024 Bio::EnsEMBL::MetaData::DBSQL::BaseInfoAdaptor
00025
00026 =head1 DESCRIPTION
00027
00028 Base adaptor for storing and retrieving objects from MySQL genome_metadata database
00029
00030 Provides basic methods for store/fetch
00031
00032 =head1 AUTHOR
00033
00034 Dan Staines
00035
00036 =head1 SEE ALSO
00037
00038 Bio::EnsEMBL::MetaData::BaseInfo
00039
00040 =cut
00041
00042 package Bio::EnsEMBL::MetaData::DBSQL::BaseInfoAdaptor;
00043
00044 use strict;
00045 use warnings;
00046 use Carp qw(cluck croak);
00047 use Module::Load;
00048 use Bio::EnsEMBL::Utils::Argument qw( rearrange );
00049 use Bio::EnsEMBL::Utils::Exception qw/throw/;
00050 use List::MoreUtils qw/natatime/;
00051
00052 use base qw/Bio::EnsEMBL::DBSQL::BaseAdaptor/;
00053
00054 =head1 METHODS
00055 =head2 fetch_all
00056 Arg : (optional) if 1, expand children of genome info
00057 Description: Fetch all genome info
00058 Returntype : Bio::EnsEMBL::MetaData::GenomeInfo
00059 Exceptions : none
00060 Caller : general
00061 Status : Stable
00062 =cut
00063
00064 sub fetch_all {
00065 my ( $self, $keen ) = @_;
00066 return $self->_fetch_generic_with_args( {}, $keen );
00067 }
00068
00069 =head2 fetch_by_dbID
00070 Arg : ID of genome info
00071 Arg : (optional) if 1, expand children of genome info
00072 Description: Fetch genome info for specified ID
00073 Returntype : Bio::EnsEMBL::MetaData::GenomeInfo
00074 Exceptions : none
00075 Caller : internal
00076 Status : Stable
00077 =cut
00078
00079 sub fetch_by_dbID {
00080 my ( $self, $id, $keen ) = @_;
00081 return
00082 $self->_first_element( $self->_fetch_generic_with_args(
00083 { $self->_get_id_field(), $id }
00084 ),
00085 $keen );
00086 }
00087
00088 =head2 fetch_by_dbIDs
00089 Arg : IDs of genome info
00090 Arg : (optional) if 1, expand children of genome info
00091 Description: Fetch genome info for specified ID
00092 Returntype : Bio::EnsEMBL::MetaData::GenomeInfo
00093 Exceptions : none
00094 Caller : internal
00095 Status : Stable
00096 =cut
00097
00098 sub fetch_by_dbIDs {
00099 my ( $self, $ids, $keen ) = @_;
00100 my @genomes = ();
00101 my $it = natatime 1000, @{$ids};
00102 while ( my @vals = $it->() ) {
00103 my $sql =
00104 $self->_get_base_sql() . ' where ' . $self->_get_id_field() . ' in (' .
00105 join( ',', @vals ) . ')';
00106 @genomes = ( @genomes, @{ $self->_fetch_generic( $sql, [] ) } );
00107 }
00108 return \@genomes;
00109 }
00110
00111 =head1 INTERNAL METHODS
00112 =head2 _get_base_sql
00113 Description: Base SQL for fetching object - must be implemented
00114 Returntype : String
00115 Exceptions : none
00116 Caller : internal
00117 Status : Stable
00118 =cut
00119 sub _get_base_sql {
00120 throw("Method not implemented in base class");
00121 }
00122
00123 =head2 _get_id_field
00124 Description: Database column containing dbID - must be implemented
00125 Returntype : String
00126 Exceptions : none
00127 Caller : internal
00128 Status : Stable
00129 =cut
00130 sub _get_id_field {
00131 throw("Method not implemented in base class");
00132 }
00133
00134 =head2 _get_obj_class
00135 Description: Class of object retrieved - must be implemented
00136 Returntype : String
00137 Exceptions : none
00138 Caller : internal
00139 Status : Stable
00140 =cut
00141 sub _get_obj_class {
00142 throw("Method not implemented in base class");
00143 }
00144
00145 =head2 _fetch_generic_with_args
00146 Arg : hashref of arguments by column
00147 Arg : (optional) if set to 1, all children will be fetched
00148 Description: Instantiate a GenomeInfo from the database using a
00149 generic method, with the supplied arguments
00150 Returntype : Arrayref of Bio::EnsEMBL::MetaData::GenomeInfo
00151 Exceptions : none
00152 Caller : internal
00153 Status : Stable
00154 =cut
00155
00156 sub _fetch_generic_with_args {
00157 my ( $self, $args, $type, $keen ) = @_;
00158 my ( $sql, $params ) = $self->_args_to_sql( $self->_get_base_sql(), $args );
00159 my $info =
00160 $self->_fetch_generic( $sql, $params, $self->_get_obj_class(), $keen );
00161 return $info;
00162 }
00163
00164 =head2 _get_obj_class
00165 Description: Load children of object - no-op implementation, can be overridden
00166 Arg : Object to retrieve children for
00167 Returntype : non
00168 Exceptions : none
00169 Caller : internal
00170 Status : Stable
00171 =cut
00172 sub _fetch_children {
00173 my ( $self, $i ) = @_;
00174 # do nothing
00175 return;
00176 }
00177
00178 =head2 _args_to_sql
00179 Description: Add where clauses to SQL given arguments
00180 Arg : String - Base SQL
00181 Arg : Hashref - arguments
00182 Returntype : String
00183 Exceptions : none
00184 Caller : internal
00185 Status : Stable
00186 =cut
00187 sub _args_to_sql {
00188 my ( $self, $sql_in, $args ) = @_;
00189 my $sql = $sql_in;
00190 my $params = [];
00191 my $clause = '';
00192 while ( my ( $k, $v ) = each %$args ) {
00193 if ( $clause ne '' ) {
00194 $clause .= ' AND ';
00195 }
00196 if ( ref($v) eq 'ARRAY' ) {
00197 $clause .= "$k in (" . join( ',', map { '?' } @$v ) . ")";
00198 $params = [ @$params, @$v ];
00199 }
00200 else {
00201 $clause .= "$k = ?";
00202 push @$params, $v;
00203 }
00204 }
00205 if ( $clause ne '' ) {
00206 $sql .= ' where ' . $clause;
00207 }
00208 return ( $sql, $params );
00209 }
00210
00211 =head2 _fetch_generic
00212 Arg : SQL to use to fetch object
00213 Arg : arrayref of bind parameters
00214 Arg : (optional) if set to 1, all children will be fetched
00215 Description: Instantiate a GenomeInfo from the database using the specified SQL
00216 Returntype : Arrayref of Bio::EnsEMBL::MetaData::GenomeInfo
00217 Exceptions : none
00218 Caller : internal
00219 Status : Stable
00220 =cut
00221
00222 sub _fetch_generic {
00223 my ( $self, $sql, $params, $type, $keen ) = @_;
00224 if ( !defined $type ) {
00225 $type = $self->_get_obj_class();
00226 }
00227 my $mds = $self->{dbc}->sql_helper()->execute(
00228 -SQL => $sql,
00229 -USE_HASHREFS => 1,
00230 -CALLBACK => sub {
00231 my $row = shift @_;
00232 my $md = $self->_get_cached_obj( $type, $row->{dbID} );
00233 if ( !defined $md ) {
00234 load $type;
00235 $md = bless $row, $type;
00236 $md->adaptor($self);
00237 $self->_store_cached_obj($md);
00238 }
00239 return $md;
00240 },
00241 -PARAMS => $params );
00242 if ($keen) {
00243 for my $md ( @{$mds} ) {
00244 $self->_fetch_children( $md, $keen );
00245 }
00246 }
00247 return $mds;
00248 } ## end sub _fetch_generic
00249
00250 =head2 _get_division_id
00251 Arg : division name
00252 Description: Return ID for division, storing if required
00253 Returntype : none
00254 Exceptions : none
00255 Caller : internal
00256 Status : Stable
00257 =cut
00258
00259 my $division_names = { 'Ensembl' => 'E',
00260 'EnsemblGenomes' => 'EG',
00261 'EnsemblBacteria' => 'EB',
00262 'EnsemblMetazoa' => 'EM',
00263 'EnsemblPlants' => 'EPl',
00264 'EnsemblProtists' => 'EPr',
00265 'EnsemblFungi' => 'EF' };
00266
00267 sub _get_division_id {
00268 my ( $self, $division, $short_name ) = @_;
00269
00270 my $div_id = $self->_cache('division')->{$division};
00271
00272 if ( !defined $div_id ) {
00273
00274 $div_id = $self->{dbc}->sql_helper()->transaction(
00275 -CALLBACK => sub {
00276 my ($dbc) = @_;
00277 my $id;
00278 my $ids =
00279 $dbc->sql_helper()->execute_simple(
00280 -SQL => 'select division_id from division where name=?',
00281 -PARAMS => [$division] );
00282 if ( scalar(@$ids) == 0 ) {
00283 # not found so create
00284 if ( !defined $short_name ) {
00285 $short_name = $division_names->{$division};
00286 if ( !defined $short_name ) {
00287 $short_name = $division;
00288 $short_name =~ s/[a-z]+
00289 }
00290 }
00291 $dbc->sql_helper->execute_update(
00292 -SQL => 'insert into division (name,short_name) values(?,?)',
00293 -CALLBACK => sub {
00294 my ( $sth, $dbh, $rv ) = @_;
00295 $id = $dbh->{mysql_insertid};
00296 },
00297 -PARAMS => [ $division, $short_name ] );
00298 }
00299 else {
00300 $id = $ids->[0];
00301 }
00302 return $id;
00303 } );
00304 $self->_cache('division')->{$division} = $div_id;
00305 } ## end if ( !defined $div_id )
00306
00307 return $div_id;
00308 } ## end sub _get_division_id
00309
00310 =head2 _cache
00311 Arg : type of object for cache
00312 Description: Return internal cache for given type
00313 Returntype : none
00314 Exceptions : none
00315 Caller : internal
00316 Status : Stable
00317 =cut
00318
00319 sub _cache {
00320 my ( $self, $type ) = @_;
00321 if ( !defined $self->{cache} || !defined $self->{cache}{$type} ) {
00322 $self->{cache}{$type} = {};
00323 }
00324 return $self->{cache}{$type};
00325 }
00326
00327 =head2 _clear_cache
00328 Arg : (optional) type of object to clear
00329 Description: Clear internal cache (optionally just one type)
00330 Returntype : none
00331 Exceptions : none
00332 Caller : internal
00333 Status : Stable
00334 =cut
00335
00336 sub _clear_cache {
00337 my ( $self, $type ) = @_;
00338 if ( defined $type ) {
00339 $self->{cache}{$type} = {};
00340 }
00341 else {
00342 $self->{cache} = {};
00343 }
00344 return;
00345 }
00346
00347 =head2 _get_cached_obj
00348 Arg : type of object to retrieve
00349 Arg : ID of object to retrieve
00350 Description: Retrieve object from internal cache
00351 Returntype : object
00352 Exceptions : none
00353 Caller : internal
00354 Status : Stable
00355 =cut
00356
00357 sub _get_cached_obj {
00358 my ( $self, $type, $id ) = @_;
00359 return $self->_cache($type)->{$id};
00360 }
00361
00362 =head2 _store_cached_obj
00363 Arg : type of object to store
00364 Arg : object to store
00365 Description: Store object in internal cache
00366 Returntype : none
00367 Exceptions : none
00368 Caller : internal
00369 Status : Stable
00370 =cut
00371
00372 sub _store_cached_obj {
00373 my ( $self, $obj ) = @_;
00374 my $type = ref $obj;
00375 $self->_cache($type)->{ $obj->dbID() } = $obj;
00376 return;
00377 }
00378
00379 =head2 _first_element
00380 Arg : arrayref
00381 Description: Utility method to return the first element in a list, undef if empty
00382 Returntype : arrayref element
00383 Exceptions : none
00384 Caller : internal
00385 Status : Stable
00386 =cut
00387
00388 sub _first_element {
00389 my ( $self, $arr ) = @_;
00390 if ( defined $arr && scalar(@$arr) > 0 ) {
00391 return $arr->[0];
00392 }
00393 else {
00394 return undef;
00395 }
00396 }
00397
00398 1;