File Coverage

blib/lib/Webservice/InterMine/Simple/Query.pm
Criterion Covered Total %
statement 9 92 9.7
branch 0 48 0.0
condition 0 8 0.0
subroutine 3 15 20.0
pod 11 11 100.0
total 23 174 13.2


line stmt bran cond sub pod time code
1             package Webservice::InterMine::Simple::Query;
2              
3 1     1   6 use strict;
  1         1  
  1         33  
4 1     1   3033 use URI;
  1         13518  
  1         63  
5              
6 1     1   16 use constant 'RESOURCE_PATH' => '/query/results';
  1         4  
  1         2279  
7              
8             =head1 NAME
9              
10             Webservice::InterMine::Simple::Query
11              
12             =head1 SYNOPSIS
13              
14             my $query = $service->new_query;
15              
16             $query->add_view("Organism.shortName", "Organism.taxonId");
17             $query->add_constraint({path => "Organism.genus", op => "=", value => "Rattus"});
18              
19             @rows = $query2->results_table;
20             for my $row (@rows) {
21             print "name: $row->[0], id: $row->[1]\n";
22             }
23              
24             =head1 DESCRIPTION
25              
26             This is a basic representation of a query. It can handle straight-forward
27             requests and result sets, but for anything more complicated, we recommend you look
28             as the more fully featured L. This is especially true of
29             large data sets, as this implementation has the potential to use lots of memory when
30             receiving and processing results.
31              
32             =head1 METHODS
33              
34             =head2 new - Construct a new query.
35              
36             Create a new blank query.
37              
38             =cut
39              
40             sub new {
41 0     0 1   my $class = shift;
42 0           my $self = {@_};
43 0   0       $self->{model} ||= "genomic";
44 0   0       $self->{view} ||= "";
45 0   0       $self->{joins} ||= [];
46 0   0       $self->{constraints} ||= [];
47 0           return bless $self, $class;
48             }
49              
50             =head2 new_from_xml - Construct a new query from xml
51              
52             Read in an existing query from a string or a file.
53              
54             Parameters:
55              
56             =over
57              
58             =item * source_file => $file_name
59              
60             The name of the file to read in.
61              
62             =item * source_string => $xml
63              
64             The xml that represents the query.
65              
66             =back
67              
68             =cut
69              
70             sub new_from_xml {
71 0     0 1   my $class = shift;
72 0           my $self = $class->new(@_);
73 0 0         if (my $file = $self->{source_file}) {
74 0 0         open (my $xml_fh, '<', $file) or die "Could not open $file, $!";
75 0           $self->{xml} = join('', <$xml_fh>);
76 0 0         close $xml_fh or die "Could not close $file, $!";
77             } else {
78 0 0         $self->{xml} = $self->{source_string} or die "No xml source supplied";
79             }
80 0           return $self;
81             }
82              
83             =head2 add_view($col1, $col2)
84              
85             Add one or more output columns to the query. These must be fully qualified,
86             legal path-strings. No validation will be performed.
87              
88             =cut
89              
90             sub add_view {
91 0     0 1   my $self = shift;
92 0 0         die "Cannot alter a query you have read in from xml" if $self->{xml};
93 0           $self->{view} .= join(' ', @_);
94             }
95              
96             =head2 add_constraint([ $href | %parameters])
97              
98             Add a constraint to the query. The constraint may be represented either as
99             a hash-reference, or as a list of parameters.
100              
101             $query->add_constraint(path => "Organism.species", op => "=", value => "melanogaster")
102              
103             =cut
104              
105             sub add_constraint {
106 0     0 1   my $self = shift;
107 0 0         die "Cannot alter a query you have read in from xml" if $self->{xml};
108 0 0         my $constraint = (ref $_[0]) ? shift : {@_};
109 0           push @{$self->{constraints}}, $constraint;
  0            
110             }
111              
112             =head2 add_join([ $href | %parameters])
113              
114             Add a join to the query. The join may be represented either as
115             a hash-reference, or as a list of parameters.
116              
117             $query->add_join(path => "Gene.proteins", style => "OUTER")
118              
119             =cut
120              
121             sub add_join {
122 0     0 1   my $self = shift;
123 0 0         die "Cannot alter a query you have read in from xml" if $self->{xml};
124 0 0         my $join = (ref $_[0]) ? shift : {@_};
125 0           push @{$self->{joins}}, $join;
  0            
126             }
127              
128             =head2 set_logic($logic)
129              
130             Set the constraint logic of the query. The logic must be represented as a
131             legal logic string. No validation will be done.
132              
133             =cut
134              
135             sub set_logic {
136 0     0 1   my $self = shift;
137 0 0         die "Cannot alter a query you have read in from xml" if $self->{xml};
138 0           $self->{logic} = shift;
139             }
140              
141             =head2 set_sort_order(@list_of_elements)
142              
143             Set the sort order for the query. The sort order should be composed of pairs
144             of paths and directions:
145              
146             $query->set_sort_order("Organism.genus asc Organism.species desc");
147              
148             =cut
149              
150             sub set_sort_order {
151 0     0 1   my $self = shift;
152 0 0         die "Cannot alter a query you have read in from xml" if $self->{xml};
153 0           $self->{sort_order} = join(' ', @_);
154             }
155              
156             sub _get_uri {
157 0     0     my $self = shift;
158 0           my $uri = URI->new($self->{service}{root} . RESOURCE_PATH);
159 0           return $uri;
160             }
161              
162             my %safe_version_of = (
163             '=' => '=',
164             'eq' => '=',
165             '>' => '>',
166             'gt' => '>',
167             '<' => '<',
168             'lt' => '<',
169             '!=' => '!=',
170             'ne' => '!=',
171             '>=' => '≥',
172             'ge' => '≥',
173             '<=' => '≤',
174             'le' => '≤',
175             'ONE OF' => 'ONE OF',
176             'one of' => 'ONE OF',
177             'NONE OF' => 'NONE OF',
178             'none of' => 'NONE OF',
179             'IS' => 'IS',
180             'is' => 'IS',
181             'IS NOT' => 'IS NOT',
182             'is not' => 'IS NOT',
183             'isnt' => 'IS NOT',
184             'LOOKUP' => 'LOOKUP',
185             'lookup' => 'LOOKUP',
186             );
187              
188             =head2 as_xml - get the XML serialisation of the query
189              
190             This is either the same value passed in to new_from_xml, or
191             a very naïve XML serialisation. No thorough XML escaping will be performed.
192              
193             =cut
194              
195             sub as_xml {
196 0     0 1   my $self = shift;
197 0 0         return $self->{xml} if $self->{xml};
198 0           my $xml = qq(
199 0 0         $xml .= qq(sortOrder="$self->{sort_order}" ) if $self->{sort_order};
200 0 0         $xml .= qq(constraintLogic="$self->{logic}" ) if $self->{logic};
201 0           $xml .= ">";
202 0           for my $join (@{$self->{joins}}) {
  0            
203 0           $xml .= qq();
204             }
205 0           for my $constraint (@{$self->{constraints}}) {
  0            
206 0 0         my $op = $safe_version_of{$constraint->{op}} if $constraint->{op};
207 0           my $values = delete $constraint->{values};
208 0           $xml .= qq(
209 0 0         $xml .= qq(type="$constraint->{type}" ) if $constraint->{type};
210 0 0         $xml .= qq(op="$op" ) if $op;
211 0 0         $xml .= qq(value="$constraint->{value}" ) if $constraint->{value};
212 0 0         $xml .= qq(extraValue="$constraint->{extra_value}" ) if $constraint->{extra_value};
213 0 0         $xml .= qq(code="$constraint->{code}" ) if $constraint->{code};
214 0           $xml .= ">";
215 0 0         if ($values) {
216 0           $xml .= join('', map {"$_"} @$values);
  0            
217             }
218 0           $xml .= "";
219             }
220 0           $xml .= "";
221 0           return $xml;
222             }
223              
224             =head2 results - get the results for this query as a single string.
225              
226             Returns the string representation of the query's results.
227              
228             Parameters:
229              
230             =over
231              
232             =item * as => $format
233              
234             Specifies the result format.
235              
236             =item * size => int
237              
238             Specifies the maximum number of rows to return.
239             A query can return up to 10,000,000 rows in a single page.
240              
241             =item * start => int
242              
243             Specifies the index of the first result to return.
244              
245             =item * columnheaders => bool
246              
247             Whether or not you want the first row to be the names
248             of the output columns.
249              
250             =back
251              
252             =cut
253              
254             sub results {
255 0     0 1   my $self = shift;
256 0           my %args = @_;
257 0           my $uri = $self->_get_uri;
258 0           my %query_form = (query => $self->as_xml, format => $args{as});
259 0           for (qw/size start columnheaders/) {
260 0 0         $query_form{$_} = $args{$_} if (exists $args{$_});
261             }
262 0 0         if ($self->{service}{token}) {
263 0           $query_form{token} = $self->{service}{token};
264             }
265 0           $uri->query_form(%query_form);
266 0           my $result = $self->{service}{ua}->get($uri);
267 0 0         if ($result->is_success) {
268 0           return $result->decoded_content;
269             } else {
270 0           die $result->status_line, "\n", $result->decoded_content;
271             }
272             }
273              
274             =head2 results_table - get a list of rows (as array-references)
275              
276             Performs very naïve parsing of returned tabular data and splits
277             rows into array references based using a failure-prone "tab" split.
278              
279             =cut
280              
281             sub results_table {
282 0     0 1   my $self = shift;
283 0           my $results = $self->results(as => 'tab');
284 0           my @lines = map {[split /\t/]} split(/\n/, $results);
  0            
285 0           return @lines;
286             }
287              
288             =head2 get_count - get the number of rows the query returns
289              
290             Returns a number representing the total number of rows in the result set.
291              
292             =cut
293              
294             sub get_count {
295 0     0 1   my $self = shift;
296 0           return $self->results(as => 'count') + 0;
297             }
298              
299             =head1 SEE ALSO
300              
301             =over 4
302              
303             =item * L For a more powerful alternative
304              
305             =back
306              
307             =head1 AUTHOR
308              
309             Alex Kalderimis C<< >>
310              
311             =head1 BUGS
312              
313             Please report any bugs or feature requests to C.
314              
315             =head1 SUPPORT
316              
317             You can find documentation for this module with the perldoc command.
318              
319             perldoc Webservice::InterMine
320              
321             You can also look for information at:
322              
323             =over 4
324              
325             =item * InterMine
326              
327             L
328              
329             =item * Documentation
330              
331             L
332              
333             =back
334              
335             =head1 COPYRIGHT AND LICENSE
336              
337             Copyright 2006 - 2011 FlyMine, all rights reserved.
338              
339             This program is free software; you can redistribute it and/or modify it
340             under the same terms as Perl itself.
341              
342             =cut
343              
344             1;
345            
346