File Coverage

blib/lib/Bio/Taxonomy/GlobalNames.pm
Criterion Covered Total %
statement 144 162 88.8
branch 27 42 64.2
condition 13 18 72.2
subroutine 25 25 100.0
pod 2 8 25.0
total 211 255 82.7


line stmt bran cond sub pod time code
1             package Bio::Taxonomy::GlobalNames;
2              
3 2     2   126756 use 5.10.0;
  2         9  
  2         111  
4 2     2   11 use strict;
  2         5  
  2         66  
5 2     2   10 use warnings;
  2         13  
  2         69  
6              
7 2     2   2372 use JSON qw(encode_json);
  2         52509  
  2         12  
8 2     2   2465 use JSON::Parse qw(parse_json);
  2         2215  
  2         360  
9 2     2   1105 use LWP::UserAgent;
  2         120990  
  2         70  
10 2     2   2205 use Moo::Lax;
  2         97949  
  2         13  
11 2     2   7066 use REST::Client;
  2         14864  
  2         80  
12 2     2   2236 use Scalar::Readonly;
  2         1855  
  2         2498  
13              
14             =head1 NAME
15              
16             Bio::Taxonomy::GlobalNames - Perlish OO bindings to the L API
17              
18             =head1 VERSION
19              
20             Version 0.06
21              
22             =cut
23              
24             our $VERSION = '0.06';
25              
26             =head1 SYNOPSIS
27              
28             use Bio::Taxonomy::GlobalNames;
29              
30             # Provide the input data and parameters.
31             my $query = Bio::Taxonomy::GlobalNames->new(
32             names => $names,
33             data_source_ids => $data_source_ids,
34             resolve_once => $resolve_once,
35             );
36              
37             my $output = $query->post(); # Perform a POST request and return the output.
38              
39             # Go through the Output object.
40             my @data = @{ $output->data };
41              
42             foreach my $datum (@data)
43             {
44            
45             # Check if a non-empty Results arrayref was returned.
46             if ( my @results = @{ $datum->results } )
47             {
48              
49             # Parse the Results objects.
50             foreach my $result (@results)
51             {
52              
53             # Retrieve the canonical name and score for each result.
54             my $canonical_name = $result->canonical_form;
55             my $score = $result->score;
56             }
57             }
58             }
59              
60             =head1 DESCRIPTION
61              
62             B provides Perl objects and functions that
63             interface with the Global Names Resolver web service. Using a REST client,
64             input is sent to the service, whereas results are internally converted
65             from JSON format to nested objects and returned to the user.
66              
67             This module can be used for automated standardisation of species names,
68             according to a variety of sources that can be manually selected, if needed.
69             See also the example script, provided with this module.
70              
71             =head2 Attributes for Bio::Taxonomy::GlobalNames objects
72              
73             =over 1
74              
75             =item data
76              
77             A string with a list of names delimited by new lines.
78             You may optionally supply your local id for each name as:
79              
80             123|Parus major
81             125|Parus thruppi
82             126|Parus carpi
83              
84             Names in the response will contain your supplied ids, facilitating integration.
85              
86             B
87              
88             =item data_source_ids
89              
90             A string with a pipe-delimited list of data sources.
91             See the list of L.
92              
93             =item file
94              
95             A file B with a list of names delimited by new lines,
96             similar to the 'data' attribute.
97             This attribute is valid only when the post method is used.
98              
99             B
100              
101             =item names
102              
103             A string with a list of names delimited by either pipe "|" or tab "\t".
104             Use a pipe with the get method.
105              
106             B
107              
108             =item resolve_once
109              
110             A string with a boolean (true/false) value. Default: 'false'.
111             Find the first available match instead of matches across all data sources with all possible renderings of a name.
112              
113             When 'true', response is rapid but incomplete.
114              
115             =item with_context
116              
117             A string with a boolean (true/false) value. Default: 'true'.
118             Reduce the likelihood of matches to taxonomic homonyms.
119              
120             When 'true', a common taxonomic context is calculated for all supplied names
121             from matches in data sources that have classification tree paths.
122             Names out of determined context are penalized during score calculation.
123              
124             =back
125              
126             =cut
127              
128             ###############################################
129             # Main object attributes with rw permissions. #
130             ###############################################
131             has file => (
132             is => 'rw',
133             default => q{},
134             );
135              
136             has names => (
137             is => 'rw',
138             default => q{},
139             );
140              
141             has data => (
142             is => 'rw',
143             default => q{},
144             );
145              
146             has data_source_ids => (
147             is => 'rw',
148             default => q{},
149             );
150              
151             has resolve_once => (
152             is => 'rw',
153             default => 'false',
154             isa => sub {
155             die "resolve_once may be either true or false!\n"
156             unless $_[0] =~ /^true|false$/;
157             },
158             );
159              
160             has with_context => (
161             is => 'rw',
162             default => 'true',
163             isa => sub {
164             die "with_context may be either true or false!\n"
165             unless $_[0] =~ /^true|false$/;
166             },
167             );
168              
169             # Make sure that the website is up.
170             sub _check_status
171             {
172 5     5   12 my ($url) = @_;
173              
174 5         59 my $ua = LWP::UserAgent->new( timeout => 5 );
175 5         2060 my $response = $ua->get($url);
176 5 50       1089833 return $response->is_success ? 1 : 0;
177             }
178              
179             =head3 Methods for Bio::Taxonomy::GlobalNames objects
180              
181             =over 1
182              
183             =item B
184              
185             Performs a GET request and returns an C object.
186              
187             =back
188              
189             =cut
190              
191             sub get
192             {
193 2     2 1 135 my $self = shift;
194              
195 2         5 my $name;
196              
197             # Make sure that only one source of names was given.
198 2 100 66     48 if ( $self->names ne q{} && $self->data ne q{} )
    50          
199             {
200 1         125 die "The attributes 'names' and 'data' are mutually exclusive!\n";
201             }
202             elsif ( $self->names ne q{} )
203             {
204 0         0 my $proper_name = $self->names;
205              
206             # Substitute space with '+'.
207 0         0 $proper_name =~ s/ /+/g;
208 0         0 $name = '?names=' . $proper_name;
209             }
210             else
211             {
212 1         6 my $proper_data = $self->data;
213              
214             # Substitute space with '+'.
215 1         3 $proper_data =~ s/ /+/g;
216 1         4 $name = '?names=' . $proper_data;
217             }
218              
219 1         4 my $gnr_url;
220 1 50       6 if ( _check_status('http://resolver.globalnames.org/') )
    0          
221             {
222 1         64 $gnr_url = 'http://resolver.globalnames.org/name_resolvers.json';
223             }
224             elsif ( _check_status('http://resolver.globalnames.biodinfo.org') )
225             {
226 0         0 $gnr_url =
227             'http://resolver.globalnames.biodinfo.org/name_resolvers.json';
228             }
229             else
230             {
231 0         0 die "The Global Names Resolver website is down.\n";
232             }
233              
234             # Create the target url.
235 1         11 my $url =
236             $gnr_url
237             . $name
238             . '&resolve_once='
239             . $self->resolve_once
240             . '&with_context='
241             . $self->with_context
242             . '&data_source_ids='
243             . $self->data_source_ids;
244              
245             # Create the REST client and perform a GET request.
246 1         1342 my $rest_client = REST::Client->new();
247 1         2511 $rest_client->GET($url);
248              
249             # Parse the results in JSON format and return them
250             # as an Output object.
251 1         360717 return Bio::Taxonomy::GlobalNames::Output::format_results(
252             parse_json( $rest_client->responseContent() ) );
253             }
254              
255             =over 1
256              
257             =item B
258              
259             Performs a POST request and returns an C object.
260             If you are supplying an input file, you have to use the 'post' method.
261              
262             =back
263              
264             =cut
265              
266             sub post
267             {
268 5     5 1 1281 my $self = shift;
269              
270 5         185 my $body = {
271             'format' => 'json',
272             'data_source_ids' => $self->data_source_ids,
273             'resolve_once' => $self->resolve_once,
274             'with_context' => $self->with_context,
275             };
276              
277             # Check the number of valid name sources provided.
278 5         219 my $input_check = 0;
279              
280 5         44 my @input_data = ( $self->file, $self->names, $self->data );
281              
282 5         16 foreach (@input_data)
283             {
284              
285             # If the source is not empty, increment the counter.
286 15 100       51 if ( $_ ne q{} )
287             {
288 6         17 $input_check++;
289             }
290             }
291              
292             # If the counter is bigger than 1, die.
293 5 100 66     590 if ( $input_check > 1 )
    100          
    50          
294             {
295 1         11 die
296             "The attributes 'file', 'names' and 'data' are mutually exclusive!\n";
297             }
298             elsif ( $self->file ne q{} && -r $self->file )
299             {
300              
301             # If a readable file was provided, read its content.
302 3         21 local $/ = undef;
303 3     1   201 open my $fh, '<:encoding(UTF-8)', $self->file;
  1         10  
  1         2  
  1         9  
304              
305 3         17243 $body->{'data'} = <$fh>;
306              
307             # Remove single and double quotes from the file's contents.
308 3         210 $body->{'data'} =~ s/['"]//g;
309              
310 3         80 close $fh;
311             }
312             elsif ( $self->names ne q{} )
313             {
314 0         0 $body->{'names'} = $self->names;
315             }
316             else
317             {
318 1         5 $body->{'data'} = $self->data;
319             }
320              
321             # Inform the server that we're sending JSON encoded content.
322 4         17 my $headers = { Content_Type => 'application/json' };
323              
324 4         11 my $gnr_url;
325 4 50       17 if ( _check_status('http://resolver.globalnames.org/') )
    0          
326             {
327 4         925 $gnr_url = 'http://resolver.globalnames.org/name_resolvers';
328             }
329             elsif ( _check_status('http://resolver.globalnames.biodinfo.org') )
330             {
331 0         0 $gnr_url = 'http://resolver.globalnames.biodinfo.org/name_resolvers';
332             }
333             else
334             {
335 0         0 die "The Global Names Resolver website is down.\n";
336             }
337              
338             # Encode data to JSON format, create the REST client and perform
339             # a POST request.
340 4         2185 my $data = encode_json($body);
341 4         53 my $rest_client = REST::Client->new();
342 4         2567 $rest_client->POST( $gnr_url, ( $data, $headers ) );
343              
344             # Parse the results in JSON format and return them
345             # as an Output object.
346 4         2558320 return Bio::Taxonomy::GlobalNames::Output::format_results(
347             parse_json( $rest_client->responseContent() ) );
348             }
349              
350             =head2 Attributes for Output objects
351              
352             =over 1
353              
354             =item $output->context
355              
356             A C object, if 'with_context' parameter is set to true.
357              
358             =item $output->data
359              
360             An array reference of C objects, containing query input(s) and results.
361              
362             my @data = @{ $output->data };
363              
364             =item $output->data_sources
365              
366             An array reference of C objects, whose ids you used for name resolution.
367             If no data sources were given, the array reference is empty.
368              
369             my @data_sources = @{ $output->data_sources };
370              
371             =item $output->id
372              
373             The resolver request id. Your request is stored temporarily in the remote database and is assigned an id.
374              
375             =item $output->parameters
376              
377             A C object, containing the parameters of the query.
378              
379             =item $output->status B $output->message
380              
381             The final status of the request -- 'success' or 'failure'.
382              
383             =item $output->status_message
384              
385             The message associated with the status.
386              
387             =item $output->url
388              
389             The url at which you can access your results for 7 days.
390              
391             =back
392              
393             =cut
394              
395             package Bio::Taxonomy::GlobalNames::Output;
396              
397 2     2   32 use Moo::Lax;
  2         6  
  2         22  
398              
399             #################################################
400             # Output object attributes with ro permissions. #
401             #################################################
402             has status => ( is => 'ro', );
403             has data_sources => ( is => 'ro', );
404             has data => ( is => 'ro', );
405             has message => ( is => 'ro', );
406             has parameters => ( is => 'ro', );
407             has url => ( is => 'ro', );
408             has context => ( is => 'ro', );
409             has id => ( is => 'ro', );
410             has status_message => ( is => 'ro', );
411              
412             # Create an Output object with results and data as sub-objects.
413             sub format_results
414             {
415 5     5 0 3080 my ($input) = @_;
416              
417 5         34 my @elements = qw(
418             status data_sources data message
419             parameters url context id
420             status_message
421             );
422              
423             # If something isn't defined, set it as the empty string.
424 5         21 foreach (@elements)
425             {
426              
427             # Avoid readonly variables caused by JSON conversion.
428 45 50       170 if ( Scalar::Readonly::readonly( $input->{$_} ) )
429             {
430 0         0 Scalar::Readonly::readonly_off( $input->{$_} );
431             }
432 45   100     213 $input->{$_} //= q{};
433             }
434              
435             # Build the object.
436 5         32 my $results_object = Bio::Taxonomy::GlobalNames::Output->new(
437             'status' => $input->{'status'},
438             'data_sources' =>
439             Bio::Taxonomy::GlobalNames::Output::DataSources::object(
440             $input->{'data_sources'}
441             ),
442             'data' =>
443             Bio::Taxonomy::GlobalNames::Output::Data::object( $input->{'data'} ),
444             'message' => $input->{'message'},
445             'parameters' => Bio::Taxonomy::GlobalNames::Output::Parameters::object(
446             $input->{'parameters'}
447             ),
448             'url' => $input->{'url'},
449             'context' => Bio::Taxonomy::GlobalNames::Output::Context::object(
450             $input->{'context'}
451             ),
452             'id' => $input->{'id'},
453             'status_message' => $input->{'status_message'}
454             );
455              
456 5         3963 return $results_object;
457             }
458              
459             =head2 Attributes for Data objects
460              
461             =over 1
462              
463             =item $datum->results
464              
465             An array reference of C objects.
466              
467             my @results = @{ $datum->results };
468              
469             =item $datum->supplied_id
470              
471             The id of the name string in the query (if provided).
472              
473             =item $datum->supplied_name_string
474              
475             The name string in the query.
476              
477             =back
478              
479             =cut
480              
481             package Bio::Taxonomy::GlobalNames::Output::Data;
482              
483 2     2   2599 use Moo::Lax;
  2         7  
  2         12  
484              
485             #################################################
486             # Data object attributes with ro permissions. #
487             #################################################
488             has supplied_name_string => ( is => 'ro', );
489             has supplied_id => ( is => 'ro', );
490             has results => ( is => 'ro', );
491              
492             # Create an array of Data objects.
493             sub object
494             {
495 5     5 0 14 my ($input) = @_;
496              
497 5         7 my @results;
498              
499             # If the input is empty, set it as an empty array.
500 5 100       23 if ( $input eq q{} )
501             {
502 3         8 $input = [];
503             }
504              
505             # If the arrayref isn't empty...
506 5         11 foreach my $species ( @{$input} )
  5         17  
507             {
508              
509             # If something isn't defined, set it as the empty string.
510 3         10 for ( 'supplied_name_string', 'supplied_id', 'results' )
511             {
512              
513             # Avoid readonly variables caused by JSON conversion.
514 9 50       41 if ( Scalar::Readonly::readonly( $species->{$_} ) )
515             {
516 0         0 Scalar::Readonly::readonly_off( $species->{$_} );
517             }
518 9   100     50 $species->{$_} //= q{};
519             }
520              
521             # Create the object.
522 3         51 my $resulting_object = Bio::Taxonomy::GlobalNames::Output::Data->new(
523             'supplied_name_string' => $species->{'supplied_name_string'},
524             'supplied_id' => $species->{'supplied_id'},
525             'results' =>
526             Bio::Taxonomy::GlobalNames::Output::Data::Results::object(
527             $species->{'results'}
528             ),
529             );
530 3         1578 push @results, $resulting_object;
531             }
532              
533 5         294 return \@results;
534             }
535              
536             =head2 Attributes for Results objects
537              
538             =over 1
539              
540             =item $result->canonical_form
541              
542             A "canonical" version of the name generated by the Global Names parser.
543              
544             =item $result->classification_path
545              
546             Tree path to the root if a name string was found within a data source classification.
547              
548             =item $result->classification_path_ids
549              
550             Tree path to the root using taxon_ids, if a name string was found within a data source classification.
551              
552             =item $result->classification_path_ranks
553              
554             =item $result->data_source_id
555              
556             The id of the data source where a name was found.
557              
558             =item $result->data_source_title
559              
560             The title of the data source where a name was found.
561              
562             =item $result->gni_uuid
563              
564             An identifier for the found name string used in Global Names.
565              
566             =item $result->local_id
567              
568             Shows id local to the data source (if provided by the data source manager).
569              
570             =item $result->match_type
571              
572             Explains how resolver found the name.
573             If the resolver cannot find names corresponding to the entire queried name string,
574             it sequentially removes terminal portions of the name string until a match is found.
575              
576             1 - Exact match
577              
578             2 - Exact match by canonical form of a name
579              
580             3 - Fuzzy match by canonical form
581              
582             4 - Partial exact match by species part of canonical form
583              
584             5 - Partial fuzzy match by species part of canonical form
585              
586             6 - Exact match by genus part of a canonical form
587              
588             =item $result->name_string
589              
590             The name string found in this data source.
591              
592             =item $result->prescore
593              
594             Displays points used to calculate the score delimited by '|' --
595             "Match points|Author match points|Context points".
596             Negative points decrease the final result.
597              
598             =item $result->score
599              
600             A confidence score calculated for the match.
601             0.5 means an uncertain result that will require investigation.
602             Results higher than 0.9 correspond to 'good' matches.
603             Results between 0.5 and 0.9 should be taken with caution.
604             Results less than 0.5 are likely poor matches.
605             The scoring is described in more details at L.
606              
607             =item $result->taxon_id
608              
609             An identifier supplied in the source Darwin Core Archive for the name string record.
610              
611             =back
612              
613             =cut
614              
615             package Bio::Taxonomy::GlobalNames::Output::Data::Results;
616              
617 2     2   3432 use Moo::Lax;
  2         4  
  2         20  
618              
619             ##################################################
620             # Results object attributes with ro permissions. #
621             ##################################################
622             has data_source_title => ( is => 'ro', );
623             has match_type => ( is => 'ro', );
624             has gni_uuid => ( is => 'ro', );
625             has taxon_id => ( is => 'ro', );
626             has classification_path_ids => ( is => 'ro', );
627             has canonical_form => ( is => 'ro', );
628             has name_string => ( is => 'ro', );
629             has score => ( is => 'ro', );
630             has prescore => ( is => 'ro', );
631             has classification_path => ( is => 'ro', );
632             has classification_path_ranks => ( is => 'ro', );
633             has data_source_id => ( is => 'ro', );
634             has local_id => ( is => 'ro', );
635              
636             # Create an array of Results objects.
637             sub object
638             {
639 3     3 0 8 my ($input) = @_;
640              
641 3         17 my @array = qw(
642             data_source_title match_type
643             gni_uuid taxon_id
644             classification_path_ids canonical_form
645             name_string score
646             prescore classification_path
647             classification_path_ranks data_source_id
648             local_id
649             );
650              
651 3         7 my @results;
652              
653             # If the input is empty, set it as an empty array.
654 3 100       12 if ( $input eq q{} )
655             {
656 1         3 $input = [];
657             }
658              
659             # If the arrayref isn't empty...
660 3         6 foreach my $hit ( @{$input} )
  3         8  
661             {
662              
663             # If something isn't defined, set it as the empty string.
664 116         220 foreach (@array)
665             {
666              
667             # Avoid readonly variables caused by JSON conversion.
668 1508 50       22566 if ( Scalar::Readonly::readonly( $hit->{$_} ) )
669             {
670 0         0 Scalar::Readonly::readonly_off( $hit->{$_} );
671             }
672 1508   100     4942 $hit->{$_} //= q{};
673             }
674              
675             # Create the object.
676 116         13543 my $resulting_object =
677             Bio::Taxonomy::GlobalNames::Output::Data::Results->new(
678             'data_source_title' => $hit->{'data_source_title'},
679             'match_type' => $hit->{'match_type'},
680             'gni_uuid' => $hit->{'gni_uuid'},
681             'taxon_id' => $hit->{'taxon_id'},
682             'classification_path_ids' => $hit->{'classification_path_ids'},
683             'canonical_form' => $hit->{'canonical_form'},
684             'name_string' => $hit->{'name_string'},
685             'score' => $hit->{'score'},
686             'prescore' => $hit->{'prescore'},
687             'classification_path' => $hit->{'classification_path_ranks'},
688             'data_source_id' => $hit->{'data_source_id'},
689             'local_id' => $hit->{'local_id'},
690             );
691 116         21349 push @results, $resulting_object;
692             }
693              
694 3         116 return \@results;
695             }
696              
697             =head2 Attributes for DataSources objects
698              
699             =over 1
700              
701             =item $data_source->id
702              
703             The ID of the data source.
704              
705             =item $data_source->title
706              
707             The name of the data source.
708              
709             =back
710              
711             =cut
712              
713             package Bio::Taxonomy::GlobalNames::Output::DataSources;
714              
715 2     2   2820 use Moo::Lax;
  2         4  
  2         12  
716              
717             ######################################################
718             # DataSources object attributes with ro permissions. #
719             ######################################################
720             has title => ( is => 'ro', );
721             has id => ( is => 'ro', );
722              
723             # Create an array of DataSources objects.
724             sub object
725             {
726 5     5 0 14 my ($input) = @_;
727              
728 5         7 my @results;
729              
730             # If the input is empty, set it as the empty array.
731 5 50       29 if ( $input eq q{} )
732             {
733 0         0 $input = [];
734             }
735              
736             # If the arrayref isn't empty...
737 5         11 foreach my $source ( @{$input} )
  5         17  
738             {
739              
740             # If something isn't defined, set it as the empty string.
741 0         0 foreach ( 'title', 'id' )
742             {
743              
744             # Avoid readonly variables caused by JSON conversion.
745 0 0       0 if ( Scalar::Readonly::readonly( $source->{$_} ) )
746             {
747 0         0 Scalar::Readonly::readonly_off( $source->{$_} );
748             }
749 0   0     0 $source->{$_} //= q{};
750             }
751              
752             # Create the object.
753 0         0 my $resulting_object =
754             Bio::Taxonomy::GlobalNames::Output::DataSources->new(
755             'title' => $source->{'title'},
756             'id' => $source->{'id'},
757             );
758 0         0 push @results, $resulting_object;
759             }
760              
761 5         33 return \@results;
762             }
763              
764             =head2 Attributes for Parameters objects
765              
766             =over 1
767              
768             =item $parameters->best_match_only
769              
770             =item $parameters->data_sources
771              
772             An array reference of data source ids you used for name resolution. If no data sources were given, the arrayref is empty.
773              
774             my @data_sources = @{ $parameters->data_sources };
775              
776             =item $parameters->header_only
777              
778             =item $parameters->preferred_data_sources
779              
780             =item $parameters->resolve_once
781              
782             True if 'resolve_once' parameter is set to true and vice versa.
783              
784             =item $parameters->with_context
785              
786             True if 'with_context' parameter is set to true and vice versa.
787              
788             =back
789              
790             =cut
791              
792             package Bio::Taxonomy::GlobalNames::Output::Parameters;
793              
794 2     2   1724 use Moo::Lax;
  2         4  
  2         8  
795              
796             #####################################################
797             # Parameters object attributes with ro permissions. #
798             #####################################################
799             has best_match_only => ( is => 'ro', );
800             has resolve_once => ( is => 'ro', );
801             has data_sources => ( is => 'ro', );
802             has header_only => ( is => 'ro', );
803             has with_context => ( is => 'ro', );
804             has preferred_data_sources => ( is => 'ro', );
805              
806             # Create the Parameters object.
807             sub object
808             {
809 5     5 0 14 my ($input) = @_;
810              
811 5         25 my @array = qw(
812             best_match_only resolve_once
813             data_sources header_only
814             with_context preferred_data_sources
815             );
816              
817             # If something isn't defined, set it as the empty string.
818 5         17 foreach (@array)
819             {
820              
821             # Avoid readonly variables caused by JSON conversion.
822 30 100       100 if ( Scalar::Readonly::readonly( $input->{$_} ) )
823             {
824 2         8 Scalar::Readonly::readonly_off( $input->{$_} );
825             }
826 30   50     102 $input->{$_} //= q{};
827             }
828              
829             # Create the object.
830 5         423 my $result = Bio::Taxonomy::GlobalNames::Output::Parameters->new(
831             'best_match_only' => $input->{'best_match_only'},
832             'resolve_once' => $input->{'resolve_once'},
833             'data_sources' => $input->{'data_sources'},
834             'header_only' => $input->{'header_only'},
835             'with_context' => $input->{'with_context'},
836             'preferred_data_sources' => $input->{'preferred_data_sources'},
837             );
838              
839 5         32156 return $result;
840             }
841              
842             =head2 Attributes for Context objects
843              
844             =over 1
845              
846             =item $context->context_clade
847              
848             A lowest taxonomic level in the data source that contains 90% or more of all names found.
849             If there are too few names to determine, this element remains empty.
850              
851             =item $context->context_data_source_id
852              
853             The id of a data source used to create the context.
854              
855             =back
856              
857             =cut
858              
859             package Bio::Taxonomy::GlobalNames::Output::Context;
860              
861 2     2   1821 use Moo::Lax;
  2         5  
  2         10  
862              
863             ##################################################
864             # Context object attributes with ro permissions. #
865             ##################################################
866             has context_data_source_id => ( is => 'ro', );
867             has context_clade => ( is => 'ro', );
868              
869             # Create a Context object.
870             sub object
871             {
872 5     5 0 17 my ($input) = @_;
873              
874             # If the input is empty, set it as the empty array.
875 5 100       31 if ( $input eq q{} )
876             {
877 3         8 $input = [];
878             }
879              
880             # If something isn't defined, set it as the empty string.
881 5         15 foreach ( 'context_data_source_id', 'context_clade' )
882             {
883              
884             # Avoid readonly variables caused by JSON conversion.
885 10 100       57 if ( Scalar::Readonly::readonly( $input->[0]->{$_} ) )
886             {
887 1         6 Scalar::Readonly::readonly_off( $input->[0]->{$_} );
888             }
889 10   100     68 $input->[0]->{$_} //= q{};
890             }
891              
892             # Create the object.
893 5         510 my $result = Bio::Taxonomy::GlobalNames::Output::Context->new(
894             'context_data_source_id' => $input->[0]->{'context_data_source_id'},
895             'context_clade' => $input->[0]->{'context_clade'},
896             );
897              
898 5         2053 return $result;
899             }
900              
901             =head1 AUTHOR
902              
903             Dimitrios - Georgios Kontopoulos, C<< >>
904              
905             =head1 BUGS
906              
907             Please report any bugs or feature requests to C, or through
908             the web interface at L.
909              
910             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
911              
912             =head1 SUPPORT
913              
914             More details about Global Names Resolver's algorithm can be obtained from
915             its L.
916              
917             You can find documentation for this module with the perldoc command.
918              
919             perldoc Bio::Taxonomy::GlobalNames
920              
921             You can also look for information at:
922              
923             =over 4
924              
925             =item * RT: CPAN's request tracker (report bugs here)
926              
927             L
928              
929             =item * AnnoCPAN: Annotated CPAN documentation
930              
931             L
932              
933             =item * CPAN Ratings
934              
935             L
936              
937             =item * Search MetaCPAN
938              
939             L
940              
941             =item * GitHub
942              
943             L
944              
945             =back
946              
947             =head1 LICENSE AND COPYRIGHT
948              
949             Copyright 2013-14 Dimitrios - Georgios Kontopoulos.
950              
951             This program is free software; you can redistribute it and/or modify it
952             under the same terms as Perl itself.
953              
954             =cut
955              
956             1; # End of Bio::Taxonomy::GlobalNames