File Coverage

blib/lib/WWW/WolframAlpha.pm
Criterion Covered Total %
statement 23 25 92.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 32 34 94.1


line stmt bran cond sub pod time code
1             package WWW::WolframAlpha;
2             BEGIN {
3 1     1   24035 $WWW::WolframAlpha::VERSION = '1.10';
4             }
5              
6 1     1   29 use 5.008008;
  1         4  
  1         34  
7 1     1   5 use strict;
  1         2  
  1         42  
8 1     1   5 use warnings;
  1         2  
  1         40  
9              
10             require Exporter;
11              
12 1     1   562 use WWW::WolframAlpha::ValidateQuery;
  1         3  
  1         47  
13 1     1   591 use WWW::WolframAlpha::Query;
  1         4  
  1         130  
14 1     1   6 use WWW::WolframAlpha::Pod;
  1         2  
  1         41  
15              
16 1     1   965 use URI::Escape qw(uri_escape_utf8);
  1         2973  
  1         75  
17 1     1   507 use XML::Simple qw(:strict);
  0            
  0            
18              
19             use LWP::UserAgent;
20             use HTTP::Request::Common;
21              
22             our @ISA = qw(Exporter);
23              
24             # Items to export into callers namespace by default. Note: do not export
25             # names by default without a very good reason. Use EXPORT_OK instead.
26             # Do not simply export all your public functions/methods/constants.
27              
28             # This allows declaration use WWW::WolframAlpha ':all';
29             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
30             # will save memory.
31             our %EXPORT_TAGS = ( 'all' => [ qw(
32             ) ] );
33              
34             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
35              
36             our @EXPORT = qw(
37             );
38              
39             our $VERSION ||= '0.0development';
40              
41             my $xs = XML::Simple->new(
42             'KeyAttr' => [],
43             'ForceArray' => ['assumption','pod','subpod','source','value','state','info','link','statelist','unit','spellcheck','sound','didyoumean','error'],
44             'ValueAttr' => [],
45             'VarAttr' => [''],
46             'SuppressEmpty' => undef,
47             );
48              
49             sub new {
50             my $class = shift;
51             my %options = @_;
52              
53             my $self = {};
54             while(my($key, $val) = each %options) {
55             my $lkey = lc($key);
56             $self->{$lkey} = $val;
57             }
58              
59             die qq(no appid) if !$self->{'appid'};
60              
61             $self->{'ua'} = get_useragent();
62              
63             return(bless($self, $class));
64             }
65              
66             my $ua_agent = 'WWW::WolframAlpha/' . $VERSION;
67             sub get_useragent {
68             my $ua = new LWP::UserAgent(
69             agent => $ua_agent,
70             );
71             return $ua;
72             }
73              
74             sub get_response {
75             my $self = shift;
76             my $url = shift;
77              
78             my $timeout = 0;
79             {
80             my ($scantimeout) = $url =~ /\&scantimeout\=(\d+)/o;
81             my ($formattimeout) = $url =~ /\&formattimeout\=(\d+)/o;
82             $timeout += $scantimeout || 3;
83             $timeout += $formattimeout || 8;
84             }
85              
86             my $response = '';
87             eval {
88             local $SIG{ALRM} = sub { die "alarm\n" };
89             alarm($timeout);
90             $response = $self->{'ua'}->request(GET $url);
91             alarm(0);
92             };
93              
94             my $xml = '';
95             my $ref = '';
96             $self->{'errmsg'} = '';
97             $self->{'error'} = 0;
98              
99             if ($@) {
100             $self->{'errmsg'} = $@;
101             $self->{'error'} = 1;
102              
103             } elsif (!$response) {
104             $self->{'errmsg'} = 'unknown request error';
105             $self->{'error'} = 1;
106              
107             } elsif ($response->code != '200') {
108             $self->{'errmsg'} = $response->code . ' ' . $response->message;
109             $self->{'error'} = 1;
110              
111             } else {
112             $xml = $response->content;
113              
114             eval {
115             $ref = $xs->XMLin($xml);
116             };
117              
118             if (!$ref) {
119             $self->{'errmsg'} = 'bad xml response';
120             $self->{'error'} = 1;
121             }
122             }
123              
124             return ($xml,$ref);
125             }
126              
127             sub construct_url {
128             my ($method,$appid,%param) = @_;
129             # my $url = 'http://preview.wolframalpha.com/api/v1/' . $method . '.jsp?';
130             my $url = 'http://api.wolframalpha.com/v1/' . $method . '.jsp?';
131             $url .= 'appid=' . $appid;
132              
133             if (exists $param{'url'}) {
134             $url = $param{'url'};
135             }
136              
137             foreach my $param (keys %param) {
138             next if $param eq 'url';
139              
140             if ($param eq 'podtitle' && $param{$param} =~ /,/) {
141             my @param = split(/\,/,$param{$param});
142             SUB_PARAM: foreach my $sub_param (@param) {
143             next SUB_PARAM if !$sub_param;
144             $url .= '&' . $param . '=' . uri_escape_utf8($sub_param);
145             }
146              
147             } else {
148             $url .= '&' . $param . '=' . uri_escape_utf8($param{$param});
149             }
150             }
151              
152             # For debugging.
153             # warn $url;
154              
155             return $url;
156             }
157              
158             sub validatequery {
159             my $self = shift;
160             my ($url) = construct_url('validatequery',$self->{'appid'},@_);
161             my ($xml,$ref) = get_response($self,$url);
162              
163             my $object = WWW::WolframAlpha::ValidateQuery->new(
164             xml => $xml,
165             xmlo => $ref,
166             );
167              
168             return $object;
169             }
170              
171             sub query {
172             my $self = shift;
173             my ($url) = construct_url('query',$self->{'appid'},@_);
174             my ($xml,$ref) = get_response($self,$url);
175              
176             my $object = WWW::WolframAlpha::Query->new(
177             xml => $xml,
178             xmlo => $ref,
179             );
180              
181             return $object;
182             }
183              
184             sub asyncPod {
185             my $self = shift;
186             my ($url) = construct_url('query',$self->{'appid'},@_);
187             my ($xml,$ref) = get_response($self,$url);
188              
189             my $object = WWW::WolframAlpha::Pod->new($ref);
190              
191             $object->{'xml'} = $xml;
192             $object->{'xmlo'} = $ref;
193              
194             return $object;
195             }
196              
197             sub error {shift->{'error'};}
198             sub errmsg {shift->{'errmsg'};}
199              
200             # Preloaded methods go here.
201              
202             1;
203              
204              
205             =pod
206              
207             =head1 NAME
208              
209             WWW::WolframAlpha
210              
211             =head1 VERSION
212              
213             version 1.10
214              
215             =head1 SYNOPSIS
216              
217             use WWW::WolframAlpha;
218              
219             my $wa = WWW::WolframAlpha->new (
220             appid => 'XXX',
221             );
222              
223             my $query = $wa->query(
224             input => 'Pi',
225             );
226              
227             if ($query->success) {
228             foreach my $pod (@{$query->pods}) {
229             ...
230             }
231             }
232              
233             =head1 DESCRIPTION
234              
235             See the included example.*.pl files for full working examples.
236              
237             Access to this module is strictly OO. Pass your appid to the constructor, which is the only parameter needed.
238              
239             There are three functions available, query, validatequery and asyncPod, which match the API calls.
240              
241             Pass any desired input paramters to the function calls. The 'input' parameter is required.
242              
243             Each function call returns objects, of the forms L, L and L, respectively.
244              
245             See the WolframAlpha API docs for details on the overall API, what parameters you can input and what you can expect in response.
246              
247             All the attributes and elements detailed in the API docs are available via the returned objects. See the documentation in L, L, L and other sub-packages for details on what methods are available for particular objects.
248              
249             =head2 ERROR HANDLING
250              
251             If there are errors contacting WA, $wa->error will be set to 1 and $wa->errmsg should give you some indication of what is going on.
252              
253             Errors returned by WA are handled within the objects themselves via success and error methods (see example.*.pl files).
254              
255             =head2 DEBUGGING
256              
257             For debugging, the raw XML output and the internal Perl object used (via L) are available via the xml and xmlo methods. However, please don't rely on these, i.e. only use them for debugging.
258              
259             =head2 EXPORT
260              
261             None by default.
262              
263             =head1 NAME
264              
265             WWW::WolframAlpha - Perl extension for the WolframAlpha API
266              
267             =head1 SEE ALSO
268              
269             B requires L, L, L and L.
270              
271             http://www.wolframalpha.com/
272              
273             =head1 AUTHOR
274              
275             Gabriel Weinberg, Eyegg@alum.mit.eduE
276              
277             =head1 COPYRIGHT AND LICENSE
278              
279             Copyright (C) 2009 by Gabriel Weinberg
280              
281             This library is free software; you can redistribute it and/or modify
282             it under the same terms as Perl itself, either Perl version 5.8.8 or,
283             at your option, any later version of Perl 5 you may have available.
284              
285             =head1 AUTHOR
286              
287             Gabriel Weinberg
288              
289             =head1 COPYRIGHT AND LICENSE
290              
291             This software is copyright (c) 2009 by Gabriel Weinberg.
292              
293             This is free software; you can redistribute it and/or modify it under
294             the same terms as the Perl 5 programming language system itself.
295              
296             =cut
297              
298              
299             __END__