Translator.pm 5.95 KB
Newer Older
1 2
=head1 LICENSE

3
Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
Thomas Maurel's avatar
Thomas Maurel committed
4
Copyright [2016-2018] EMBL-European Bioinformatics Institute
5

6 7 8
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
9

10
     http://www.apache.org/licenses/LICENSE-2.0
11

12 13 14 15 16
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
17

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
=head1 NAME

Bio::EnsEMBL::IO::Translator - Base class for object translator

=head1 SYNOPSIS

  The class should not be directly instantiated, but derived to a subclass
  based on the object type being interrogated.

  use Bio::EnsEMBL::IO::Translator;

  my $translator = Bio::EnsEMBL::IO::Translator->new();

  my @values = $translator->batch_fields($object, @fields);
  my $value = $translator->get_field($object, 'fieldname');

  $translator->add_callbacks($ref_of_hash_of_callbacks);

36 37 38 39 40 41 42 43 44 45
  # There are two main ways to override callbacks for attributes

  # The first will use the given function name and attempt to call it on $self in
  # the translator, ie. $self->attribute_callback($object)
  $translator->add_callbacks( { attribute_name => 'attribute_callback' } );

  # The second, the callback can be a CODE reference, to call a method in a
  # different translator object you might do something like:
  $translator->add_callbacks( { attribute_name => sub { $other_translator->get_attribute(@_) } } );

46 47 48 49 50 51 52
=head1 Description

Base class for a translator, the purpose of a translator is to translate between the object types
being serialized and the writer. The translator for a specific object type should know how to
access the needed attributes requested by the writer, either directly from the object or if
more complicated lookups are needed how to do those lookups.

53 54 55 56 57 58
=cut

package Bio::EnsEMBL::IO::Translator;

use strict;
use warnings;
59 60
use Carp;

61 62
use Bio::EnsEMBL::Utils::ColourMap;

63
my %field_callbacks;
64 65 66 67

=head2 new

    Returntype   : Bio::EnsEMBL::IO::Translator
Anne Lyle's avatar
Anne Lyle committed
68 69 70
    Args[1]      : (optional) hashref - current valid key-value pairs:
                      no_exception => 1 (should be checked for wherever an exception could be thrown,
                                         and alternative web-friendly behaviour offered)
71
                      species_defs => EnsEMBL::Web::SpeciesDefs (can be used by webcode to specify feature colours)
72 73 74 75

=cut

sub new {
76
  my ($class, $args) = @_;
77
  
78
  my $self = $args || {};
79

80 81 82 83 84
  ## Note that colourmap can be used without SpeciesDefs,
  ## to do basic colour conversion between hex, RGB and named colours
  $self->{'colourmap'} = Bio::EnsEMBL::Utils::ColourMap->new($args->{'species_defs'});
  $self->{'default_colour'} = 'black';
             
85
  bless $self, $class;
86

87
  return $self;
88 89 90

}

91 92 93 94 95 96 97
=head2 
  
    Description : Getter for no_exception parameter 
    Returntype  : Boolean

=cut

98 99 100 101 102
sub no_exception {
  my $self = shift;
  return $self->{'no_exception'};
}

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
=head2 
  
    Description : Getter for ColourMap object, used for colour manipulation
    Returntype  : Bio::EnsEMBL::Utils::ColourMap

=cut

sub colourmap {
  my $self = shift;
  return $self->{'colourmap'};
}

=head2 
  
    Description : Getter/setter for default colour
    Returntype  : String

=cut

sub default_colour {
  my ($self, $colour) = @_;
  if ($colour) {
    $self->{'default_colour'} = $colour;
  }
  return $self->{'default_colour'};
}

130 131 132 133 134 135 136 137 138 139 140 141
=head2 
  
    Description : Getter for optional SpeciesDefs object, used to output feature colours from web
    Returntype  : EnsEMBL::Web::SpeciesDefs

=cut

sub species_defs {
  my $self = shift;
  return $self->{'species_defs'};
}

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
=head2 get_field

    Description: Fetch a field from the object, use the callback set by
                 derived classes to access the field from the object. If
                 the callback doesn't exist, return undef
    Args[1]    : Object to fetch fields from
    Args[2]    : Field name
    Returntype : String, hashref or undef

=cut

sub get_field {
    my $self = shift;
    my $object = shift;
    my $field = shift;

    # If we have the requested field, return it
    if(defined( $field_callbacks{$field} )) {
Anne Lyle's avatar
Anne Lyle committed
160 161 162 163 164
	    my $value;
	    if( ref($field_callbacks{$field}) eq 'CODE' ) {
	      $value = $field_callbacks{$field}($object);
	    } else {
	      my $callback = $field_callbacks{$field};
165
	      $value = $self->can($callback) ? $self->$callback($object) : undef;
Anne Lyle's avatar
Anne Lyle committed
166 167
	    }
	    return $value;
168 169 170
    }

    # If the field doesn't exist, return undef
Tiago Grego's avatar
Tiago Grego committed
171
    return;
172 173
}

174 175 176 177 178
=head2 batch_fields

    Description: Fetch a list of fields from the object in one call, fields are returned
                 in the same order requested
    Args[1]    : Object to fetch fields from
179
    Args[2]    : Arrayref, List of fields to return
180 181 182
    Returntype : Array

=cut
183

184 185 186 187 188 189 190 191 192
sub batch_fields {
    my $self = shift;
    my $object = shift;
    my $fields = shift;

    my @values;

    # Cycle through fields and fetch values
    foreach my $field (@{$fields}) {
Anne Lyle's avatar
Anne Lyle committed
193 194
	    my $value = $self->get_field($object, $field);
	    push @values, $value;
195 196 197
    }
    
    return @values;
198 199
}

200 201 202 203 204 205 206 207 208 209 210 211 212
=head2 add_callbacks

    Description: Add additional field callbacks to the translator
    Args[1]    : Hashref, list of fields and callbacks
    Returntype : None

=cut

sub add_callbacks {
    my $self = shift;
    my $callbacks = shift;

    @field_callbacks{ keys %$callbacks } = values %$callbacks;
213 214
}

215 216 217 218 219 220 221 222 223 224 225 226
=head2 fetch_callback

    Description: Fetch a field's callback, if set
    Args[1]    : Field name
    Returntype : String or undef

=cut

sub fetch_callback {
    my $self = shift;
    my $field = shift;

Anne Lyle's avatar
Anne Lyle committed
227
    # If we have the requested field, return it
228
    if(defined( $field_callbacks{$field} )) {
Anne Lyle's avatar
Anne Lyle committed
229
	    return $field_callbacks{$field};
230 231 232
    }

    # If the field doesn't exist, return undef
Tiago Grego's avatar
Tiago Grego committed
233
    return;
234 235
}

236
1;