# -*- mode: cperl -*- ################################################################ # Synergizer::DemoClient # # Copyright (c) 2009 President and Fellows of Harvard College # and Gabriel F. Berriz. All rights # reserved. ################################################################ $Synergizer::DemoClient::VERSION = '0.02'; use strict; use warnings FATAL => 'all'; no warnings 'once'; { package Synergizer::DemoClient; use Exporter 'import'; our @EXPORT_OK = qw( translate cull fmt ); our %EXPORT_TAGS = ( all => \@EXPORT_OK, std => \@EXPORT_OK ); use constant SERVER_URL => 'http://llama.mshri.on.ca/cgi/synergizer/serv'; use LWP::UserAgent; use JSON::XS qw( encode_json decode_json ); sub translate { my $args = shift; my $call = +{ method => 'translate', params => [ $args ], id => 0 }; my $data = _post( $call ); my $error = $data->{ error }; if ( $error ) { die 'server error: ' . $error->{ message }; } return wantarray ? @{ $data->{ result } } : $data->{ result }; } sub cull { my $translated = shift; my @unrecognized; for ( my $i = $#$translated; $i >= 0; --$i ) { my $t = $translated->[ $i ]; if ( _is_unrecognized( $t ) ) { splice @{ $translated }, $i, 1; unshift @unrecognized, _from( $t ); } } return @unrecognized; } sub fmt { my $row = shift; my $from = _from( $row ); my $to = _is_unrecognized( $row ) ? '!?' : join ' | ', _to( $row ); return "$from\t$to\n"; } sub _post { my $call = shift; my $req_content = encode_json( $call ); my $ua = LWP::UserAgent->new; my $res = $ua->post( SERVER_URL, 'Content' => $req_content, 'Content-Type' => 'application/json', 'Content-Length' => length( $req_content ) ); if ( $res->is_success ) { my $res_content = $res->content; if ( defined( $res_content ) ) { return decode_json( $res_content ); } } die 'server error'; } sub _is_unrecognized { my $r = $_[ 0 ]; return @$r == 2 && ! defined $r->[ 1 ]; } sub _from { return $_[ 0 ][ 0 ]; } sub _to { my $row = shift; return _is_unrecognized( $row ) ? ( undef ) : @{ $row }[ 1 .. $#$row ]; } } 1; __END__ =begin notes =end notes =head1 NAME Synergizer::DemoClient - a simple Synergizer client module =head1 SYNOPSIS use Synergizer::DemoClient ':all'; my $args = +{ authority => 'ensembl', species => 'Homo sapiens', domain => 'hgnc_symbol', range => 'entrezgene', ids => [ qw( c1ql4 scn5A IL1RL1 il1rl1 ?test? pxn RORC MYC lnx1 ) ] }; my $translated = translate( $args ); my @unrecognized = cull( $translated ); print fmt( $_ ) for @$translated; print "\unrecognized:\n"; print "$_\n" for @unrecognized; =head1 DESCRIPTION Synergizer::DemoClient illustrates the essential steps in writing a Synergizer client, focusing on the C method of the Synergizer API. It has only two external dependencies: the excellent Perl module JSON::XS to encode and decode Perl to and from JSON, and the standard Perl module LWP::UserAgent. Note that this is a bare-bones client with minimal functionality, for demonstration purposes only. This documentation presupposes some familiarity with Perl and with the contents of the Synergizer documentation page at http://llama.mshri.on.ca/synergizer/doc. =head1 METHODS =head2 translate( $args ) Briefly, this method takes as its single argument a reference to hash that has five required keys, and returns an array of translations. For more details, please see the Synergizer documentation page. The five required items in the input hash ref are: =head3 authority A string representing the name of the desired authority. E.g. 'ensembl', 'ncbi'. =head3 species A string representing the name of the desired species. E.g. 'Homo sapiens', 'Mus musculus'. =head3 domain A string representing the name of the namespace to translate from. E.g. 'embl', 'ipi'. =head3 range A string representing the name of the namespace to translate to. E.g. 'ipi', 'embl'. =head3 ids A reference to an array of strings, representing database identifiers in the namespace designated via the C field. The easiest way to find out what are the valid values for the first four fields, please look at the menu options in the Synergizer interactive web tool, at http://llama.mshri.on.ca/synergizer/translate. The C method returns an array of arrays, either of the form [ INPUT_ID, TRANSLATE_1, TRANSLATE_2, ..., TRANSLATE_N ] or [ INPUT_ID, undef ] The first form corresponds to the case where C indeed belongs to the requested domain namespace (for the requested species, and according to the requested authority). Note that in this case the number of translates can be zero, in which case the array would consist only of the input id. The second form always consists of two elements, of which the second one is always C. It corresponds to the case where the Synergizer was not able to locate INPUT_ID in the specified domain namespace (for the requested species, and according to the requested authority). The returned array preserves the order of the original the identifiers passed through the C field. Therefore, using the definitions given in the SYNOPSIS, map $_->[ 0 ], translate( $args ); should produce an array equivalent to @{ $args->{ ids } } =head2 cull( array_ref ) This method takes as its argument a reference to an array returned by C, and removes from this array all the entries corresponding to IDs that were not recognized as belonging to the specified domain namespace. The input identifiers extracted from the removed entries are returned to the caller as an array. =head2 fmt( array_ref ) This method takes as input one of the elements of the array returned by C and returns a formatted string representation of it. This representation has the form INPUT_IDTRANSLATE_1 | TRANSLATE_2 | ... | TRANSLATE_N or INPUT_ID!? corresponding to the two output cases described under the documentation for C. =head1 INTERNAL METHODS =head2 _post( hash_ref ) This method is the core of the module's functionality. It takes as input a hash reference of the form { method => , params => [ , , ... ], id => } where C is the name of some method in the Synergizer API, C, C, ... C are Perl scalars corresponding to its arguments, and is any integer. (The last argument is included to conform to the current proposals for JSON-RPC standard, but it is currently not used, so any integer will do.) The method returns the Perl representation of the returned JSON object, which should be a hash of the form { result => , error => undef, id => } on success, and { result => undef, error => { code => message => , }, id => } (More details on the semantics of this structure can be found in the current version of the JSON-RPC standard.) As written, the C<_post> method is quite general; it should be able to handle any method in the Synergizer API, not just C. =head2 _is_unrecognized( array_ref ) This method takes as input one of the elements of the array returned by C. It tests whether its argument corresponds to an unrecognized input ID (for the request authority, species, and domain namespace), and returns the resulting boolean value. =head2 _from( array_ref ) This method takes as input one of the elements of the array returned by C, and returns its input ID. =head2 _to( array_ref ) This method takes as input one of the elements of the array returned by C, and returns either a (possibly empty) list of the translates contained in the argument, or the value undefined (when the corresponding input ID is not recognized). =head1 DEPENDENCIES =over =item LWP::UserAgent =item JSON::XS =back =begin comment =head1 TO DO ... =head1 CHANGES =over =item ... =item ... =back =end comment =head1 AUTHOR Gabriel Berriz =begin comment =head1 SEE ALSO ... =head1 APPENDIX ... =end comment =cut