Geo::Coder::Googleを逆ジオコーディングに対応させる

 リクエストパラメータを切り替えるだけでよかったので、簡単でした!

{
    package Geo::Coder::Google;

    {
        no warnings 'redefine';

        sub geocode {
            my $self = shift;
            my %param;
            if ( @_ % 2 == 0 ) {
                %param = @_;
            }
            else {
                $param{location} = shift;
            }
            my @placemark = $self->_fetch_data(\%param);
            wantarray ? @placemark : $placemark[0];
        }
    }

    # 逆ジオコーディング用メソッド
    sub rgeocode {
        my $self = shift;

        my %param;
        if ( @_ % 2 == 0 ) {
            %param = @_;
        }
        else {
            my $arg = shift;
            $param{lat} = $arg->{lat};
            $param{long} = $arg->{long};
        }

        my @placemark = $self->_fetch_data(\%param);
        wantarray ? @placemark : $placemark[0];
    }

    sub _make_request {
        my $self  = shift;
        my $args  = shift;

        my %query_parameters = ( output => 'json', key => $self->{key} );
        $query_parameters{hl} = $self->{language} if defined $self->{language};
        if ( my $location = $args->{location} ) {

            if ( Encode::is_utf8($location) ) {
                $location = Encode::encode_utf8($location);
            }
            $query_parameters{q} = $location;
        }
        else {
            $query_parameters{ll} = do {
                my $lat = $args->{lat};
                my $lng = $args->{long};
                "${lat},${lng}";
            };
        }
        %query_parameters;
    }

    sub _fetch_data {
        my $self = shift;
        my $args = shift;
        my $uri = URI->new("http://$self->{host}/maps/geo");
        my %query_parameters = $self->_make_request($args);
        $uri->query_form(%query_parameters);

        my $res = $self->{ua}->get($uri);

        if ( $res->is_error ) {
            Carp::croak(
                "Google Maps API returned error: " . $res->status_line );
        }

        # Ugh, Google Maps returns so stupid HTTP header
        # Content-Type: text/javascript; charset=UTF-8; charset=Shift_JIS
        my @ctype = $res->content_type;
        my $charset = ( $ctype[1] =~ /charset=([\w\-]+)$/ )[0] || "utf-8";

        my $content = Encode::decode( $charset, $res->content );

        local $JSON::Syck::ImplicitUnicode = 1;
        my $data = JSON::Syck::Load($content);

        my @placemark = @{ $data->{Placemark} || [] };
        @placemark;
    }
}