/* * HTTPGoogleAPI.java * * Copyright (c) 2009-2010 PSU Capstone Team D * Scott Glazer, Cong Hoang, Ba Nguyen, Marek Dolgos, * Steve Phelps, Mark Smith, Roman Taycher * * Citation Application is free/open source software released under * the unmodified MIT/X11 license. A copy can be found in the * LICENSE file or at: * * http://www.opensource.org/licenses/mit-license.php * */ package citation.query; import java.io.InputStream; import java.util.Vector; import javax.microedition.io.Connector; import javax.microedition.io.StreamConnection; /** * HTTPGoogleAPI class - provides reverse geocode lookup through Google api * All methods are static and provide helper functions for address * lookup. * * Perform operation in the following sequence: * --------------------------------------------- * 1. ReverseGeoQuery - get address list from a lat/lon * 2. getAddressList - parse results from #1, and return an array of addresses */ public class HTTPGoogleAPI { public class ParseType { public static final int ADDRESS = 1; public static final int CITY = 2; public static final int STATE = 3; public static final int ZIP = 4; } public static final int MIN_ACCURACY_LEVEL = 6; public static final int MAX_ADDRESS_RESULTS = 8; /* * GEOCODE ACCURACY LEVELS 0 Unknown accuracy. 1 Country level accuracy. 2 * Region (state, province, prefecture, etc.) level accuracy. 3 Sub-region * (county, municipality, etc.) level accuracy. 4 Town (city, village) level * accuracy. 5 Post code (zip code) level accuracy. 6 Street level accuracy. * 7 Intersection level accuracy. 8 Address level accuracy. 9 Premise * (building name, property name, shopping center, etc.) level accuracy. */ /** * ReverseGeoQuery - runs the basic geo query to Google geo query service * * @param lat - latitude of lookup location * @param lon - longitute of lookup location * * @return - String containing the raw Google lookup results */ public static String ReverseGeoQuery(double lat, double lon) { String response = null; StringBuffer url = new StringBuffer(); url.append("http://maps.google.com/maps/geo?"); url.append("q=" + Double.toString(lat) + "," + Double.toString(lon)); url.append("&output=json&sensor=true_or_false"); try { // String result = post(url.toString()); response = getPage(url.toString()); } // TODO clean up empty catch catch (Exception e) { System.out.println("HTTPGoogleAPI.getPage Exception: " + e.toString()); } return response; } /* * getPage - sample code from web for getting simple page results TODO clean * up code for error conditions and remove the 255 response limit */ private static String getPage(String url) { String response = null; StreamConnection s = null; try { // try wifi network connection first s = (StreamConnection) Connector.open(url + ";deviceside=true;interface=wifi"); } catch (Exception e) { // no-op; failure to open a wi-fi connection is quite likely } try { // wi-fi failed so try normal network connection if (s == null) { s = (StreamConnection) Connector.open(url); } // still no good - time to bail if (s == null) return response; InputStream input = s.openInputStream(); byte[] data = new byte[256]; int len = 0; StringBuffer raw = new StringBuffer(); while (-1 != (len = input.read(data))) { raw.append(new String(data, 0, len)); } response = raw.toString(); input.close(); s.close(); } // TODO clean up empty catch catch (Exception e) { System.out.println("StreamConnection Exception: " + e.toString()); } return response; } /** * getAddressList - return all geocode addresses with accuracy 6 or better * * @param _str - full response string to the geocode request * @return - array of strings containing address parse results from previous Google query */ public static String[] getAddressList(String _str) { String[] response = null; Vector addrList = new Vector(); String startAddressParseKey = "\"address\": "; String endParseKey = ",\n"; String accuracyParseKey = "\"Accuracy\" :"; int accuracyLevel = 0; int beginIndex = 0; int endIndex = 0; for (int i = 0; i < MAX_ADDRESS_RESULTS; i++) { try { beginIndex = _str.indexOf(startAddressParseKey, beginIndex) + startAddressParseKey.length() + 1; endIndex = _str.indexOf(endParseKey, beginIndex) - 1; String fullAddress = _str.substring(beginIndex, endIndex); beginIndex = endIndex + 1; beginIndex = _str.indexOf(accuracyParseKey, beginIndex) + accuracyParseKey.length() + 1; endIndex = _str.indexOf(endParseKey, beginIndex); String accStr = _str.substring(beginIndex, endIndex); accuracyLevel = Integer.parseInt(accStr.trim()); // only add items that meet minimum accuracy levels if ( accuracyLevel >= MIN_ACCURACY_LEVEL ) { addrList.addElement(fullAddress); } else { // remaining results will be at or below this accuracy, so we can break and return break; } } // one of the parse functions failed, so bail as the results are unknown and there's no // simple way to recover and pick up where we left off. catch(IndexOutOfBoundsException ex) { break; } catch (NumberFormatException ex) { break; } } // transfer the vector into an appropriately sized array if (addrList.size() > 0) { response = new String[addrList.size()]; for ( int j = 0; j < addrList.size(); j++) { response[j] = (String)addrList.elementAt(j); } } return response; } /** * parseFullMapResult - take a geocode response, and parse out an * address into the requested parts * * @param _str - full address string from a Google query * @param addrType - enum from HTTPGoogleAPI indicating which part of an address to get * * @return - string of the address part requested */ public static String parseFullMapResult(String _str, int _addrType) { String fullAddress = null; String[] addrList = getAddressList(_str); if (addrList.length <= 0) { return null; } fullAddress = addrList[0]; return parseAddressResult(fullAddress, _addrType); } /** * parseAddressResult - parse a full address into it's constituent parts * * @param _str - assumes input string is a full address as street, city, * state, zip * * @param addrType - defines which portion of string to return * * @return - string of portion of address requested */ public static String parseAddressResult(String _str, int _addrType) { String response = null; String address; String city; String state; String zip; int beginIndex = 0; int endIndex = 0; endIndex = _str.indexOf(",", beginIndex); address = _str.substring(beginIndex, endIndex); beginIndex = endIndex + 2; endIndex = _str.indexOf(",", beginIndex); city = _str.substring(beginIndex, endIndex); beginIndex = endIndex + 2; endIndex = _str.indexOf(" ", beginIndex); state = _str.substring(beginIndex, endIndex); beginIndex = endIndex + 1; endIndex = _str.indexOf(",", beginIndex); zip = _str.substring(beginIndex, endIndex); if ((int) _addrType == ParseType.ADDRESS) { response = address; } else if (_addrType == ParseType.CITY) { response = city; } else if (_addrType == ParseType.STATE) { response = state; } else if (_addrType == ParseType.ZIP) { response = zip; } else { response = _str; } return response; } }