Tuesday, July 12, 2011

Geocoding an address with Google Maps API in Java

Geocoding is the process of finding associated geographic coordinates (often expressed as latitude and longitude) from other geographic data, such as street addresses, or zip codes (postal codes). With geographic coordinates the features can be mapped and entered into Geographic Information Systems, or the coordinates can be embedded into media such as digital photographs via geotagging.
I made a simple method that giving an address it returns a list of with the corresponding formatted address, latitue, longitide, separated by ";".

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.ddelizia.batchgeocoding.client.BasicService;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
public class GeocoderService {
public String processAddress(String input){
String list="";
String xml=getResponse(normalize(s));
List<String[]> resultOfXML=readXML(xml);
for (String[] elements : resultOfXML) {
list+=s+";"+elements[0]+";"+elements[1]+";"+elements[2]+";\n";
}
return list;
}
public static String getResponse(String address){
String response="";
try {
URL url = new URL("http://maps.google.com/maps/api/geocode/xml?address="+address+"&sensor=false");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.connect();
InputStream in = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in,"UTF-8"));
String newText = reader.readLine();
while (newText!=null){
response+=newText;
newText = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
public static String normalize(String address){
address=address.replaceAll(" ", "+");
while (address.contains("++")){
address=address.replace("++", "+");
}
return address;
}
public static List<String[]> readXML(String xml){
List<String[]> list= new LinkedList<String [] >();
try {
SAXParserFactory spf=SAXParserFactory.newInstance();
SAXParser interpreter = spf.newSAXParser();
interpreter.parse(new InputSource( new StringReader( xml )), new XMLHandler(list));
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
}

Here is the class XMLHandler to parse the XML answer
import java.util.List;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XMLHandler extends DefaultHandler {
private boolean isGeometry = false;
private boolean isLocation = false;
private boolean isLat = false;
private boolean isLon = false;
private boolean isFormattedAddress = false;
private List<String[]> result;
private String[] current;
public XMLHandler(List<String[]> result) {
super();
this.result = result;
}
@Override
public void startDocument() throws SAXException {
}
@Override
public void endDocument() throws SAXException {
}
@Override
public void startElement(String uri, String localName, String qName,
org.xml.sax.Attributes attributes) throws SAXException {
if (qName.equals("formatted_address")) {
current = new String[3];
isFormattedAddress = true;
} else if (qName.equals("geometry")) {
isGeometry = true;
} else if (qName.equals("location")) {
isLocation = true;
} else if (qName.equals("lat")) {
isLat = true;
} else if (qName.equals("lng")) {
isLon = true;
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equals("formatted_address")) {
isFormattedAddress = false;
} else if (qName.equals("geometry")) {
isGeometry = false;
result.add(current);
} else if (qName.equals("location")) {
isLocation = false;
} else if (qName.equals("lat")) {
isLat = false;
} else if (qName.equals("lng")) {
isLon = false;
}
}
@Override
public void characters(char ch[], int start, int length) {
if (isGeometry && isLocation && isLat) {
current[1] = new String(ch, start, length);
} else if (isGeometry && isLocation && isLon) {
current[2] = new String(ch, start, length);
} else if (isFormattedAddress) {
current[0] = new String(ch, start, length);
}
}
}
view raw XMLHandler.java hosted with ❤ by GitHub