$Weather::OpenWeatherMap::Request::VERSION = '0.001004'; # TRIAL
use v5.10;
use strictures 1;
use Carp;
use Types::Standard -all;
use Types::DateTime -all;
use URI::Escape 'uri_escape_utf8';
use Module::Runtime 'use_module';
use Storable 'freeze';
sub new_for {
my ($class, $type) = splice @_, 0, 2;
confess "Expected a subclass type" unless $type;
my $subclass = $class .'::'. ucfirst($type);
use_module($subclass)->new(@_)
}
=pod
=for Pod::Coverage has_\w+
=cut
has api_key => (
lazy => 1,
is => 'ro',
isa => Str,
predicate => 1,
builder => sub { '' },
);
has tag => (
lazy => 1,
is => 'ro',
predicate => 1,
builder => sub { '' },
);
has location => (
required => 1,
is => 'ro',
isa => Str,
);
has ts => (
is => 'ro',
isa => StrictNum,
builder => sub { time },
);
has url => (
init_arg => undef,
lazy => 1,
is => 'ro',
isa => Str,
builder => sub { shift->_parse_location_str },
);
has http_request => (
lazy => 1,
is => 'ro',
isa => InstanceOf['HTTP::Request'],
builder => sub {
my ($self) = @_;
my $req = HTTP::Request->new( GET => $self->url );
$req->header( 'x-api-key' => $self->api_key )
if $self->has_api_key and length $self->api_key;
$req
},
);
has _units => (
required => 1,
is => 'ro',
isa => Str,
builder => sub { 'imperial' },
);
sub _url_bycode {
my ($self, $code) = @_;
. uri_escape_utf8($code)
. '&units=' . $self->_units
}
sub _url_bycoord {
my $self = shift;
my ($lat, $long) = map {; uri_escape_utf8($_) } @_;
. '&units=' . $self->_units
}
sub _url_byname {
my ($self, @parts) = @_;
. join(',', map {; uri_escape_utf8($_) } @parts)
. '&units=' . $self->_units
}
sub _parse_location_str {
my ($self) = @_;
state $latlong =
qr{\Alat(?:itude)?\s+?(-?[0-9.]+),?\s+?long?(?:itude)?\s+?(-?[0-9.]+)};
my $str = $self->location;
my $url;
URL: {
if (is_StrictNum $str) {
$url = $self->_url_bycode($str);
last URL
}
if (my ($lat, $lon) = $str =~ $latlong) {
$url = $self->_url_bycoord($lat, $lon);
last URL
}
my @parts = split /,\s+?/, $str;
$url = $self->_url_byname(@parts);
}
$url
}
1;
=pod
=head1 NAME
Weather::OpenWeatherMap::Request - Weather lookup request superclass
=head1 SYNOPSIS
# Normally generated via Weather::OpenWeatherMap
# (when a request is made)
=head1 DESCRIPTION
This is the parent class for request objects generated by
L<Weather::OpenWeatherMap>.
See also:
L<Weather::OpenWeatherMap::Request::Current>
L<Weather::OpenWeatherMap::Request::Forecast>
=head2 ATTRIBUTES
=head3 api_key
The L<OpenWeatherMap API key|http://www.weathermap.org/api> attached to this
request.
=head3 location
B<Required:>
The location string, used to (lazily) generate the L</http_request> and L</url>
attributes.
Locations can be specified in various ways.
Strings such as 'City, State' or 'City, Country' will be parsed appropriately.
A numeric location is taken to be an
L<OpenWeatherMap|http://www.openweathermap.org> city code.
A string in the form of 'lat X, long Y' or 'latitude X, longitude Y' is also
accepted.
=head3 tag
An (optional) arbitrary scalar attached to the request object at construction
time.
=head3 http_request
The (generated) L<HTTP::Request> object used to request the weather data.
=head3 ts
The C<time()> the request object was created.
=head3 url
The (generated) L<OpenWeatherMap|http://www.openweathermap.org/> URL.
=head2 METHODS
=head3 new_for
Factory method; returns a new object belonging to the appropriate subclass:
my $request = Weather::OpenWeatherMap::Request->new_for(
Current =>
api_key => $api_key,
location => $location,
tag => $tag,
);
=head1 AUTHOR
Jon Portnoy <avenj@cobaltirc.org>
=cut