package com.awsmithson.tcx2nikeplus.http; import com.awsmithson.tcx2nikeplus.util.Log; import com.awsmithson.tcx2nikeplus.util.Util; import com.google.common.base.Preconditions; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import org.w3c.dom.Document; import org.xml.sax.SAXException; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; import java.util.TimeZone; import java.util.logging.Level; import javax.annotation.Nonnull; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; public class Geonames { private static final @Nonnull Log logger = Log.getInstance(); private static final @Nonnull String URL_TIMEZONE = "http://ws.geonames.org/timezone?username=tcx2nikeplus_app&lat=%.4f&lng=%.4f"; private static final @Nonnull BigDecimal MIN_LONGITUDE_DEGREES = new BigDecimal("-180"); private static final @Nonnull BigDecimal MAX_LONGITUDE_DEGREES = new BigDecimal("180"); private static final @Nonnull BigDecimal MIN_LATITUDE_DEGREES = new BigDecimal("-90"); private static final @Nonnull BigDecimal MAX_LATITUDE_DEGREES = new BigDecimal("90"); public static @Nonnull TimeZone getTimeZone(@Nonnull BigDecimal longitudeDegrees, @Nonnull BigDecimal latitudeDegrees) throws IOException, ParserConfigurationException, SAXException { Preconditions.checkNotNull(longitudeDegrees, "longitudeDegrees argument is null."); Preconditions.checkNotNull(latitudeDegrees, "latitudeDegrees argument is null."); ensureInRange(longitudeDegrees, MIN_LONGITUDE_DEGREES, MAX_LONGITUDE_DEGREES, "longitudeDegrees"); ensureInRange(latitudeDegrees, MIN_LATITUDE_DEGREES, MAX_LATITUDE_DEGREES, "latitudeDegrees"); logger.out("Looking up timezone for lon: %.4f, lat: %.4f", longitudeDegrees, latitudeDegrees); try (CloseableHttpClient client = HttpClients.createDefaultHttpClientBuilder().build()) { HttpPost post = new HttpPost(String.format(URL_TIMEZONE, latitudeDegrees, longitudeDegrees)); try (CloseableHttpResponse response = client.execute(post)) { logger.out(Level.FINE, " - response code: %d", response.getStatusLine().getStatusCode()); HttpEntity httpEntity = response.getEntity(); if (httpEntity != null) { try (InputStream inputStream = httpEntity.getContent()) { Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream); EntityUtils.consumeQuietly(httpEntity); document.normalize(); logger.out(Level.FINEST, "\t%s", Util.documentToString(document)); String timeZoneId = Util.getSimpleNodeValue(document, "timezoneId"); logger.out(" - lon: %.4f, lat: %.4f = %s", longitudeDegrees, latitudeDegrees, timeZoneId); return TimeZone.getTimeZone(timeZoneId); } } else { throw new NullPointerException("Http response empty"); } } } } private static void ensureInRange(@Nonnull BigDecimal value, @Nonnull BigDecimal minAcceptable, @Nonnull BigDecimal maxAcceptable, @Nonnull String argumentName) { Preconditions.checkArgument(value.compareTo(minAcceptable) > 0, "%s argument [%s] must be >= %s.", argumentName, value, minAcceptable); Preconditions.checkArgument(value.compareTo(maxAcceptable) < 0, "%s argument [%s] must be <= %s.", argumentName, value, maxAcceptable); } }