Geo-Coder-OSM-0.03/000755 000766 000024 00000000000 12241000615 013731 5ustar00raygstaff000000 000000 Geo-Coder-OSM-0.03/Changes000644 000766 000024 00000000511 12240777767 015255 0ustar00raygstaff000000 000000 Revision history for Geo-Coder-OSM 0.03 Wed Nov 13 22:40:07 UTC 2013 - Added reverse_geocode method. - Allowed for additional sources to be defined. 0.02 Tue Mar 22 00:15:25 UTC 2011 - Added support for the Mapquest mirror of the Nominatim service. 0.01 Sun Jun 27 00:33:44 UTC 2010 - Initial distribution. Geo-Coder-OSM-0.03/ex/000755 000766 000024 00000000000 12241000615 014345 5ustar00raygstaff000000 000000 Geo-Coder-OSM-0.03/lib/000755 000766 000024 00000000000 12241000615 014477 5ustar00raygstaff000000 000000 Geo-Coder-OSM-0.03/Makefile.PL000644 000766 000024 00000002543 11541706457 015732 0ustar00raygstaff000000 000000 use strict; use warnings; use ExtUtils::MakeMaker; my %conf = ( NAME => 'Geo::Coder::OSM', AUTHOR => 'gray ', LICENSE => 'perl', VERSION_FROM => 'lib/Geo/Coder/OSM.pm', ABSTRACT_FROM => 'lib/Geo/Coder/OSM.pm', PREREQ_PM => { 'Encode' => 0, 'JSON' => 2.0, 'LWP::UserAgent' => 0, 'URI' => 1.36, }, BUILD_REQUIRES => { 'Test::More' => 0.82, }, META_MERGE => { resources => { repository => 'http://github.com/gray/geo-coder-osm', }, recommends => { 'JSON::XS' => 2.0, }, }, dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, clean => { FILES => 'Geo-Coder-OSM-*' }, ); my $eumm_version=$ExtUtils::MakeMaker::VERSION; delete $conf{META_MERGE} if $eumm_version < 6.46; $conf{PREREQ_PM} = { %{ $conf{PREREQ_PM} || {} }, %{ delete $conf{BUILD_REQUIRES} }, } if ($conf{BUILD_REQUIRES} and $eumm_version < 6.5503); WriteMakefile(%conf); sub MY::postamble { return <<" MAKE_FRAG"; authortest: \t\$(MAKE) -e \$(TEST_TYPE) TEST_FILES="xt/*.t" MAKE_FRAG } sub MY::dist_test { my $self = shift; return $self->MM::dist_test . <<" MAKE_FRAG"; \tcd \$(DISTVNAME) && \$(MAKE) authortest \$(PASTHRU) MAKE_FRAG } Geo-Coder-OSM-0.03/MANIFEST000644 000766 000024 00000000637 12241000615 015070 0ustar00raygstaff000000 000000 Changes ex/custom-useragent.pl lib/Geo/Coder/OSM.pm Makefile.PL MANIFEST This list of files README t/00_compile.t t/01_new.t xt/kwalitee.t xt/live.t xt/perlcritic.t xt/perlcriticrc xt/pod.t xt/pod_coverage.t xt/portability_filenames.t xt/vars.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Geo-Coder-OSM-0.03/META.json000644 000766 000024 00000002176 12241000615 015360 0ustar00raygstaff000000 000000 { "abstract" : "Geocode addresses with the OpenStreetMap Nominatim API", "author" : [ "gray " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 6.82, CPAN::Meta::Converter version 2.132830", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Geo-Coder-OSM", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "Test::More" : "0.82" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "recommends" : { "JSON::XS" : "2" }, "requires" : { "Encode" : "0", "JSON" : "2", "LWP::UserAgent" : "0", "URI" : "1.36" } } }, "release_status" : "stable", "resources" : { "repository" : { "url" : "http://github.com/gray/geo-coder-osm" } }, "version" : "0.03" } Geo-Coder-OSM-0.03/META.yml000644 000766 000024 00000001157 12241000615 015206 0ustar00raygstaff000000 000000 --- abstract: 'Geocode addresses with the OpenStreetMap Nominatim API' author: - 'gray ' build_requires: Test::More: 0.82 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 6.82, CPAN::Meta::Converter version 2.132830' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Geo-Coder-OSM no_index: directory: - t - inc recommends: JSON::XS: 2 requires: Encode: 0 JSON: 2 LWP::UserAgent: 0 URI: 1.36 resources: repository: http://github.com/gray/geo-coder-osm version: 0.03 Geo-Coder-OSM-0.03/README000644 000766 000024 00000001026 12240777314 014630 0ustar00raygstaff000000 000000 Geo-Coder-OSM ============= This module provides an interface to the OpenStreetMap Nominatim API INSTALLATION To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module requires these other modules and libraries: Encode JSON LWP::UserAgent Test::More URI COPYRIGHT AND LICENCE Copyright (C) 2010-2013 by gray This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Geo-Coder-OSM-0.03/t/000755 000766 000024 00000000000 12241000615 014174 5ustar00raygstaff000000 000000 Geo-Coder-OSM-0.03/xt/000755 000766 000024 00000000000 12241000615 014364 5ustar00raygstaff000000 000000 Geo-Coder-OSM-0.03/xt/kwalitee.t000644 000766 000024 00000000262 11541706107 016371 0ustar00raygstaff000000 000000 use strict; use warnings; use Test::More; eval { require Test::Kwalitee; Test::Kwalitee->import(); 1 } or do { plan skip_all => 'Test::Kwalitee not installed; skipping'; }; Geo-Coder-OSM-0.03/xt/live.t000644 000766 000024 00000003607 12240771205 015527 0ustar00raygstaff000000 000000 use strict; use warnings; use Encode; use Geo::Coder::OSM; use LWP::UserAgent; use Test::More; my $debug = $ENV{GEO_CODER_OSM_DEBUG}; diag "Set GEO_CODER_OSM_DEBUG to see request/response data" unless $debug; for my $source (qw(osm mapquest)) { my $geocoder = Geo::Coder::OSM->new( debug => $debug, sources => $source, ); { my $address = '132 Maney Hill Road, West Midlands, UK'; my $forward = $geocoder->geocode($address); is( $forward->{address}{town}, 'Sutton Coldfield', "correct town for $address" ); my $road = $forward->{address}{road}; my ($lat, $lon) = @$forward{qw(lat lon)}; my $reverse = $geocoder->reverse_geocode(lat => $lat, lon => $lon); is( $reverse->{address}{road}, $forward->{address}{road}, 'correct street for lat/lon', ); } { my $address = qq(Champs-\xC9lys\xE9es, 75008); my $location = $geocoder->geocode($address); ok($location, 'latin1 bytes'); is($location->{address}{country}, 'France', 'latin1 bytes'); $location = $geocoder->geocode(decode('latin1', $address)); ok($location, 'UTF-8 characters'); is($location->{address}{country}, 'France', 'UTF-8 characters'); TODO: { local $TODO = 'UTF-8 bytes'; $location = $geocoder->geocode( encode('utf-8', decode('latin1', $address)) ); ok($location, 'UTF-8 bytes'); is($location->{address}{country}, 'France', 'UTF-8 bytes'); } } { my $city = decode('latin1', qq(Schm\xF6ckwitz)); my $location = $geocoder->geocode("$city, Berlin, Germany"); is( $location->{address}{suburb}, $city, 'decoded character encoding of response' ); } } done_testing; Geo-Coder-OSM-0.03/xt/perlcritic.t000644 000766 000024 00000000372 11541706107 016726 0ustar00raygstaff000000 000000 use strict; use warnings; use Test::More; eval { require Test::Perl::Critic; 1 } or do { plan skip_all => "Test::Perl::Critic is not installed."; }; Test::Perl::Critic->import( -profile => 'xt/perlcriticrc' ); all_critic_ok(qw( ex lib t xt )); Geo-Coder-OSM-0.03/xt/perlcriticrc000644 000766 000024 00000000655 11541706107 017015 0ustar00raygstaff000000 000000 verbose = 8 [CodeLayout::ProhibitHardTabs] allow_leading_tabs = 0 severity = 5 [CodeLayout::ProhibitTrailingWhitespace] severity = 5 # requires Perl::Critic::More [CodeLayout::RequireASCII] severity = 5 [TestingAndDebugging::RequireUseWarnings] severity = 5 [-TestingAndDebugging::ProhibitNoStrict] [-BuiltinFunctions::ProhibitStringyEval] # requires Regexp::Parser [RegularExpressions::ProhibitUnusedCapture] severity = 5 Geo-Coder-OSM-0.03/xt/pod.t000644 000766 000024 00000000250 11541706107 015343 0ustar00raygstaff000000 000000 use strict; use warnings; use Test::More; eval "use Test::Pod 1.00; 1" or do { plan skip_all => 'Test::Pod 1.00 required for testing POD'; }; all_pod_files_ok(); Geo-Coder-OSM-0.03/xt/pod_coverage.t000644 000766 000024 00000000270 11541706107 017220 0ustar00raygstaff000000 000000 use strict; use warnings; use Test::More; eval "use Test::Pod::Coverage 1.00; 1" or do { plan skip_all => 'Test::Pod::Coverage 1.00 is not installed.'; }; all_pod_coverage_ok(); Geo-Coder-OSM-0.03/xt/portability_filenames.t000644 000766 000024 00000000256 11541706107 021154 0ustar00raygstaff000000 000000 use strict; use warnings; use Test::More; eval "use Test::Portability::Files; 1" or do { plan skip_all => 'Test::Portability::Files is not installed.'; }; run_tests(); Geo-Coder-OSM-0.03/xt/vars.t000644 000766 000024 00000000224 11541706107 015535 0ustar00raygstaff000000 000000 use strict; use warnings; use Test::More; eval "use Test::Vars; 1" or do { plan skip_all => 'Test::Vars is not installed.'; }; all_vars_ok(); Geo-Coder-OSM-0.03/t/00_compile.t000644 000766 000024 00000000131 11411513046 016310 0ustar00raygstaff000000 000000 use strict; use warnings; use Test::More tests => 1; BEGIN { use_ok 'Geo::Coder::OSM' } Geo-Coder-OSM-0.03/t/01_new.t000644 000766 000024 00000000314 11411513121 015447 0ustar00raygstaff000000 000000 use strict; use warnings; use Test::More tests => 3; use Geo::Coder::OSM; new_ok('Geo::Coder::OSM' => []); new_ok('Geo::Coder::OSM' => [debug => 1]); can_ok('Geo::Coder::OSM', qw(geocode response ua)); Geo-Coder-OSM-0.03/lib/Geo/000755 000766 000024 00000000000 12241000615 015211 5ustar00raygstaff000000 000000 Geo-Coder-OSM-0.03/lib/Geo/Coder/000755 000766 000024 00000000000 12241000615 016245 5ustar00raygstaff000000 000000 Geo-Coder-OSM-0.03/lib/Geo/Coder/OSM.pm000644 000766 000024 00000017637 12241000062 017253 0ustar00raygstaff000000 000000 package Geo::Coder::OSM; use strict; use warnings; use Carp qw(croak); use Encode (); use JSON; use LWP::UserAgent; use URI; our $VERSION = '0.03'; $VERSION = eval $VERSION; our %SOURCES = ( osm => 'http://nominatim.openstreetmap.org', mapquest => 'http://open.mapquestapi.com/nominatim/v1', ); sub new { my ($class, @params) = @_; my %params = (@params % 2) ? (key => @params) : @params; my $self = bless \ %params, $class; $self->ua( $params{ua} || LWP::UserAgent->new(agent => "$class/$VERSION") ); if (exists $self->{sources}) { my $sources = $self->{sources}; $self->{sources} = $sources = [$sources] unless ref $sources; for my $source (@$sources) { croak qq(unknown source '$source') unless exists $SOURCES{$source}; } } else { $self->{sources} = ['osm']; } $self->{source_idx} = 0; if ($self->{debug}) { my $dump_sub = sub { $_[0]->dump(maxlength => 0); return }; $self->ua->set_my_handler(request_send => $dump_sub); $self->ua->set_my_handler(response_done => $dump_sub); } elsif (exists $self->{compress} ? $self->{compress} : 1) { $self->ua->default_header(accept_encoding => 'gzip,deflate'); } return $self; } sub response { $_[0]->{response} } sub ua { my ($self, $ua) = @_; if ($ua) { croak q('ua' must be (or derived from) an LWP::UserAgent') unless ref $ua and $ua->isa(q(LWP::UserAgent)); $self->{ua} = $ua; } return $self->{ua}; } sub geocode { my ($self, @params) = @_; my %params = (@params % 2) ? (location => @params) : @params; my $location = delete $params{location} or return; $location = Encode::encode('utf-8', $location); # Cycle throught the list of sources. my $idx = ($self->{source_idx} %= @{ $self->{sources} })++; my $uri = URI->new($SOURCES{ $self->{sources}[$idx] } . '/search'); $uri->query_form( q => $location, format => 'json', addressdetails => 1, 'accept-language' => 'en', %params, ); return $self->_request($uri); } sub reverse_geocode { my ($self, @params) = @_; my %params = (@params % 2) ? (latlng => @params) : @params; # Maintain api compatibility with other geocoders. my ($lat, $lon); if (my $latlon = delete $params{latlng}) { ($lat, $lon) = split '\s*,\s*', $latlon; } else { $lat = delete $params{lat}; ($lon) = grep defined, delete @params{qw(lon lng)}; } return unless 2 == grep defined, $lat, $lon; # Cycle throught the list of sources. my $idx = ($self->{source_idx} %= @{ $self->{sources} })++; my $uri = URI->new($SOURCES{ $self->{sources}[$idx] } . '/reverse'); $uri->query_form( lat => $lat, lon => $lon, format => 'json', addressdetails => 1, 'accept-language' => 'en', %params, ); return $self->_request($uri); } sub _request { my ($self, $uri) = @_; return unless $uri; my $res = $self->{response} = $self->ua->get($uri); return unless $res->is_success; # Change the content type of the response (if necessary) so # HTTP::Message will decode the character encoding. $res->content_type('text/plain') unless $res->content_type =~ /^text/; my $content = $res->decoded_content; return unless $content; my $data = eval { from_json($content) }; return unless $data; my @results = 'ARRAY' eq ref $data ? @$data : ($data); return wantarray ? @results : $results[0]; } 1; __END__ =head1 NAME Geo::Coder::OSM - Geocode addresses with the OpenStreetMap Nominatim API =head1 SYNOPSIS use Geo::Coder::OSM; my $geocoder = Geo::Coder::OSM->new; my $location = $geocoder->geocode( location => 'Hollywood and Highland, Los Angeles, CA' ); =head1 DESCRIPTION The C module provides an interface to the OpenStreet Nominatim geocoding service. =head1 METHODS =head2 new $geocoder = Geo::Coder::OSM->new() $geocoder = Geo::Coder::OSM->new( ua => $ua, sources => [ 'osm', 'mapquest' ], debug => 1, ) Creates a new geocoding object. Accepts an optional B parameter for passing in a custom LWP::UserAgent object. Accepts an optional B parameter for specifying the data sources. Current valid values are B and B. The default value is B. To cycle between different sources, specify an array reference for the B value. To define additional sources, see L below. =head2 geocode $location = $geocoder->geocode(location => $location) @locations = $geocoder->geocode(location => $location) In scalar context, this method returns the first location result; and in list context it returns all location results. Each location result is a hashref; a typical example looks like: { address => { city => "Los Angeles", country => "United States of America", country_code => "us", hamlet => "Hollywood", road => "Hollywood Boulevard", station => "Hollywood/Highland", suburb => "Little Armenia", }, boundingbox => [ "34.101634979248", "34.1018371582031", "-118.339317321777", "-118.33910369873", ], class => "railway", display_name => "Hollywood/Highland, Hollywood Boulevard, Little Armenia, Hollywood, Los Angeles, United States of America", icon => "http://nominatim.openstreetmap.org/images/mapicons/transport_train_station2.p.20.png", lat => "34.101736", licence => "Data Copyright OpenStreetMap Contributors, Some Rights Reserved. CC-BY-SA 2.0.", lon => "-118.33921", osm_id => 472413621, osm_type => "node", place_id => 9071654, type => "station", } =head2 reverse_geocode $location = $geocoder->reverse_geocode(lat => $lat, lon => $lon) $location = $geocoder->reverse_geocode(latlng => "$lat,$lon") Returns a location result for the given lat/lon pair. =head2 response $response = $geocoder->response() Returns an L object for the last submitted request. Can be used to determine the details of an error. =head2 ua $ua = $geocoder->ua() $ua = $geocoder->ua($ua) Accessor for the UserAgent object. =head2 SOURCES To define additional sources add them to the B<%SOURCES> package variable like so: $Geo::Coder::OSM::SOURCES{local} = 'http://127.0.0.1/api_base_path'; $Geo::Coder::OSM::SOURCES{internal} = 'http://internal.corp/api_base_path'; =head1 SEE ALSO L L =head1 REQUESTS AND BUGS Please report any bugs or feature requests to L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc Geo::Coder::OSM You can also look for information at: =over =item * GitHub Source Repository L =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * RT: CPAN's request tracker L =item * Search CPAN L =back =head1 COPYRIGHT AND LICENSE Copyright (C) 2010-2013 gray , all rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHOR gray, =cut Geo-Coder-OSM-0.03/ex/custom-useragent.pl000755 000766 000024 00000000766 11411516223 020230 0ustar00raygstaff000000 000000 #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; use Geo::Coder::OSM; my $location = join(' ', @ARGV) || die "Usage: $0 \$location_string"; # Custom useragent identifier. my $ua = LWP::UserAgent->new(agent => 'My Geocoder'); # Load any proxy settings from environment variables. $ua->env_proxy; my $geocoder = Geo::Coder::OSM->new( ua => $ua, debug => 1, ); my $result = $geocoder->geocode(location => $location); local $Data::Dumper::Indent = 1; print Dumper($result);