Commit 5b7fb4a1 authored by Marek Szuba's avatar Marek Szuba
Browse files

RNAProduct: objects now hold type code rather than type ID

More useful, for instance for the upcoming implementation of
Transcript::get_all_RNAProducts() with type filtering. Drawback: must do
a join between rnaproduct and rnaproduct_type on all queries so that
RNAProductAdaptor has got something to put in this field.

Complete with relevant updates to RNAProductTypeMapper and its tests.
parent 96343caf
......@@ -95,7 +95,7 @@ sub fetch_all_by_Transcript {
assert_ref($transcript, 'Bio::EnsEMBL::Transcript');
return $self->_fetch_direct_query(['transcript_id', $transcript->dbID(), SQL_INTEGER]);
return $self->_fetch_direct_query(['rp.transcript_id', $transcript->dbID(), SQL_INTEGER]);
}
......@@ -204,7 +204,7 @@ sub fetch_by_dbID {
throw("dbID argument is required") unless defined($dbID);
return ($self->_fetch_direct_query(['rnaproduct_id', $dbID, SQL_INTEGER]))->[0];
return ($self->_fetch_direct_query(['rp.rnaproduct_id', $dbID, SQL_INTEGER]))->[0];
}
......@@ -226,7 +226,7 @@ sub fetch_by_stable_id {
throw("stable id argument is required") unless $stable_id;
return ($self->_fetch_direct_query(['stable_id', $stable_id, SQL_VARCHAR]))->[0];
return ($self->_fetch_direct_query(['rp.stable_id', $stable_id, SQL_VARCHAR]))->[0];
}
......@@ -308,9 +308,10 @@ sub _fetch_direct_query {
$self->db()->dbc()->from_date_to_seconds('modified_date');
my $sql =
sprintf("SELECT rnaproduct_id, rnaproduct_type_id, transcript_id, "
. "seq_start, seq_end, stable_id, version, %s, %s "
. "FROM rnaproduct "
sprintf("SELECT rp.rnaproduct_id, pt.code, rp.transcript_id, "
. "rp.seq_start, rp.seq_end, rp.stable_id, rp.version, %s, %s "
. "FROM rnaproduct rp JOIN rnaproduct_type pt "
. "ON rp.rnaproduct_type_id = pt.rnaproduct_type_id "
. "WHERE %s = ?",
$rp_created_date, $rp_modified_date, $where_args->[0]);
my $sth = $self->prepare($sql);
......@@ -339,7 +340,7 @@ sub _obj_from_sth {
my $sql_data = $sth->fetchall_arrayref();
my $transcript_adaptor = $self->db()->get_TranscriptAdaptor();
while (my $row_ref = shift @{$sql_data}) {
my ($rnaproduct_id, $rnaproduct_type_id, $transcript_id, $seq_start,
my ($rnaproduct_id, $type_code, $transcript_id, $seq_start,
$seq_end, $stable_id, $version, $created_date, $modified_date) =
@{$row_ref};
......@@ -349,10 +350,10 @@ sub _obj_from_sth {
}
my $class_name = Bio::EnsEMBL::Utils::RNAProductTypeMapper::mapper()
->type_id_to_class($rnaproduct_type_id);
->type_code_to_class($type_code);
my $rnaproduct = $class_name->new_fast( {
'dbID' => $rnaproduct_id,
'type_id' => $rnaproduct_type_id,
'type_code' => $type_code,
'adaptor' => $self,
'start' => $seq_start,
'end' => $seq_end,
......
......@@ -102,8 +102,8 @@ sub new { ## no critic (Subroutines::RequireArgUnpacking)
my $class = ref($caller) || $caller;
my $type_id = Bio::EnsEMBL::Utils::RNAProductTypeMapper::mapper()
->class_to_type_id($class);
my $type_code = Bio::EnsEMBL::Utils::RNAProductTypeMapper::mapper()
->class_to_type_code($class);
my ($seq_start, $seq_end, $stable_id, $version, $dbID, $adaptor, $seq,
$created_date, $modified_date ) =
......@@ -125,7 +125,7 @@ sub new { ## no critic (Subroutines::RequireArgUnpacking)
'seq' => $seq,
'created_date' => $created_date,
'modified_date' => $modified_date,
'type_id' => $type_id
'type_code' => $type_code,
}, $class;
$self->adaptor($adaptor);
......@@ -807,24 +807,26 @@ sub transcript {
}
=head2 type_id
=head2 type_code
Example : my $rp_type_id = $rnaproduct->type_id();
Example : my $rp_type_code = $rnaproduct->type_code();
Description: Getter for the RNAProduct type (e.g. miRNA, circRNA, ...).
The type is expressed as a numerical ID and it is up to the
user to look the details up in rnaproduct_type; it has been
implemented this way because at this point it hasn't been
decided whether we need to expose this to users at all.
Returntype : int
The type is expressed as human-readable code.
This is somewhat redundant because similar information can
be obtained simply by looking at the class of the object,
indeed type_code is not meant to be modified independently
of the class. However, there are certain use cases when the
latter are more convenient than the former.
Returntype : string
Exceptions : none
Caller : ?
Status : In Development
=cut
sub type_id {
sub type_code {
my $self = shift;
return $self->{'type_id'};
return $self->{'type_code'};
}
......
......@@ -43,7 +43,7 @@ users to call the mapper directly; it is invoked internally whenever
such mappings are needed (e.g. in RNAProduct constructor or in
RNAProductAdaptor).
Note that the type_id<->class_name mappings are hardcoded here,
Note that the type_code<->class_name mappings are hardcoded here,
specifically in the constructor, instead of being fetched from the
database. This is so that it is not possible for someone to trigger
construction of arbitrary objects by having modified class names
......@@ -53,8 +53,8 @@ stored in the database.
my $rpt_mapper = Bio::EnsEMBL::Utils::RNAProductTypeMapper->new();
my $class = $rpt_mapper->type_id_to_class( 1 );
my $type_id = $rpt_mapper->class_to_type_id( 'Bio::EnsEMBL::MicroRNA' );
my $class_name = $rpt_mapper->type_code_to_class( 'generic' );
my $type_code = $rpt_mapper->class_to_type_code( 'Bio::EnsEMBL::MicroRNA' );
=cut
......@@ -111,43 +111,43 @@ sub new {
# Declare this here rather than in the package scope so that the map
# cannot be modified (we do not presently use Readonly in the Core
# API code), accidentally or otherwise.
my $id_to_class_map = {
1 => 'Bio::EnsEMBL::RNAProduct',
2 => 'Bio::EnsEMBL::MicroRNA',
my $type_to_class_map = {
'generic' => 'Bio::EnsEMBL::RNAProduct',
'miRNA' => 'Bio::EnsEMBL::MicroRNA',
};
my $self = bless {
'id_to_class_map' => $id_to_class_map,
'class_to_id_map' => undef,
'type_to_class_map' => $type_to_class_map,
'class_to_type_map' => undef,
}, $class;
return $self;
}
=head2 class_to_type_id
=head2 class_to_type_code
Arg [1] : string $class_name - fully qualified rnaproduct class name
Example : my $type_id
= $mapper->class_to_type_id( 'Bio::EnsEMBL::MicroRNA' );
Example : my $type_code
= $mapper->class_to_type_code( 'Bio::EnsEMBL::MicroRNA' );
Description: For the given name of a class representing a mature RNA
product, returns the type ID used to reference it in the
product, returns the type code used to represent it in the
Ensembl database.
Returntype : int
Returntype : string
Exceptions : throw if the class does not represent known RNA-product type
Caller : internal
Status : Stable
=cut
sub class_to_type_id {
sub class_to_type_code {
my ( $self, $class_name ) = @_;
if ( !defined( $self->{'class_to_id_map'} ) ) {
if ( !defined( $self->{'class_to_type_map'} ) ) {
$self->_generate_reverse_map();
}
my %map = %{ $self->{'class_to_id_map'} };
my %map = %{ $self->{'class_to_type_map'} };
if ( !exists $map{$class_name} ) {
throw( "Unknown RNA-product class name " . $class_name );
}
......@@ -156,34 +156,34 @@ sub class_to_type_id {
}
=head2 type_id_to_class
=head2 type_code_to_class
Arg [1] : int $type_id - internal type identified of rnaproduct
Example : my $class_name = $mapper->class_to_type_id( 1 );
Description: For the type ID referencing a mature RNA product in the
Arg [1] : string $type_code - type code of rnaproduct
Example : my $class_name = $mapper->class_to_type_code( 1 );
Description: For the type code representing a mature RNA product in the
Ensembl database, return its API class name
Returntype : string
Exceptions : throw if the ID does not represent known RNA-product type
Exceptions : throw if the code does not represent known RNA-product type
Caller : internal
Status : Stable
=cut
sub type_id_to_class {
my ( $self, $type_id ) = @_;
sub type_code_to_class {
my ( $self, $type_code ) = @_;
my %map = %{ $self->{'id_to_class_map'} };
if ( !exists $map{$type_id} ) {
throw( "Unknown RNA-product type ID " . $type_id );
my %map = %{ $self->{'type_to_class_map'} };
if ( !exists $map{$type_code} ) {
throw( "Unknown RNA-product type ID " . $type_code );
}
return $map{$type_id};
return $map{$type_code};
}
# _generate_reverse_map
# Description: PRIVATE generates class_name->type_id map from the
# type_id->class_name one.
# Description: PRIVATE generates class_name->type_code map from the
# type_code->class_name one.
# Returntype : none
# Exceptions : none
# Caller : internal
......@@ -193,8 +193,8 @@ sub _generate_reverse_map {
my ($self) = @_;
# Safe to use reverse because both keys and values are unique
my %reversed_map = reverse %{$self->{'id_to_class_map'}};
$self->{'class_to_id_map'} = \%reversed_map;
my %reversed_map = reverse %{$self->{'type_to_class_map'}};
$self->{'class_to_type_map'} = \%reversed_map;
return;
}
......
......@@ -84,8 +84,8 @@ ok(test_getter_setter($rp, 'version', 13), 'Test getter/setter version()');
ok(test_getter_setter($rp, 'created_date', time()), 'Test getter/setter created_date()');
ok(test_getter_setter($rp, 'modified_date', time()), 'Test getter/setter modified_date()');
# FIXME: temporary, at least this way
is($rp->type_id(), 1, 'type_id is 1 (i.e. generic mature RNA)');
# FIXME: use RNAProductTypeMapper instead of hardcoded type code
is($rp->type_code(), 'generic', 'RNAProduct object has expected type code');
subtest 'Test stable_id_version() functionality' => sub {
ok(test_getter_setter($rp, 'stable_id_version', 3.14),
......@@ -211,8 +211,9 @@ $rp = undef;
$rp = $rp_a->fetch_by_stable_id('ENSM00000000001');
ok($rp, 'Can fetch RNAProduct by stable ID');
# FIXME: temporary, at least this way
is($rp->type_id(), 2, 'type_id is 2 (i.e. miRNA)');
# FIXME: use RNAProductTypeMapper instead of hardcodings
isa_ok($rp, 'Bio::EnsEMBL::MicroRNA', 'miRNA object from database');
is($rp->type_code(), 'miRNA', 'type_code is miRNA');
# FIXME: perform an in-depth inspection of one of the fetched RNAProducts,
# to make sure new_fast() call all of these fetch methods use does what it
......@@ -337,14 +338,14 @@ subtest 'RNAProductTypeMapper tests' => sub {
my $rpt_mapper2 = Bio::EnsEMBL::Utils::RNAProductTypeMapper->mapper();
is($rpt_mapper, $rpt_mapper2, 'mapper() reuses existing instance if present');
is($rpt_mapper->type_id_to_class(2), 'Bio::EnsEMBL::MicroRNA',
is($rpt_mapper->type_code_to_class('miRNA'), 'Bio::EnsEMBL::MicroRNA',
'Can map existing type ID to class');
dies_ok(sub { $rpt_mapper->type_id_to_class(34356); },
dies_ok(sub { $rpt_mapper->type_code_to_class('semprini'); },
'Exception thrown on unknown type ID');
is($rpt_mapper->class_to_type_id('Bio::EnsEMBL::RNAProduct'), 1,
is($rpt_mapper->class_to_type_code('Bio::EnsEMBL::RNAProduct'), 'generic',
'Can map existing class to type ID');
dies_ok(sub { $rpt_mapper->class_to_type_id('Bio::EnsEMBL::Storable'); },
dies_ok(sub { $rpt_mapper->class_to_type_code('Bio::EnsEMBL::Storable'); },
'Exception thrown on unknown rnaproduct class name');
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment