/* 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.nominatim; import slash.navigation.common.NavigationPosition; import slash.navigation.common.SimpleNavigationPosition; import slash.navigation.geocoding.GeocodingService; import slash.navigation.nominatim.reverse.AddresspartsType; import slash.navigation.nominatim.reverse.ReversegeocodeType; import slash.navigation.nominatim.search.PlaceType; import slash.navigation.nominatim.search.SearchresultsType; import slash.navigation.rest.Get; import javax.xml.bind.JAXBException; 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 Nominatim service. * * @author Christian Pesch */ public class NominatimService implements GeocodingService { private static final Preferences preferences = Preferences.userNodeForPackage(NominatimService.class); private static final String NOMINATIM_URL_PREFERENCE = "nominatiumUrl"; public String getName() { return "Nominatim"; } public boolean isDownload() { return false; } public boolean isOverQueryLimit() { return false; } private String getNominatimUrl() { return preferences.get(NOMINATIM_URL_PREFERENCE, "https://nominatim.openstreetmap.org/"); } private String execute(String uri) throws IOException { String url = getNominatimUrl() + uri; Get get = new Get(url); String result = get.executeAsString(); if (get.isSuccessful()) return result; return null; } private SearchresultsType getSearchFor(String uri) throws IOException { String result = execute(uri); if (result != null) { try { return NominatimUtil.unmarshalSearch(result); } catch (JAXBException e) { throw new IOException("Cannot unmarshall " + result + ": " + e, e); } } return null; } private List<NavigationPosition> extractPositions(List<PlaceType> placeTypes) { List<NavigationPosition> result = new ArrayList<>(placeTypes.size()); for (PlaceType placeType : placeTypes) { result.add(new SimpleNavigationPosition(placeType.getLon().doubleValue(), placeType.getLat().doubleValue(), null, placeType.getDisplayName() + " (" + placeType.getType() + ")")); } return result; } public List<NavigationPosition> getPositionsFor(String address) throws IOException { SearchresultsType result = getSearchFor("search/?q=" + encodeUri(address) + "&limit=10&format=xml"); if (result == null) return null; return extractPositions(result.getPlace()); } private ReversegeocodeType getReverseFor(String uri) throws IOException { String result = execute(uri); if (result != null) { try { return NominatimUtil.unmarshalReverse(result); } catch (JAXBException e) { throw new IOException("Cannot unmarshall " + result + ": " + e, e); } } return null; } public String getAddressFor(NavigationPosition position) throws IOException { ReversegeocodeType type = getReverseFor("reverse?lat=" + position.getLatitude() + "&lon=" + position.getLongitude() + "&zoom=18&addressdetails=1&format=xml"); if (type == null) return null; AddresspartsType parts = type.getAddressparts(); if (parts == null) return null; String result = (parts.getRoad() != null ? parts.getRoad() : "") + (parts.getHouseNumber() != null ? " " + parts.getHouseNumber() : ""); if (result.length() > 0) result += ", "; result += (parts.getPostcode() != null ? parts.getPostcode() : "") + " " + (parts.getCity() != null ? parts.getCity() + ", " : "") + (parts.getCountry() != null ? parts.getCountry() : ""); return trim(result); } }