/* This file is part of RouteConverter. RouteConverter 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. RouteConverter 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 RouteConverter; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Copyright (C) 2007 Christian Pesch. All Rights Reserved. */ package slash.navigation.photon; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.geojson.Feature; import org.geojson.FeatureCollection; import org.geojson.GeoJsonObject; import org.geojson.LngLatAlt; import org.geojson.Point; import slash.navigation.common.NavigationPosition; import slash.navigation.common.SimpleNavigationPosition; import slash.navigation.geocoding.GeocodingService; import slash.navigation.rest.Get; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.prefs.Preferences; import static slash.common.io.Transfer.encodeUri; import static slash.common.io.Transfer.trim; /** * Encapsulates REST access to the OSM Photon service. * * @author Christian Pesch */ public class PhotonService implements GeocodingService { private static final Preferences preferences = Preferences.userNodeForPackage(PhotonService.class); private static final String PHOTON_URL_PREFERENCE = "photonUrl"; public String getName() { return "Photon"; } public boolean isDownload() { return false; } public boolean isOverQueryLimit() { return false; } private String getPhotonUrl() { return preferences.get(PHOTON_URL_PREFERENCE, "http://photon.komoot.de"); } private String execute(String uri) throws IOException { String url = getPhotonUrl() + uri; Get get = new Get(url); String result = get.executeAsString(); if (get.isSuccessful()) return result; return null; } private FeatureCollection getResultFor(String uri) throws IOException { String result = execute(uri); if (result != null) { try { return new ObjectMapper().readValue(result, FeatureCollection.class); } catch (JsonParseException | JsonMappingException e) { throw new IOException("Cannot unmarshall " + result + ": " + e, e); } } return null; } private List<NavigationPosition> extractPositions(List<Feature> features) { List<NavigationPosition> result = new ArrayList<>(features.size()); for (Feature feature : features) { GeoJsonObject geometry = feature.getGeometry(); if (!(geometry instanceof Point)) continue; Point point = Point.class.cast(geometry); LngLatAlt lngLatAlt = point.getCoordinates(); String type = feature.getProperty("osm_key"); result.add(new SimpleNavigationPosition(lngLatAlt.getLongitude(), lngLatAlt.getLatitude(), null, getDisplayName(feature) + " (" + type + ")")); } return result; } public List<NavigationPosition> getPositionsFor(String address) throws IOException { FeatureCollection collection = getResultFor("/api/?q=" + encodeUri(address) + "&limit=10"); if (collection == null) return null; return extractPositions(collection.getFeatures()); } public String getAddressFor(NavigationPosition position) throws IOException { FeatureCollection collection = getResultFor("/reverse/?lon=" + position.getLongitude() + "&lat=" + position.getLatitude()); if (collection == null) return null; List<Feature> features = collection.getFeatures(); if (features.size() == 0) return null; Feature feature = features.get(0); GeoJsonObject geometry = feature.getGeometry(); if (!(geometry instanceof Point)) return null; return getDisplayName(feature); } private String getProperty(Feature feature, String propertyName) { Object property = feature.getProperty(propertyName); return property != null ? trim(property.toString()) : ""; } private String getDisplayName(Feature feature) { String result = getProperty(feature, "name"); if(result.length() > 0) result += ", "; String postcode = getProperty(feature, "postcode"); if(postcode.length() > 0) result += postcode; String city = getProperty(feature, "city"); if(city.length() > 0) result += " " + city; String state = getProperty(feature, "state"); if(state.length() > 0) result += ", " + state; String country = getProperty(feature, "country"); if(country.length() > 0) result += ", " + country; result = result.replaceAll(" ", " "); if(result.endsWith(", ")) result = result.substring(0, result.length() - 2); return result; } }