diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index d6728b51f6c913d590bd83c1ac506022887d4987..1002f40c0e1eb8e1e3b37cfb0e0e4024022c2593 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -39,6 +39,7 @@ module Geocoder :baidu, :geocodio, :smarty_streets, + :okf, :test ] end diff --git a/lib/geocoder/lookups/okf.rb b/lib/geocoder/lookups/okf.rb new file mode 100644 index 0000000000000000000000000000000000000000..ae45e06a4680c8e61aaf05eeae547495aff5e03a --- /dev/null +++ b/lib/geocoder/lookups/okf.rb @@ -0,0 +1,43 @@ +require 'geocoder/lookups/base' +require "geocoder/results/okf" + +module Geocoder::Lookup + class Okf < Base + + def name + "Okf" + end + + def query_url(query) + "#{protocol}://data.okf.fi/gis/1/geocode/json?" + url_query_string(query) + end + + private # --------------------------------------------------------------- + + def valid_response?(response) + status = parse_json(response.body)["status"] + super(response) and ['OK', 'ZERO_RESULTS'].include?(status) + end + + def results(query) + return [] unless doc = fetch_data(query) + case doc['status']; when "OK" # OK status implies >0 results + return doc['results'] + end + return [] + end + + def query_url_okf_params(query) + params = { + (query.reverse_geocode? ? :latlng : :address) => query.sanitized_text, + :sensor => "false", + :language => (query.language || configuration.language) + } + params + end + + def query_url_params(query) + query_url_okf_params(query).merge(super) + end + end +end diff --git a/lib/geocoder/results/okf.rb b/lib/geocoder/results/okf.rb new file mode 100644 index 0000000000000000000000000000000000000000..973922591474c75897a963e4d0b1aef46cd028ed --- /dev/null +++ b/lib/geocoder/results/okf.rb @@ -0,0 +1,106 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class Okf < Base + + def coordinates + ['lat', 'lng'].map{ |i| geometry['location'][i] } + end + + def address(format = :full) + formatted_address + end + + def city + fields = [:locality, :sublocality, + :administrative_area_level_3, + :administrative_area_level_2] + fields.each do |f| + if entity = address_components_of_type(f).first + return entity['long_name'] + end + end + return nil # no appropriate components found + end + + def state + "" + end + + def sub_state + "" + end + + def state_code + "" + end + + def country + if country = address_components_of_type(:country).first + country['long_name'] + end + end + + def country_code + if country = address_components_of_type(:country).first + country['short_name'] + end + end + + def postal_code + if postal = address_components_of_type(:postal_code).first + postal['long_name'] + end + end + + def route + if route = address_components_of_type(:route).first + route['long_name'] + end + end + + def street_number + if street_number = address_components_of_type(:street_number).first + street_number['long_name'] + end + end + + def street_address + [route, street_number].compact.join(' ') + end + + def types + @data['types'] + end + + def formatted_address + @data['formatted_address'] + end + + def address_components + @data['address_components'] + end + + ## + # Get address components of a given type. Valid types are defined in + # Google's Geocoding API documentation and include (among others): + # + # :street_number + # :locality + # :neighborhood + # :route + # :postal_code + # + def address_components_of_type(type) + address_components.select{ |c| c['types'].include?(type.to_s) } + end + + def geometry + @data['geometry'] + end + + def precision + geometry['location_type'] if geometry + end + end +end diff --git a/test/fixtures/okf_kirstinmaki b/test/fixtures/okf_kirstinmaki new file mode 100644 index 0000000000000000000000000000000000000000..79d50b9636c554fb7af243820cfe29ae3d3b6cc7 --- /dev/null +++ b/test/fixtures/okf_kirstinmaki @@ -0,0 +1,67 @@ +{ + "status" : "OK", + "results" : [ + { + "formatted_address" : "Kirstinmäki 1, 02760 Espoo, Suomi", + "sources" : [ + { + "name" : "National Land Survey of Finland - Topographic Dataset (2013-03-08)", + "terms_of_use" : "National Land Survey open data licence - version 1.0 - 1 May 2012\nhttp://www.maanmittauslaitos.fi/en/NLS_open_data_licence_version1_20120501" + }, + { + "name" : "Itella perusosoitteisto (2014-02-01)", + "terms_of_use" : "http://www.itella.fi/liitteet/palvelutjatuotteet/yhteystietopalvelut/Postinumeropalvelut-Palvelukuvausjakayttoehdot.pdf" + } + ], + "types" : [ + "street_address" + ], + "address_components" : [ + { + "types" : [ + "street_number" + ], + "short_name" : "1", + "long_name" : "1" + }, + { + "types" : [ + "route" + ], + "short_name" : "Kirstinmäki", + "long_name" : "Kirstinmäki" + }, + { + "types" : [ + "administrative_area_level_3", + "political" + ], + "short_name" : "Espoo", + "long_name" : "Espoo" + }, + { + "types" : [ + "postal_code" + ], + "short_name" : "02760", + "long_name" : "02760" + }, + { + "types" : [ + "country", + "political" + ], + "short_name" : "FI", + "long_name" : "Suomi" + } + ], + "geometry" : { + "location" : { + "lat" : 60.2015185792087, + "lng" : 24.6667520050026 + }, + "location_type" : "RANGE_INTERPOLATED" + } + } + ] +} diff --git a/test/fixtures/okf_no_results b/test/fixtures/okf_no_results new file mode 100644 index 0000000000000000000000000000000000000000..184b56deadf96dcb3f8a3138cbe72fe4e610c7a6 --- /dev/null +++ b/test/fixtures/okf_no_results @@ -0,0 +1,4 @@ +{ + "status" : "ZERO_RESULTS", + "results" : [] +} diff --git a/test/test_helper.rb b/test/test_helper.rb index ce5ad195739a93e83f74c6b9f42bece6e6d46eed..e57c779ac614dc5c1d818838eea215a38acad638 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -207,6 +207,13 @@ module Geocoder "geocodio_1101_pennsylvania_ave" end end + + class Okf + private + def default_fixture_filename + "okf_kirstinmaki" + end + end end end diff --git a/test/unit/lookups/okf_test.rb b/test/unit/lookups/okf_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..7882ff247cfe024e4d6349065db34952c766b04c --- /dev/null +++ b/test/unit/lookups/okf_test.rb @@ -0,0 +1,38 @@ +# encoding: utf-8 +$: << File.join(File.dirname(__FILE__), "..", "..") +require 'test_helper' + +class OkgTest < GeocoderTestCase + + def setup + Geocoder.configure(lookup: :okf) + end + + def test_okf_result_components + result = Geocoder.search("Kirstinmäki 11b28").first + assert_equal "Espoo", + result.address_components_of_type(:administrative_area_level_3).first['long_name'] + end + + def test_okf_result_components_contains_route + result = Geocoder.search("Kirstinmäki 11b28").first + assert_equal "Kirstinmäki", + result.address_components_of_type(:route).first['long_name'] + end + + def test_okf_result_components_contains_street_number + result = Geocoder.search("Kirstinmäki 11b28").first + assert_equal "1", + result.address_components_of_type(:street_number).first['long_name'] + end + + def test_okf_street_address_returns_formatted_street_address + result = Geocoder.search("Kirstinmäki 11b28").first + assert_equal "Kirstinmäki 1", result.street_address + end + + def test_okf_precision + result = Geocoder.search("Kirstinmäki 11b28").first + assert_equal "RANGE_INTERPOLATED", result.precision + end +end