diff --git a/src/main/java/by/prominence/openweather/api/provider/WeatherProvider.java b/src/main/java/by/prominence/openweather/api/AuthenticationTokenBasedRequester.java similarity index 76% rename from src/main/java/by/prominence/openweather/api/provider/WeatherProvider.java rename to src/main/java/by/prominence/openweather/api/AuthenticationTokenBasedRequester.java index 56aa8d3..cab5928 100644 --- a/src/main/java/by/prominence/openweather/api/provider/WeatherProvider.java +++ b/src/main/java/by/prominence/openweather/api/AuthenticationTokenBasedRequester.java @@ -20,17 +20,14 @@ * SOFTWARE. */ -package by.prominence.openweather.api.provider; +package by.prominence.openweather.api; -import by.prominence.openweather.api.model.weather.WeatherResponse; +abstract class AuthenticationTokenBasedRequester { -public class WeatherProvider extends AbstractOpenWeatherProvider { + protected String authToken; - public WeatherProvider(String authToken) { - super(authToken); + protected AuthenticationTokenBasedRequester(String authToken) { + this.authToken = authToken; } - protected String getRequestType() { - return "weather"; - } } diff --git a/src/main/java/by/prominence/openweather/api/BasicRequester.java b/src/main/java/by/prominence/openweather/api/BasicRequester.java new file mode 100644 index 0000000..659f226 --- /dev/null +++ b/src/main/java/by/prominence/openweather/api/BasicRequester.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018 Alexey Zinchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package by.prominence.openweather.api; + +import by.prominence.openweather.api.constants.System; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; + +abstract class BasicRequester extends AuthenticationTokenBasedRequester { + + protected String language; + protected String unit; + protected String accuracy; + + protected BasicRequester(String authToken) { + super(authToken); + } + + protected URL buildURL(String requestSpecificParameters) throws MalformedURLException { + + StringBuilder urlBuilder = new StringBuilder(System.OPEN_WEATHER_API_URL); + urlBuilder.append(getRequestType()); + urlBuilder.append(requestSpecificParameters); + + urlBuilder.append("&appid="); + urlBuilder.append(authToken); + + + if (language != null) { + urlBuilder.append("&lang="); + urlBuilder.append(language); + } + + if (unit != null) { + urlBuilder.append("&units="); + urlBuilder.append(unit); + } + + if (accuracy != null) { + urlBuilder.append("&type="); + urlBuilder.append(accuracy); + } + + Map additionalParameters = getAdditionalParameters(); + if (additionalParameters != null) { + additionalParameters.forEach((key, value) -> { + urlBuilder.append("&"); + urlBuilder.append(key); + urlBuilder.append("="); + urlBuilder.append(value); + }); + } + + return new URL(urlBuilder.toString()); + } + + protected Map getAdditionalParameters() { + return null; + } + + protected abstract String getRequestType(); + +} diff --git a/src/main/java/by/prominence/openweather/api/ForecastRequester.java b/src/main/java/by/prominence/openweather/api/ForecastRequester.java new file mode 100644 index 0000000..576d112 --- /dev/null +++ b/src/main/java/by/prominence/openweather/api/ForecastRequester.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2018 Alexey Zinchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package by.prominence.openweather.api; + +import by.prominence.openweather.api.exception.DataNotFoundException; +import by.prominence.openweather.api.exception.InvalidAuthTokenException; +import by.prominence.openweather.api.model.Coordinates; +import by.prominence.openweather.api.model.forecast.ForecastResponse; +import by.prominence.openweather.api.utils.JsonUtils; +import by.prominence.openweather.api.utils.RequestUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +public class ForecastRequester extends BasicRequester { + + private int amountOfDays = -1; + + ForecastRequester(String authToken) { + super(authToken); + } + + public ForecastRequester setAmountOfDays(int amountOfDays) { + this.amountOfDays = amountOfDays; + return this; + } + + public ForecastRequester setLanguage(String language) { + this.language = language; + return this; + } + + public ForecastRequester setUnit(String unit) { + this.unit = unit; + return this; + } + + public ForecastRequester setAccuracy(String accuracy) { + this.accuracy = accuracy; + return this; + } + + public ForecastResponse getByCityId(String id) throws InvalidAuthTokenException, DataNotFoundException { + return executeRequest("?id=" + id); + } + + public ForecastResponse getByCityName(String name) throws InvalidAuthTokenException, DataNotFoundException { + return executeRequest("?q=" + name); + } + + public ForecastResponse getByCoordinates(double latitude, double longitude) throws InvalidAuthTokenException, DataNotFoundException { + return executeRequest("?lat=" + latitude + "&lon=" + longitude); + } + + public ForecastResponse getByCoordinates(Coordinates coordinates) throws InvalidAuthTokenException, DataNotFoundException { + return getByCoordinates(coordinates.getLatitude(), coordinates.getLongitude()); + } + + public ForecastResponse getByZIPCode(String zipCode, String countryCode) throws InvalidAuthTokenException, DataNotFoundException { + return executeRequest("?zip=" + zipCode + "," + countryCode); + } + + @Override + protected Map getAdditionalParameters() { + Map additionalParameters = null; + if (amountOfDays != -1) { + additionalParameters = new HashMap<>(); + additionalParameters.put("cnt", String.valueOf(amountOfDays)); + } + + return additionalParameters; + } + + protected String getRequestType() { + if (amountOfDays != -1) { + return "forecast/daily"; + } + return "forecast"; + } + + private ForecastResponse executeRequest(String requestSpecificParameters) throws InvalidAuthTokenException, DataNotFoundException { + + try { + InputStream requestResult = RequestUtils.executeGetRequest(buildURL(requestSpecificParameters)); + return (ForecastResponse)JsonUtils.parseJson(requestResult, ForecastResponse.class); + } catch (IOException ex) { + ex.printStackTrace(); + } + + return null; + } + +} diff --git a/src/main/java/by/prominence/openweather/api/OpenWeatherProviderManager.java b/src/main/java/by/prominence/openweather/api/OpenWeatherMapManager.java similarity index 69% rename from src/main/java/by/prominence/openweather/api/OpenWeatherProviderManager.java rename to src/main/java/by/prominence/openweather/api/OpenWeatherMapManager.java index 0219045..b78dcdc 100644 --- a/src/main/java/by/prominence/openweather/api/OpenWeatherProviderManager.java +++ b/src/main/java/by/prominence/openweather/api/OpenWeatherMapManager.java @@ -22,27 +22,19 @@ package by.prominence.openweather.api; -import by.prominence.openweather.api.provider.ForecastProvider; -import by.prominence.openweather.api.provider.WeatherProvider; - -public class OpenWeatherProviderManager { +public class OpenWeatherMapManager { private String authToken; - public OpenWeatherProviderManager(String token) { + public OpenWeatherMapManager(String token) { this.authToken = token; } - public WeatherProvider getWeather() { - return new WeatherProvider(authToken); + public WeatherRequester getWeatherRequester() { + return new WeatherRequester(authToken); } - public ForecastProvider getForecast() { - return new ForecastProvider(authToken); + public ForecastRequester getForecastRequester() { + return new ForecastRequester(authToken); } - - public ForecastProvider getForecast(int amountOfDays) { - return new ForecastProvider(authToken, amountOfDays); - } - } diff --git a/src/main/java/by/prominence/openweather/api/WeatherRequester.java b/src/main/java/by/prominence/openweather/api/WeatherRequester.java new file mode 100644 index 0000000..ee9e903 --- /dev/null +++ b/src/main/java/by/prominence/openweather/api/WeatherRequester.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018 Alexey Zinchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package by.prominence.openweather.api; + +import by.prominence.openweather.api.exception.DataNotFoundException; +import by.prominence.openweather.api.exception.InvalidAuthTokenException; +import by.prominence.openweather.api.model.Coordinates; +import by.prominence.openweather.api.model.weather.WeatherResponse; +import by.prominence.openweather.api.utils.JsonUtils; +import by.prominence.openweather.api.utils.RequestUtils; + +import java.io.IOException; +import java.io.InputStream; + +public class WeatherRequester extends BasicRequester { + + WeatherRequester(String authToken) { + super(authToken); + } + + public WeatherRequester setLanguage(String language) { + this.language = language; + return this; + } + + public WeatherRequester setUnit(String unit) { + this.unit = unit; + return this; + } + + public WeatherRequester setAccuracy(String accuracy) { + this.accuracy = accuracy; + return this; + } + + public WeatherResponse getByCityId(String id) throws InvalidAuthTokenException, DataNotFoundException { + return executeRequest("?id=" + id); + } + + public WeatherResponse getByCityName(String name) throws InvalidAuthTokenException, DataNotFoundException { + return executeRequest("?q=" + name); + } + + public WeatherResponse getByCoordinates(double latitude, double longitude) throws InvalidAuthTokenException, DataNotFoundException { + return executeRequest("?lat=" + latitude + "&lon=" + longitude); + } + + public WeatherResponse getByCoordinates(Coordinates coordinates) throws InvalidAuthTokenException, DataNotFoundException { + return getByCoordinates(coordinates.getLatitude(), coordinates.getLongitude()); + } + + public WeatherResponse getByZIPCode(String zipCode, String countryCode) throws InvalidAuthTokenException, DataNotFoundException { + return executeRequest("?zip=" + zipCode + "," + countryCode); + } + + protected String getRequestType() { + return "weather"; + } + + private WeatherResponse executeRequest(String requestSpecificParameters) throws InvalidAuthTokenException, DataNotFoundException { + + try { + InputStream requestResult = RequestUtils.executeGetRequest(buildURL(requestSpecificParameters)); + return (WeatherResponse)JsonUtils.parseJson(requestResult, WeatherResponse.class); + } catch (IOException ex) { + ex.printStackTrace(); + } + + return null; + } + +} diff --git a/src/main/java/by/prominence/openweather/api/provider/AbstractOpenWeatherProvider.java b/src/main/java/by/prominence/openweather/api/provider/AbstractOpenWeatherProvider.java deleted file mode 100644 index 01bd261..0000000 --- a/src/main/java/by/prominence/openweather/api/provider/AbstractOpenWeatherProvider.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2018 Alexey Zinchenko - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package by.prominence.openweather.api.provider; - -import by.prominence.openweather.api.constants.System; -import by.prominence.openweather.api.exception.DataNotFoundException; -import by.prominence.openweather.api.exception.InvalidAuthTokenException; -import by.prominence.openweather.api.model.Coordinates; -import by.prominence.openweather.api.model.OpenWeatherResponse; -import by.prominence.openweather.api.utils.JsonUtils; - -import java.io.IOException; -import java.lang.reflect.ParameterizedType; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Map; - -public abstract class AbstractOpenWeatherProvider implements OpenWeatherProvider { - - protected final String authToken; - - protected String language; - protected String unit; - protected String accuracy; - private Class type; - - public AbstractOpenWeatherProvider(String authToken) { - this.authToken = authToken; - type = (Class)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]; - } - - public OpenWeatherProvider setLanguage(String language) { - this.language = language; - return this; - } - - public OpenWeatherProvider setUnit(String unit) { - this.unit = unit; - return this; - } - - public OpenWeatherProvider setAccuracy(String accuracy) { - this.accuracy = accuracy; - return this; - } - - public T getByCityId(String id) throws InvalidAuthTokenException, DataNotFoundException { - return executeRequest("?id=" + id); - } - - public T getByCityName(String name) throws InvalidAuthTokenException, DataNotFoundException { - return executeRequest("?q=" + name); - } - - public T getByCoordinates(double latitude, double longitude) throws InvalidAuthTokenException, DataNotFoundException { - return executeRequest("?lat=" + latitude + "&lon=" + longitude); - } - - public T getByCoordinates(Coordinates coordinates) throws InvalidAuthTokenException, DataNotFoundException { - return getByCoordinates(coordinates.getLatitude(), coordinates.getLongitude()); - } - - public T getByZIPCode(String zipCode, String countryCode) throws InvalidAuthTokenException, DataNotFoundException { - return executeRequest("?zip=" + zipCode + "," + countryCode); - } - - protected T executeRequest(String requestSpecificParameters) throws InvalidAuthTokenException, DataNotFoundException { - - T openWeatherResponse = null; - - try { - URL requestUrl = buildURL(requestSpecificParameters); - - HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection(); - connection.setRequestMethod("GET"); - - switch (connection.getResponseCode()) { - case HttpURLConnection.HTTP_OK: - openWeatherResponse = type.cast(JsonUtils.parseJson(connection.getInputStream(), type)); - break; - case HttpURLConnection.HTTP_UNAUTHORIZED: - throw new InvalidAuthTokenException(); - case HttpURLConnection.HTTP_NOT_FOUND: - throw new DataNotFoundException(); - } - } catch (IOException | ClassCastException ex) { - ex.printStackTrace(); - } - - return openWeatherResponse; - } - - protected String getRequestUrl() { - return System.OPEN_WEATHER_API_URL + getRequestType(); - } - - protected Map getAdditionalParameters() { - return null; - } - - private URL buildURL(String requestSpecificParameters) throws MalformedURLException { - - StringBuilder urlBuilder = new StringBuilder(getRequestUrl() + requestSpecificParameters + "&appid=" + authToken); - - if (language != null) { - urlBuilder.append("&lang="); - urlBuilder.append(language); - } - - if (unit != null) { - urlBuilder.append("&units="); - urlBuilder.append(unit); - } - - if (accuracy != null) { - urlBuilder.append("&type="); - urlBuilder.append(accuracy); - } - - Map additionalParameters = getAdditionalParameters(); - if (additionalParameters != null) { - additionalParameters.forEach((key, value) -> { - urlBuilder.append("&"); - urlBuilder.append(key); - urlBuilder.append("="); - urlBuilder.append(value); - }); - } - - return new URL(urlBuilder.toString()); - } - - protected abstract String getRequestType(); -} diff --git a/src/main/java/by/prominence/openweather/api/provider/ForecastProvider.java b/src/main/java/by/prominence/openweather/api/provider/ForecastProvider.java deleted file mode 100644 index 3073f4a..0000000 --- a/src/main/java/by/prominence/openweather/api/provider/ForecastProvider.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2018 Alexey Zinchenko - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package by.prominence.openweather.api.provider; - -import by.prominence.openweather.api.model.forecast.ForecastResponse; - -import java.util.HashMap; -import java.util.Map; - -public class ForecastProvider extends AbstractOpenWeatherProvider { - - private int amountOfDays = -1; - - public ForecastProvider(String authToken) { - super(authToken); - } - - public ForecastProvider(String authToken, int amountOfDays) { - super(authToken); - this.amountOfDays = amountOfDays; - } - - protected String getRequestType() { - if (amountOfDays != -1) { - return "forecast/daily"; - } - return "forecast"; - } - - @Override - protected Map getAdditionalParameters() { - Map additionalParameters = null; - if (amountOfDays != -1) { - additionalParameters = new HashMap<>(); - additionalParameters.put("cnt", String.valueOf(amountOfDays)); - } - - return additionalParameters; - } -} diff --git a/src/main/java/by/prominence/openweather/api/provider/OpenWeatherProvider.java b/src/main/java/by/prominence/openweather/api/utils/RequestUtils.java similarity index 54% rename from src/main/java/by/prominence/openweather/api/provider/OpenWeatherProvider.java rename to src/main/java/by/prominence/openweather/api/utils/RequestUtils.java index b43a565..8348742 100644 --- a/src/main/java/by/prominence/openweather/api/provider/OpenWeatherProvider.java +++ b/src/main/java/by/prominence/openweather/api/utils/RequestUtils.java @@ -20,23 +20,39 @@ * SOFTWARE. */ -package by.prominence.openweather.api.provider; +package by.prominence.openweather.api.utils; import by.prominence.openweather.api.exception.DataNotFoundException; import by.prominence.openweather.api.exception.InvalidAuthTokenException; -import by.prominence.openweather.api.model.Coordinates; -import by.prominence.openweather.api.model.OpenWeatherResponse; -public interface OpenWeatherProvider { +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; - OpenWeatherResponse getByCityId(String id) throws InvalidAuthTokenException, DataNotFoundException; - OpenWeatherResponse getByCityName(String name) throws InvalidAuthTokenException, DataNotFoundException; - OpenWeatherResponse getByCoordinates(double latitude, double longitude) throws InvalidAuthTokenException, DataNotFoundException; - OpenWeatherResponse getByCoordinates(Coordinates coordinates) throws InvalidAuthTokenException, DataNotFoundException; - OpenWeatherResponse getByZIPCode(String zipCode, String countryCode) throws InvalidAuthTokenException, DataNotFoundException; +public class RequestUtils { - OpenWeatherProvider setLanguage(String language); - OpenWeatherProvider setUnit(String unit); - OpenWeatherProvider setAccuracy(String accuracy); + public static InputStream executeGetRequest(URL requestUrl) throws InvalidAuthTokenException, DataNotFoundException { + InputStream resultStream = null; + + try { + HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection(); + connection.setRequestMethod("GET"); + + switch (connection.getResponseCode()) { + case HttpURLConnection.HTTP_OK: + resultStream = connection.getInputStream(); + break; + case HttpURLConnection.HTTP_UNAUTHORIZED: + throw new InvalidAuthTokenException(); + case HttpURLConnection.HTTP_NOT_FOUND: + throw new DataNotFoundException(); + } + } catch (IOException | ClassCastException ex) { + ex.printStackTrace(); + } + + return resultStream; + } }