org.photovault.geocoding.OSMGeocoder.java Source code

Java tutorial

Introduction

Here is the source code for org.photovault.geocoding.OSMGeocoder.java

Source

/*
  Copyright (c) 2011 Harri Kaimio
    
  This file is part of Photovault.
    
  Photovault is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
    
  Photovault is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  General Public License for more details.
    
  You should have received a copy of the GNU General Public License
  along with Photovault; if not, write to the Free Software Foundation,
  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */

package org.photovault.geocoding;

import ch.hsr.geohash.GeoHash;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.photovault.imginfo.location.Location;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * Geocode provider that uses the Open Street Maps API for finding the location
 * information
 * @author Harri Kaimio
 * @since 0.6.0
 */
public class OSMGeocoder implements GeocodeProvider {

    private static Log log = LogFactory.getLog(OSMGeocoder.class);

    private XPathExpression reverseAddrExpr = null;
    private XPathExpression reverseHouseExpr = null;
    private XPathExpression reverseRoadExpr = null;
    private XPathExpression reverseSuburbExpr = null;
    private XPathExpression reverseCityExpr = null;
    private XPathExpression reverseCountryExpr = null;
    private XPathExpression reverseCountryCodeExpr = null;

    public OSMGeocoder() {
        XPathFactory xpf = XPathFactory.newInstance();
        XPath path = xpf.newXPath();
        try {
            reverseAddrExpr = path.compile("/reversegeocode/result/text()");
            reverseHouseExpr = path.compile("/reversegeocode/addressparts/house/text()");
            reverseRoadExpr = path.compile("/reversegeocode/addressparts/road/text()");
            reverseSuburbExpr = path.compile("/reversegeocode/addressparts/suburb/text()");
            reverseCityExpr = path.compile("/reversegeocode/addressparts/city/text()");
            reverseCountryExpr = path.compile("/reversegeocode/addressparts/country/text()");
            reverseCountryCodeExpr = path.compile("/reversegeocode/addressparts/country_code/text()");
        } catch (XPathExpressionException e) {
            log.error(e);
        }
    }

    public Location findLocation(String addr) {
        String urlbase = "http://nominatim.openstreetmap.org/search?q=";
        try {
            String encoded = urlbase + URLEncoder.encode(addr, "utf-8") + "&format=xml&addressdetails=1";
            URL url = new URL(encoded);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            InputStream is = conn.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true); // never forget this!
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(is);
            parsePlaces(doc);
        } catch (IOException e) {
            log.error(e);
        } catch (ParserConfigurationException e) {
            log.error(e);
        } catch (SAXException e) {
            log.error(e);
        }
        return null;
    }

    private List<Location> parsePlaces(Document doc) {
        List<Location> ret = new ArrayList();
        XPathFactory xpf = XPathFactory.newInstance();
        XPath nodesPath = xpf.newXPath();
        try {
            NodeList placeNodes = (NodeList) nodesPath.evaluate("/searchresults/place", doc,
                    XPathConstants.NODESET);
            for (int n = 0; n < placeNodes.getLength(); n++) {
                Location loc = new Location();
                Node placeNode = placeNodes.item(n);
                String road = nodesPath.evaluate("//road/text()", placeNode);
                String suburb = nodesPath.evaluate("//suburb/text()", placeNode);
                String city = nodesPath.evaluate("//city/text()", placeNode);
                String county = nodesPath.evaluate("//county/text()", placeNode);
                String country = nodesPath.evaluate("//country/text()", placeNode);
                String countryCode = nodesPath.evaluate("//country_code/text()", placeNode);
                String latStr = nodesPath.evaluate("@lat", placeNode);
                String lonStr = nodesPath.evaluate("@lon", placeNode);
                String desc = nodesPath.evaluate("@display_name", placeNode);
                loc.setRoad(road);
                loc.setSuburb(suburb);
                loc.setCity(city);
                loc.setCountry(country);
                loc.setCountryCode(countryCode);
                double lat = Double.parseDouble(latStr);
                double lon = Double.parseDouble(lonStr);
                GeoHash geohash = GeoHash.withBitPrecision(lat, lon, 60);
                loc.setCoordinate(geohash);
                ret.add(loc);
            }

        } catch (XPathExpressionException e) {
            log.error(e);
        }
        return ret;

    }

    public Location findByGeoHash(String geohashStr) {
        GeoHash geohash = GeoHash.fromGeohashString(geohashStr);
        double lat = geohash.getPoint().getLatitude();
        double lon = geohash.getPoint().getLongitude();
        String urlbase = "http://nominatim.openstreetmap.org/reverse?";
        Location ret = null;
        try {
            String encoded = urlbase + "lat=" + lat + "&lon=" + lon + "&format=xml&addressdetails=1&zoom=18";
            URL url = new URL(encoded);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            InputStream is = conn.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true); // never forget this!
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(is);
            ret = parseReverseResult(doc);
            ret.setCoordinate(geohash);
        } catch (IOException e) {
            log.error(e);
        } catch (ParserConfigurationException e) {
            log.error(e);
        } catch (SAXException e) {
            log.error(e);
        }
        return ret;
    }

    Location parseReverseResult(Document doc) {
        Location ret = new Location();
        try {
            String address = reverseAddrExpr.evaluate(doc);
            ret.setDescription(address);
            String house = reverseHouseExpr.evaluate(doc);
            ret.setBuilding(house);
            String road = reverseRoadExpr.evaluate(doc);
            ret.setRoad(road);
            String suburb = reverseSuburbExpr.evaluate(doc);
            ret.setSuburb(suburb);
            String city = reverseCityExpr.evaluate(doc);
            ret.setCity(city);
            String country = reverseCountryExpr.evaluate(doc);
            ret.setCountry(country);
            String countryCode = reverseCountryCodeExpr.evaluate(doc);
            ret.setCountryCode(countryCode);
        } catch (XPathExpressionException e) {
            log.error(e);
        }
        return ret;
    }

    static public void main(String args[]) {
        GeocodeProvider p = new OSMGeocoder();
        p.findLocation("Mannerheimintie,Finland");

        Location l = p.findByGeoHash("ud9wzn7vxgrs");
        System.out.println(l.getDescription());
    }
}