--- /dev/null
+require 'open-uri'\r
+require 'rexml/document'\r
+\r
+module Ym4r\r
+ module GmPlugin\r
+ module Geocoding\r
+\r
+ GEO_SUCCESS = 200\r
+ GEO_MISSING_ADDRESS = 601\r
+ GEO_UNKNOWN_ADDRESS = 602\r
+ GEO_UNAVAILABLE_ADDRESS = 603\r
+ GEO_BAD_KEY = 610\r
+ GEO_TOO_MANY_QUERIES = 620\r
+ GEO_SERVER_ERROR = 500\r
+ \r
+ #Gets placemarks by querying the Google Maps Geocoding service with the +request+ string. Options can either an explicity GMaps API key (<tt>:key</tt>) or a host, (<tt>:host</tt>). \r
+ def self.get(request,options = {})\r
+ api_key = ApiKey.get(options)\r
+ output = options[:output] || "kml"\r
+ url = "http://maps.google.com/maps/geo?q=#{URI.encode(request)}&key=#{api_key}&output=#{output}"\r
+\r
+ res = open(url).read\r
+\r
+ case output.to_sym\r
+ when :json\r
+ res = eval(res.gsub(":","=>")) #!!!EVAL EVAL EVAL EVAL!!! hopefully we can trust google...\r
+ placemarks = Placemarks.new(res['name'],res['Status']['code'])\r
+ if res['Placemark']\r
+ placemark = res['Placemark']\r
+ \r
+ placemark.each do |data|\r
+ \r
+ data_country = data['Country']['CountryNameCode'] rescue ""\r
+ data_administrative = data['Country']['AdministrativeArea']['AdministrativeAreaName'] rescue ""\r
+ data_sub_administrative = data['Country']['AdministrativeArea']['SubAdministrativeArea']['SubAdministrativeAreaName'] rescue ""\r
+ data_locality = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['LocalityName'] rescue ""\r
+ data_dependent_locality = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']['DependentLocalityName'] rescue ""\r
+ data_thoroughfare = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']['Thoroughfare']['ThoroughfareName'] rescue ""\r
+ data_postal_code = data['Country']['AdministrativeArea']['SubAdministrativeArea']['Locality']['DependentLocality']['Thoroughfare']['PostalCode']['PostalCodeNumber'] rescue ""\r
+ lon, lat = data['Point']['coordinates'][0,2]\r
+ data_accuracy = data['Accuracy']\r
+ unless data_accuracy.nil?\r
+ data_accuracy = data_accuracy.to_i\r
+ end\r
+ \r
+ placemarks << Geocoding::Placemark.new(data['address'],\r
+ data_country,\r
+ data_administrative,\r
+ data_sub_administrative,\r
+ data_locality,\r
+ data_dependent_locality,\r
+ data_thoroughfare,\r
+ data_postal_code,\r
+ lon, lat, data_accuracy)\r
+ \r
+ end\r
+ end\r
+ when :kml, :xml\r
+ \r
+ doc = REXML::Document.new(res) \r
+\r
+ response = doc.elements['//Response']\r
+ placemarks = Placemarks.new(response.elements['name'].text,response.elements['Status/code'].text.to_i)\r
+ response.elements.each(".//Placemark") do |placemark|\r
+ data = placemark.elements\r
+ data_country = data['.//CountryNameCode']\r
+ data_administrative = data['.//AdministrativeAreaName']\r
+ data_sub_administrative = data['.//SubAdministrativeAreaName']\r
+ data_locality = data['.//LocalityName']\r
+ data_dependent_locality = data['.//DependentLocalityName']\r
+ data_thoroughfare = data['.//ThoroughfareName']\r
+ data_postal_code = data['.//PostalCodeNumber']\r
+ lon, lat = data['.//coordinates'].text.split(",")[0..1].collect {|l| l.to_f }\r
+ data_accuracy = data['.//*[local-name()="AddressDetails"]'].attributes['Accuracy']\r
+ unless data_accuracy.nil?\r
+ data_accuracy = data_accuracy.to_i\r
+ end\r
+ placemarks << Geocoding::Placemark.new(data['address'].text,\r
+ data_country.nil? ? "" : data_country.text,\r
+ data_administrative.nil? ? "" : data_administrative.text,\r
+ data_sub_administrative.nil? ? "" : data_sub_administrative.text,\r
+ data_locality.nil? ? "" : data_locality.text,\r
+ data_dependent_locality.nil? ? "" : data_dependent_locality.text,\r
+ data_thoroughfare.nil? ? "" : data_thoroughfare.text,\r
+ data_postal_code.nil? ? "" : data_postal_code.text,\r
+ lon, lat, data_accuracy )\r
+ end\r
+ end\r
+ \r
+ placemarks\r
+ end\r
+\r
+ #Group of placemarks returned by the Geocoding service. If the result is valid the +status+ attribute should be equal to <tt>Geocoding::GE0_SUCCESS</tt>\r
+ class Placemarks < Array\r
+ attr_accessor :name,:status\r
+\r
+ def initialize(name,status)\r
+ super(0)\r
+ @name = name\r
+ @status = status\r
+ end\r
+ end\r
+\r
+ #A result from the Geocoding service.\r
+ class Placemark < Struct.new(:address,:country_code,:administrative_area,:sub_administrative_area,:locality,:dependent_locality,:thoroughfare,:postal_code,:longitude,:latitude,:accuracy)\r
+ def lonlat\r
+ [longitude,latitude]\r
+ end\r
+\r
+ def latlon\r
+ [latitude,longitude]\r
+ end\r
+ end\r
+ end\r
+ end\r
+end\r