package esl.datastructures.util;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.util.Hash;
import com.mongodb.util.JSON;
import org.apache.commons.codec.net.URLCodec;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
public class YahooPlaceFinderReverseGeo {
private Logger logger = Logger.getLogger(YahooPlaceFinderReverseGeo.class);
private static YahooPlaceFinderReverseGeo instance = new YahooPlaceFinderReverseGeo();
private HashMap<String, BasicDBObject> geocodeCache = null;
private GeocodingCache persistentGeocodingCache = new GeocodingCache();
private URLCodec codec = new URLCodec();
public YahooPlaceFinderReverseGeo() {
geocodeCache = persistentGeocodingCache.getAll();
}
public static BasicDBObject reverseGeoCode(double lat, double lon) throws IOException {
return instance.queryPlaceFinder(lat, lon);
}
public static BasicDBObject geoCode(String address) throws IOException {
return instance.queryPlaceFinder(address);
}
private BasicDBObject queryPlaceFinder(String addressWithSpaces) throws IOException {
BasicDBObject cachedObj = geocodeCache.get(addressWithSpaces);
if (cachedObj != null) {
//logger.info("Found cached address for: " + addressWithSpaces);
return cachedObj;
}
BasicDBObject pGcInfo = persistentGeocodingCache.getFromCache(addressWithSpaces);
if (pGcInfo != null) {
geocodeCache.put(addressWithSpaces, pGcInfo);
return pGcInfo;
}
logger.info("Geocoding adress: " + addressWithSpaces);
String url = "http://query.yahooapis.com/v1/public/yql?q=" +
codec.encode("select * from geo.placefinder WHERE text = \"" + addressWithSpaces + "\"", "ISO-8859-1") +
"&appid=UmMtXR7c&format=json";
HttpClient httpclient = new DefaultHttpClient();
String buffer = httpclient.execute(new HttpGet(url), new BasicResponseHandler());
BasicDBObject object = (BasicDBObject) JSON.parse(buffer);
BasicDBObject query = (BasicDBObject) object.get("query");
BasicDBObject result;
if (query.getInt("count") == 0) {
throw new RuntimeException("Geocoder found no results for " + addressWithSpaces);
}
if (query.getInt("count") == 1) {
result = (BasicDBObject) query.get("results");
}
else {
BasicDBObject r = (BasicDBObject) query.get("results");
BasicDBList list = (BasicDBList) r.get("Result");
result = (BasicDBObject) list.get(0);
}
logger.info("geocoding " + addressWithSpaces + " = " + result);
/*** old impl
URL placeFinderURL = new URL("http://where.yahooapis.com/geocode?q=" + addressWithSpaces.replaceAll(" ", "%20")
+ "&flags=J&appid=UmMtXR7c");
URLConnection placeFinderConnection = placeFinderURL.openConnection();
BufferedReader in = new BufferedReader(new
InputStreamReader(placeFinderConnection.getInputStream()));
StringBuilder buffer = new StringBuilder(100);
int ich;
while ((ich = in.read()) != -1) buffer.append((char) ich);
in.close();
int ix = buffer.indexOf("[");
if (ix == -1) return null;
int eix = buffer.indexOf("]");
if (eix == -1) return null;
BasicDBList list = (BasicDBList) JSON.parse(buffer.substring(ix, eix + 1));
if (list.size() > 1) logger.info("LocationFetcher got more than one location");
if (list.size() == 0) return null;
BasicDBObject result = (BasicDBObject) list.get(0);
*/
geocodeCache.put(addressWithSpaces, result);
persistentGeocodingCache.addToCache(addressWithSpaces, result);
return result;
}
private BasicDBObject queryFactual(double lat, double lon) throws IOException {
logger.info("Reverse Geocoding Factual");
URL placeFinderURL = new URL("http://api.v3.factual.com/places/geocode?geo={%22$point%22:[" + lat + "," + lon
+ "]}&KEY=T2DDACVJNeHrnT835pAz7MufmdQm64pxAE3VFHv3");
URLConnection placeFinderConnection = placeFinderURL.openConnection();
BufferedReader in = new BufferedReader(new
InputStreamReader(placeFinderConnection.getInputStream()));
StringBuilder buffer = new StringBuilder(100);
int ich;
while ((ich = in.read()) != -1) buffer.append((char) ich);
in.close();
BasicDBObject ret = new BasicDBObject();
int ix = buffer.indexOf("[");
if (ix == -1) return ret;
int eix = buffer.indexOf("]");
if (eix == -1) return ret;
BasicDBList datalist = (BasicDBList) JSON.parse(buffer.substring(ix, eix + 1));
if (datalist.size() == 0) return ret;
BasicDBObject object = (BasicDBObject) datalist.get(0);
if (object.containsField("locality")) ret.put("city", object.getString("locality"));
if (object.containsField("region")) ret.put("state", object.getString("region"));
if (object.containsField("country")) ret.put("country", object.getString("country"));
if (object.containsField("postcode")) ret.put("uzip", object.getString("postcode"));
if (object.containsField("address")) ret.put("line1", object.getString("address"));
return object;
}
private BasicDBObject queryPlaceFinder(double lat, double lon) throws IOException {
String url = "http://query.yahooapis.com/v1/public/yql?q="
+ codec.encode("select * from geo.placefinder where text=\"" + lat + ", " + lon + "\" and gflags=\"R\"", "ISO-8859-1")
+ "&appid=UmMtXR7c&format=json";
HttpClient httpclient = new DefaultHttpClient();
String buffer = httpclient.execute(new HttpGet(url), new BasicResponseHandler());
BasicDBObject object = (BasicDBObject) JSON.parse(buffer);
BasicDBObject query = (BasicDBObject) object.get("query");
BasicDBObject result;
if (query.getInt("count") == 0) {
throw new RuntimeException("Rev-Geocoder found no results for " + lat + ", " + lon);
}
if (query.getInt("count") == 1) {
result = (BasicDBObject) query.get("results");
}
else {
BasicDBObject r = (BasicDBObject) query.get("results");
BasicDBList list = (BasicDBList) r.get("Result");
result = (BasicDBObject) list.get(0);
}
logger.info("reverse geocoding " + lat + ", " + lon + " = " + result);
return result;
/*logger.info("Reverse Geocoding");
URL placeFinderURL = new URL("http://where.yahooapis.com/geocode?q=" + lat + "," + lon
+ "&gflags=R&flags=J&appid=UmMtXR7c");
URLConnection placeFinderConnection = placeFinderURL.openConnection();
BufferedReader in = new BufferedReader(new
InputStreamReader(placeFinderConnection.getInputStream()));
StringBuilder buffer = new StringBuilder(100);
int ich;
while ((ich = in.read()) != -1) buffer.append((char) ich);
in.close();
int ix = buffer.indexOf("[");
if (ix == -1) return null;
int eix = buffer.indexOf("]");
if (eix == -1) return null;
BasicDBList list = (BasicDBList) JSON.parse(buffer.substring(ix, eix + 1));
if (list.size() > 1) logger.info("LocationFetcher got more than one location");
if (list.size() == 0) return null;
return (BasicDBObject) list.get(0);
*/
//return queryFactual(lat, lon);
}
}