diff --git a/.gitignore b/.gitignore index 9beb001..fdf0a01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.iml -.idea/ +.idea .gradle -build/ -target/ \ No newline at end of file +build +target +out \ No newline at end of file diff --git a/build.gradle b/build.gradle index b15edae..f31b2ce 100644 --- a/build.gradle +++ b/build.gradle @@ -114,8 +114,8 @@ jacocoTestReport { dependsOn test // tests are required to run before generating the report reports { csv.required = false - xml.enabled true - xml.destination file("${buildDir}/reports/jacoco/report.xml") + xml.required = true + xml.outputLocation = layout.buildDirectory.file('reports/jacoco/report.xml') html.outputLocation = layout.buildDirectory.dir('jacocoHtml') } } diff --git a/docs/SNAPSHOT.md b/docs/SNAPSHOT.md index 318ed74..5a74194 100644 --- a/docs/SNAPSHOT.md +++ b/docs/SNAPSHOT.md @@ -1,8 +1,11 @@ ### Implemented features: * Current weather data -* 5 day / 3-hour forecast +* Hourly forecast * One Call API +* Daily forecast +* 5 day / 3-hour forecast * Air Pollution +* Geocoding API Other: @@ -159,7 +162,7 @@ You are able to set preferable options(via chain methods) and execute appropriat | `getRain()` | Returns `Rain` instance that contains information about rain volume for the last one hour and/or the last 3 hours. Can be absent in case of no data. | | `getSnow()` | Returns `Snow` instance that contains information about snow volume for the last one hour and/or the last 3 hours. Can be absent in case of no data. | | `getClouds()` | Returns `Clouds` instance that contains information about cloudiness percentage. | -| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset` and `coordinate`. | +| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset` and `coordinates`. | | `toString()` | Returns informative string for the whole available weather information. | `toString()` output example: @@ -218,7 +221,7 @@ You are able to set preferable options(via chain methods) and execute appropriat | Method | Description | |-------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------| -| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset`, `coordinate` and `population`. | +| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset`, `coordinates` and `population`. | | `getWeatherForecasts()` | Returns list of `WeatherForecast` objects with forecast information. | | `toString()` | Returns informative string for the whole available forecast information. | @@ -227,7 +230,7 @@ You are able to set preferable options(via chain methods) and execute appropriat A forecast for Minsk with 15 timestamps. ``` -`com.github.prominence.openweathermap.api.model.forecast.WeatherForecast`'s useful public methods(setters are not listed): +`com.github.prominence.openweathermap.api.model.forecast.free.WeatherForecast`'s useful public methods(setters are not listed): | Method | Description | |-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------| diff --git a/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java b/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java index c29d1eb..ec052c2 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java +++ b/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java @@ -26,11 +26,14 @@ import com.github.prominence.openweathermap.api.annotation.SubscriptionAvailabil import com.github.prominence.openweathermap.api.conf.TimeoutSettings; import com.github.prominence.openweathermap.api.request.RequestSettings; import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequester; +import com.github.prominence.openweathermap.api.request.forecast.daily.DailyForecastRequester; import com.github.prominence.openweathermap.api.request.forecast.free.FiveDayThreeHourStepForecastRequester; +import com.github.prominence.openweathermap.api.request.forecast.hourly.FourDaysHourlyForecastRequester; +import com.github.prominence.openweathermap.api.request.geocoding.GeocodingRequester; import com.github.prominence.openweathermap.api.request.onecall.OneCallWeatherRequester; import com.github.prominence.openweathermap.api.request.weather.CurrentWeatherRequester; -import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.ALL; +import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.*; /** * The main public API client to communicate with OpenWeatherMap services. @@ -74,6 +77,24 @@ public class OpenWeatherMapClient { return new FiveDayThreeHourStepForecastRequester(new RequestSettings(apiKey, timeoutSettings)); } + /** + * Hourly forecast API. + * @return requester for retrieving hourly weather forecast information for 4 days. + */ + @SubscriptionAvailability(plans = { DEVELOPER, PROFESSIONAL, ENTERPRISE }) + public FourDaysHourlyForecastRequester forecastHourly4Days() { + return new FourDaysHourlyForecastRequester(new RequestSettings(apiKey, timeoutSettings)); + } + + /** + * Daily forecast API. + * @return requester for retrieving daily weather forecast information for 16 days. + */ + @SubscriptionAvailability(plans = PAID) + public DailyForecastRequester forecastDaily16Days() { + return new DailyForecastRequester(new RequestSettings(apiKey, timeoutSettings)); + } + /** * One Call API. * To get information about current weather, minute forecast for 1 hour, hourly forecast for 48 hours, daily forecast for 7 days and government weather alerts. @@ -93,4 +114,9 @@ public class OpenWeatherMapClient { public AirPollutionRequester airPollution() { return new AirPollutionRequester(new RequestSettings(apiKey, timeoutSettings)); } + + @SubscriptionAvailability(plans = ALL) + public GeocodingRequester geocoding() { + return new GeocodingRequester(new RequestSettings(apiKey, timeoutSettings)); + } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/AtmosphericPressureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/AtmosphericPressureDeserializer.java new file mode 100644 index 0000000..16b0d93 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/AtmosphericPressureDeserializer.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.AtmosphericPressure; + +import java.io.IOException; + +public class AtmosphericPressureDeserializer extends JsonDeserializer { + @Override + public AtmosphericPressure deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode mainNode = p.getCodec().readTree(p); + + final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(mainNode.get("pressure").asDouble()); + + final JsonNode seaLevelNode = mainNode.get("sea_level"); + final JsonNode groundLevelNode = mainNode.get("grnd_level"); + if (seaLevelNode != null) { + atmosphericPressure.setSeaLevelValue(seaLevelNode.asDouble()); + } + if (groundLevelNode != null) { + atmosphericPressure.setGroundLevelValue(groundLevelNode.asDouble()); + } + + return atmosphericPressure; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/CloudsDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/CloudsDeserializer.java new file mode 100644 index 0000000..a0a1ae9 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/CloudsDeserializer.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.Clouds; + +import java.io.IOException; + +public class CloudsDeserializer extends JsonDeserializer { + @Override + public Clouds deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode cloudsNode = p.getCodec().readTree(p); + + final JsonNode allValueNode = cloudsNode.get("all"); + if (allValueNode != null) { + return Clouds.withValue((byte) allValueNode.asInt()); + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/CoordinatesDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/CoordinatesDeserializer.java new file mode 100644 index 0000000..975412c --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/CoordinatesDeserializer.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.Coordinates; + +import java.io.IOException; + +public class CoordinatesDeserializer extends JsonDeserializer { + @Override + public Coordinates deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JacksonException { + JsonNode rootNode = jp.getCodec().readTree(jp); + if (rootNode.has("lat") && rootNode.has("lon")) { + return Coordinates.of(rootNode.get("lat").asDouble(), rootNode.get("lon").asDouble()); + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/GeocodingRecordDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/GeocodingRecordDeserializer.java new file mode 100644 index 0000000..1dec9bc --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/GeocodingRecordDeserializer.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord; + +import java.io.IOException; +import java.util.Map; + +public class GeocodingRecordDeserializer extends JsonDeserializer { + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public GeocodingRecordDeserializer() { + final SimpleModule module = new SimpleModule(); + module.addDeserializer(Coordinates.class, new CoordinatesDeserializer()); + objectMapper.registerModule(module); + } + + @Override + public GeocodingRecord deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JacksonException { + JsonNode rootNode = jp.getCodec().readTree(jp); + String name = rootNode.get("name").asText(); + String country = rootNode.get("country").asText(); + Map localNames = objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("local_names")), new TypeReference>() {}); + Coordinates coordinates = objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Coordinates.class); + return new GeocodingRecord(name, localNames, coordinates, country); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/HumidityDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/HumidityDeserializer.java new file mode 100644 index 0000000..3311b30 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/HumidityDeserializer.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.Humidity; + +import java.io.IOException; + +public class HumidityDeserializer extends JsonDeserializer { + @Override + public Humidity deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + + return Humidity.withValue((byte) (rootNode.get("humidity").asInt())); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/TemperatureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/TemperatureDeserializer.java new file mode 100644 index 0000000..8808688 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/TemperatureDeserializer.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.Temperature; + +import java.io.IOException; + +public class TemperatureDeserializer extends JsonDeserializer { + @Override + public Temperature deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode mainNode = p.getCodec().readTree(p); + final UnitSystem unitSystem = (UnitSystem) ctxt.findInjectableValue("unitSystem", null, null); + + final double tempValue = mainNode.get("temp").asDouble(); + final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit()); + + final JsonNode feelsLikeNode = mainNode.get("feels_like"); + if (feelsLikeNode != null) { + temperature.setFeelsLike(feelsLikeNode.asDouble()); + } + final JsonNode tempMaxNode = mainNode.get("temp_max"); + if (tempMaxNode != null) { + temperature.setMaxTemperature(tempMaxNode.asDouble()); + } + final JsonNode tempMinNode = mainNode.get("temp_min"); + if (tempMinNode != null) { + temperature.setMinTemperature(tempMinNode.asDouble()); + } + + return temperature; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/WeatherStateDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/WeatherStateDeserializer.java new file mode 100644 index 0000000..6876573 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/WeatherStateDeserializer.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.WeatherState; + +import java.io.IOException; + +public class WeatherStateDeserializer extends JsonDeserializer { + @Override + public WeatherState deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + JsonNode weatherNode = p.getCodec().readTree(p); + final WeatherState weatherState = new WeatherState( + weatherNode.get("id").asInt(), + weatherNode.get("main").asText(), + weatherNode.get("description").asText() + ); + weatherState.setIconId(weatherNode.get("icon").asText()); + return weatherState; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/WindDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/WindDeserializer.java new file mode 100644 index 0000000..8d8d92b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/WindDeserializer.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.Wind; + +import java.io.IOException; + +public class WindDeserializer extends JsonDeserializer { + @Override + public Wind deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode windNode = p.getCodec().readTree(p); + final UnitSystem unitSystem = (UnitSystem) ctxt.findInjectableValue("unitSystem", null, null); + + JsonNode speedNode = windNode.get("speed"); + if (speedNode == null) { + speedNode = windNode.get("wind_speed"); + } + double speed = speedNode.asDouble(); + + final Wind wind = Wind.withValue(speed, unitSystem.getWindUnit()); + JsonNode degNode = windNode.get("deg"); + if (degNode == null) { + degNode = windNode.get("wind_deg"); + } + if (degNode != null) { + wind.setDegrees(degNode.asDouble()); + } + + JsonNode gustNode = windNode.get("gust"); + if (gustNode == null) { + gustNode = windNode.get("wind_gust"); + } + if (gustNode != null) { + wind.setGust(gustNode.asDouble()); + } + + return wind; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/ZipCodeGeocodingDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/ZipCodeGeocodingDeserializer.java new file mode 100644 index 0000000..d1bdff9 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/ZipCodeGeocodingDeserializer.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingRecord; + +import java.io.IOException; + +public class ZipCodeGeocodingDeserializer extends JsonDeserializer { + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public ZipCodeGeocodingDeserializer() { + final SimpleModule module = new SimpleModule(); + module.addDeserializer(Coordinates.class, new CoordinatesDeserializer()); + objectMapper.registerModule(module); + } + + @Override + public ZipCodeGeocodingRecord deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + JsonNode rootNode = p.getCodec().readTree(p); + String zip = rootNode.get("zip").asText(); + String name = rootNode.get("name").asText(); + String country = rootNode.get("country").asText(); + + Coordinates coordinates = objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Coordinates.class); + + return new ZipCodeGeocodingRecord(zip, name, coordinates, country); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastLocationDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastLocationDeserializer.java new file mode 100644 index 0000000..1b28d10 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastLocationDeserializer.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.forecast.hourly; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.deserializer.CoordinatesDeserializer; +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.forecast.hourly.Location; + +import java.io.IOException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.TimeZone; + +public class HourlyForecastLocationDeserializer extends JsonDeserializer { + private final ObjectMapper objectMapper = new ObjectMapper(); + + public HourlyForecastLocationDeserializer() { + final SimpleModule module = new SimpleModule(); + module.addDeserializer(Coordinates.class, new CoordinatesDeserializer()); + objectMapper.registerModule(module); + } + + @Override + public Location deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + final Location location = Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText()); + + final JsonNode timezoneNode = rootNode.get("timezone"); + if (timezoneNode != null) { + location.setZoneOffset(ZoneOffset.ofTotalSeconds(timezoneNode.asInt())); + } + + final JsonNode countryNode = rootNode.get("country"); + if (countryNode != null) { + location.setCountryCode(countryNode.asText()); + } + + final JsonNode sunriseNode = rootNode.get("sunrise"); + final JsonNode sunsetNode = rootNode.get("sunset"); + if (sunriseNode != null) { + location.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunriseNode.asLong()), TimeZone.getDefault().toZoneId())); + } + if (sunsetNode != null) { + location.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunsetNode.asLong()), TimeZone.getDefault().toZoneId())); + } + + final JsonNode coordNode = rootNode.get("coord"); + if (coordNode != null) { + location.setCoordinate(objectMapper.readValue(objectMapper.treeAsTokens(coordNode), Coordinates.class)); + } + + return location; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastRainDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastRainDeserializer.java new file mode 100644 index 0000000..8562323 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastRainDeserializer.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.forecast.hourly; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.forecast.hourly.Rain; + +import java.io.IOException; + +public class HourlyForecastRainDeserializer extends JsonDeserializer { + @Override + public Rain deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rainNode = p.getCodec().readTree(p); + final JsonNode oneHourNode = rainNode.get("1h"); + if (oneHourNode != null) { + return Rain.withOneHourLevelValue(oneHourNode.asDouble()); + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastSnowDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastSnowDeserializer.java new file mode 100644 index 0000000..cf63048 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastSnowDeserializer.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.forecast.hourly; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.forecast.hourly.Snow; + +import java.io.IOException; + +public class HourlyForecastSnowDeserializer extends JsonDeserializer { + @Override + public Snow deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode snowNode = p.getCodec().readTree(p); + final JsonNode oneHourNode = snowNode.get("1h"); + if (oneHourNode != null) { + return Snow.withOneHourLevelValue(oneHourNode.asDouble()); + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/AlertDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/AlertDeserializer.java new file mode 100644 index 0000000..bd1c468 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/AlertDeserializer.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.onecall; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.onecall.current.Alert; +import com.github.prominence.openweathermap.api.utils.JsonDeserializationUtils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class AlertDeserializer extends JsonDeserializer { + @Override + public Alert deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode alertNode = p.getCodec().readTree(p); + + Alert alert = new Alert(); + alert.setSenderName(alertNode.get("sender_name").asText()); + alert.setEventName(alertNode.get("event").asText()); + alert.setStartTime(JsonDeserializationUtils.parseDateTime(alertNode.get("start"))); + alert.setEndTime(JsonDeserializationUtils.parseDateTime(alertNode.get("end"))); + alert.setDescription(alertNode.get("description").asText()); + + final JsonNode tagsNode = alertNode.get("tags"); + if (tagsNode != null) { + List tags = new ArrayList<>(); + for (JsonNode tagNode : tagsNode) { + tags.add(tagNode.asText()); + } + alert.setTags(tags); + } + + return alert; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallAtmosphericPressureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallAtmosphericPressureDeserializer.java new file mode 100644 index 0000000..b7361b2 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallAtmosphericPressureDeserializer.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.onecall; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.onecall.AtmosphericPressure; + +import java.io.IOException; + +public class OneCallAtmosphericPressureDeserializer extends JsonDeserializer { + @Override + public AtmosphericPressure deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + return AtmosphericPressure.withValue(rootNode.get("pressure").asDouble()); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyRainDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyRainDeserializer.java new file mode 100644 index 0000000..e33701e --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyRainDeserializer.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.onecall; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.onecall.current.DailyRain; + +import java.io.IOException; + +public class OneCallDailyRainDeserializer extends JsonDeserializer { + @Override + public DailyRain deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + final JsonNode valueNode = rootNode.get("rain"); + if (valueNode != null) { + return DailyRain.withValue(valueNode.asDouble()); + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailySnowDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailySnowDeserializer.java new file mode 100644 index 0000000..01e81fb --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailySnowDeserializer.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.onecall; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.onecall.current.DailySnow; + +import java.io.IOException; + +public class OneCallDailySnowDeserializer extends JsonDeserializer { + @Override + public DailySnow deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + + final JsonNode valueNode = rootNode.get("snow"); + if (valueNode != null) { + return DailySnow.withValue(valueNode.asDouble()); + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyTemperatureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyTemperatureDeserializer.java new file mode 100644 index 0000000..244143b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyTemperatureDeserializer.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.onecall; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.onecall.current.DailyTemperature; + +import java.io.IOException; + +public class OneCallDailyTemperatureDeserializer extends JsonDeserializer { + @Override + public DailyTemperature deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + + final DailyTemperature temperature = new DailyTemperature(); + final JsonNode tempNode = rootNode.get("temp"); + temperature.setMorning(tempNode.get("morn").asDouble()); + temperature.setDay(tempNode.get("day").asDouble()); + temperature.setEve(tempNode.get("eve").asDouble()); + temperature.setNight(tempNode.get("night").asDouble()); + temperature.setMin(tempNode.get("min").asDouble()); + temperature.setMax(tempNode.get("max").asDouble()); + + final JsonNode feelsLikeNode = rootNode.get("feels_like"); + temperature.setMorningFeelsLike(feelsLikeNode.get("morn").asDouble()); + temperature.setDayFeelsLike(feelsLikeNode.get("day").asDouble()); + temperature.setEveFeelsLike(feelsLikeNode.get("eve").asDouble()); + temperature.setNightFeelsLike(feelsLikeNode.get("night").asDouble()); + + return temperature; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallRainDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallRainDeserializer.java new file mode 100644 index 0000000..11be57a --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallRainDeserializer.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.onecall; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.onecall.Rain; + +import java.io.IOException; + +public class OneCallRainDeserializer extends JsonDeserializer { + @Override + public Rain deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + final JsonNode rainNode = rootNode.get("rain"); + if (rainNode != null) { + final JsonNode oneHourNode = rainNode.get("1h"); + if (oneHourNode != null) { + return Rain.withOneHourLevelValue(oneHourNode.asDouble()); + } + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallSnowDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallSnowDeserializer.java new file mode 100644 index 0000000..fc72894 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallSnowDeserializer.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.onecall; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.onecall.Rain; +import com.github.prominence.openweathermap.api.model.onecall.Snow; + +import java.io.IOException; + +public class OneCallSnowDeserializer extends JsonDeserializer { + @Override + public Snow deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + final JsonNode snowNode = rootNode.get("snow"); + if (snowNode != null) { + final JsonNode OneHourNode = snowNode.get("1h"); + if (OneHourNode != null) { + Rain.withOneHourLevelValue(OneHourNode.asDouble()); + } + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallTemperatureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallTemperatureDeserializer.java new file mode 100644 index 0000000..d776834 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallTemperatureDeserializer.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.onecall; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.onecall.Temperature; + +import java.io.IOException; + +public class OneCallTemperatureDeserializer extends JsonDeserializer { + @Override + public Temperature deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + final UnitSystem unitSystem = (UnitSystem) ctxt.findInjectableValue("unitSystem", null, null); + + final double tempValue = rootNode.get("temp").asDouble(); + final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit()); + + final JsonNode tempFeelsLike = rootNode.get("feels_like"); + if (tempFeelsLike != null) { + temperature.setFeelsLike(tempFeelsLike.asDouble()); + } + final JsonNode dewPoint = rootNode.get("dew_point"); + if (dewPoint != null) { + temperature.setDewPoint(dewPoint.asDouble()); + } + + return temperature; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherLocationDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherLocationDeserializer.java new file mode 100644 index 0000000..d0ddbde --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherLocationDeserializer.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.weather; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.deserializer.CoordinatesDeserializer; +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.weather.Location; + +import java.io.IOException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.TimeZone; + +public class WeatherLocationDeserializer extends JsonDeserializer { + private final ObjectMapper objectMapper = new ObjectMapper(); + + public WeatherLocationDeserializer() { + final SimpleModule module = new SimpleModule(); + module.addDeserializer(Coordinates.class, new CoordinatesDeserializer()); + objectMapper.registerModule(module); + } + + @Override + public Location deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rootNode = p.getCodec().readTree(p); + final Location location = Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText()); + + final JsonNode timezoneNode = rootNode.get("timezone"); + if (timezoneNode != null) { + location.setZoneOffset(ZoneOffset.ofTotalSeconds(timezoneNode.asInt())); + } + + final JsonNode sysNode = rootNode.get("sys"); + if (sysNode != null) { + final JsonNode countryNode = sysNode.get("country"); + if (countryNode != null) { + location.setCountryCode(countryNode.asText()); + } + + final JsonNode sunriseNode = sysNode.get("sunrise"); + final JsonNode sunsetNode = sysNode.get("sunset"); + if (sunriseNode != null) { + location.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunriseNode.asInt()), TimeZone.getDefault().toZoneId())); + } + if (sunsetNode != null) { + location.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunsetNode.asInt()), TimeZone.getDefault().toZoneId())); + } + } + + final JsonNode coordNode = rootNode.get("coord"); + if (coordNode != null) { + location.setCoordinate(objectMapper.readValue(objectMapper.treeAsTokens(coordNode), Coordinates.class)); + } + + return location; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherRainDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherRainDeserializer.java new file mode 100644 index 0000000..4372bcc --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherRainDeserializer.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.weather; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.weather.Rain; + +import java.io.IOException; + +public class WeatherRainDeserializer extends JsonDeserializer { + @Override + public Rain deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode rainNode = p.getCodec().readTree(p); + if (rainNode != null) { + final JsonNode oneHourNode = rainNode.get("1h"); + final JsonNode threeHourNode = rainNode.get("3h"); + if (oneHourNode != null && threeHourNode != null) { + return Rain.withValues(oneHourNode.asDouble(), threeHourNode.asDouble()); + } else if (oneHourNode != null) { + return Rain.withOneHourLevelValue(oneHourNode.asDouble()); + } else if (threeHourNode != null) { + return Rain.withThreeHourLevelValue(threeHourNode.asDouble()); + } + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherSnowDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherSnowDeserializer.java new file mode 100644 index 0000000..ebf9c4d --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherSnowDeserializer.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.deserializer.weather; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.weather.Snow; + +import java.io.IOException; + +public class WeatherSnowDeserializer extends JsonDeserializer { + @Override + public Snow deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + final JsonNode snowNode = p.getCodec().readTree(p); + if (snowNode != null) { + final JsonNode oneHourNode = snowNode.get("1h"); + final JsonNode threeHourNode = snowNode.get("3h"); + if (oneHourNode != null && threeHourNode != null) { + return Snow.withValues(oneHourNode.asDouble(), threeHourNode.asDouble()); + } else if (oneHourNode != null) { + return Snow.withOneHourLevelValue(oneHourNode.asDouble()); + } else if (threeHourNode != null) { + return Snow.withThreeHourLevelValue(threeHourNode.asDouble()); + } + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/SubscriptionPlan.java b/src/main/java/com/github/prominence/openweathermap/api/enums/SubscriptionPlan.java index b2419c7..0de8a7f 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/SubscriptionPlan.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/SubscriptionPlan.java @@ -32,6 +32,11 @@ public enum SubscriptionPlan { */ FREE, + /** + * An alias that represents any of paid plans: startup, developer, professional or enterprise. + */ + PAID, + /** * Startup subscription plan. */ diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/AbstractMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/AbstractMapper.java new file mode 100644 index 0000000..0fbbf8b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/mapper/AbstractMapper.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.mapper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.utils.JsonDeserializationUtils; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractMapper { + protected final ObjectMapper objectMapper = new ObjectMapper(); + + protected LocalDateTime parseDateTime(JsonNode dateTimeNode) { + return JsonDeserializationUtils.parseDateTime(dateTimeNode); + } + + protected ZoneId parseZoneId(JsonNode zoneIdNode) { + return JsonDeserializationUtils.parseZoneId(zoneIdNode); + } + + protected ZoneOffset parseZoneOffset(JsonNode zoneOffsetNode) { + return JsonDeserializationUtils.parseZoneOffset(zoneOffsetNode); + } + + protected List parseWeatherStates(JsonNode weatherArrayNode) throws IOException { + List weatherStateList = new ArrayList<>(); + if (weatherArrayNode != null && weatherArrayNode.isArray()) { + for (JsonNode weatherNode : weatherArrayNode) { + weatherStateList.add(objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class)); + } + } + return weatherStateList; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/AirPollutionResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/AirPollutionResponseMapper.java index b6a069e..94d5fd3 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/AirPollutionResponseMapper.java +++ b/src/main/java/com/github/prominence/openweathermap/api/mapper/AirPollutionResponseMapper.java @@ -26,7 +26,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.prominence.openweathermap.api.enums.AirQualityIndex; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails; import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionRecord; @@ -37,7 +37,7 @@ import java.util.List; import java.util.TimeZone; /** - * The type Air pollution response mapper. + * Official API response documentation: https://openweathermap.org/api/air-pollution#fields. */ public class AirPollutionResponseMapper { /** @@ -91,11 +91,11 @@ public class AirPollutionResponseMapper { return airPollutionRecord; } - private Coordinate parseCoordinate(JsonNode rootNode) { + private Coordinates parseCoordinate(JsonNode rootNode) { final JsonNode latitudeNode = rootNode.get("lat"); final JsonNode longitudeNode = rootNode.get("lon"); if (latitudeNode != null && longitudeNode != null) { - return Coordinate.of(latitudeNode.asDouble(), longitudeNode.asDouble()); + return Coordinates.of(latitudeNode.asDouble(), longitudeNode.asDouble()); } return null; } diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapper.java index 4e4174e..bbbc1b7 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapper.java +++ b/src/main/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapper.java @@ -22,76 +22,46 @@ package com.github.prominence.openweathermap.api.mapper; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.deserializer.*; +import com.github.prominence.openweathermap.api.deserializer.weather.WeatherLocationDeserializer; +import com.github.prominence.openweathermap.api.deserializer.weather.WeatherRainDeserializer; +import com.github.prominence.openweathermap.api.deserializer.weather.WeatherSnowDeserializer; import com.github.prominence.openweathermap.api.model.weather.*; import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.model.*; +import java.io.IOException; import java.time.Instant; import java.time.LocalDateTime; -import java.time.ZoneOffset; import java.util.ArrayList; import java.util.List; import java.util.TimeZone; /** - * Official API response documentation: - * Parameters: - * --- coord - * |- coord.lon City geo location, longitude - * |- coord.lat City geo location, latitude - * --- weather (more info Weather condition codes) - * |- weather.id Weather condition id - * |- weather.main Group of weather parameters (Rain, Snow, Extreme etc.) - * |- weather.description Weather condition within the group - * |- weather.icon Weather icon id - * --- base Internal parameter - * --- main - * |- main.temp Temperature. UnitSystem Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit. - * |- main.feels_like Temperature. This temperature parameter accounts for the human perception of weather. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit. - * |- main.pressure Atmospheric pressure (on the sea level, if there is no sea_level or grnd_level data), hPa - * |- main.humidity Humidity, % - * |- main.temp_min Minimum temperature at the moment. This is deviation from current temp that is possible for large cities and megalopolises geographically expanded (use these parameter optionally). UnitSystem Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit. - * |- main.temp_max Maximum temperature at the moment. This is deviation from current temp that is possible for large cities and megalopolises geographically expanded (use these parameter optionally). UnitSystem Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit. - * |- main.sea_level Atmospheric pressure on the sea level, hPa - * |- main.grnd_level Atmospheric pressure on the ground level, hPa - * --- wind - * |- wind.speed Wind speed. UnitSystem Default: meter/sec, Metric: meter/sec, Imperial: miles/hour. - * |- wind.deg Wind direction, degrees (meteorological) - * |- wind.gust Wind gust. Unit Default: meter/sec, Metric: meter/sec, Imperial: miles/hour - * --- clouds - * |- clouds.all Cloudiness, % - * --- rain - * |- rain.1h Rain volume for the last 1 hour, mm - * |- rain.3h Rain volume for the last 3 hours, mm - * --- snow - * |- snow.1h Snow volume for the last 1 hour, mm - * |- snow.3h Snow volume for the last 3 hours, mm - * --- dt Time of data calculation, unix, UTC - * --- sys - * |- sys.type Internal parameter - * |- sys.id Internal parameter - * |- sys.message Internal parameter - * |- sys.country Country code (GB, JP etc.) - * |- sys.sunrise Sunrise time, unix, UTC - * |- sys.sunset Sunset time, unix, UTC - * --- timezone Shift in seconds from UTC - * --- id City ID - * --- name City name - * --- cod Internal parameter + * Official API response documentation: https://openweathermap.org/current#current_JSON. + * Ignored internal parameters: "root.cod", "sys.type", "sys.id", "sys.message". */ -public class CurrentWeatherResponseMapper { - private final UnitSystem unitSystem; - +public class CurrentWeatherResponseMapper extends AbstractMapper { /** * Instantiates a new Current weather response mapper. * * @param unitSystem the unit system */ public CurrentWeatherResponseMapper(UnitSystem unitSystem) { - this.unitSystem = unitSystem != null ? unitSystem : UnitSystem.STANDARD; + objectMapper.setInjectableValues(new InjectableValues.Std().addValue("unitSystem", unitSystem != null ? unitSystem : UnitSystem.STANDARD)); + final SimpleModule module = new SimpleModule(); + module.addDeserializer(WeatherState.class, new WeatherStateDeserializer()); + module.addDeserializer(Temperature.class, new TemperatureDeserializer()); + module.addDeserializer(AtmosphericPressure.class, new AtmosphericPressureDeserializer()); + module.addDeserializer(Humidity.class, new HumidityDeserializer()); + module.addDeserializer(Wind.class, new WindDeserializer()); + module.addDeserializer(Rain.class, new WeatherRainDeserializer()); + module.addDeserializer(Snow.class, new WeatherSnowDeserializer()); + module.addDeserializer(Clouds.class, new CloudsDeserializer()); + module.addDeserializer(Location.class, new WeatherLocationDeserializer()); + objectMapper.registerModule(module); } /** @@ -100,218 +70,50 @@ public class CurrentWeatherResponseMapper { * @param json the json string * @return the weather object */ - public Weather getSingle(String json) { - final ObjectMapper objectMapper = new ObjectMapper(); + public Weather mapToWeather(String json) { Weather weather; try { final JsonNode root = objectMapper.readTree(json); - weather = getSingle(root); - } catch (JsonProcessingException e) { - throw new RuntimeException("Cannot parse Weather response"); + weather = mapToWeather(root); + } catch (IOException e) { + throw new RuntimeException("Cannot parse Weather response", e); } return weather; } - private Weather getSingle(JsonNode rootNode) { + private Weather mapToWeather(JsonNode rootNode) throws IOException { final JsonNode weatherArrayNode = rootNode.get("weather"); - final JsonNode weatherNode = weatherArrayNode != null ? weatherArrayNode.get(0) : null; final Weather weather = new Weather(); - weather.setWeatherState(parseWeatherState(weatherNode)); - weather.setTemperature(parseTemperature(rootNode)); - weather.setAtmosphericPressure(parsePressure(rootNode)); - weather.setHumidity(parseHumidity(rootNode)); - weather.setWind(parseWind(rootNode)); - weather.setRain(parseRain(rootNode)); - weather.setSnow(parseSnow(rootNode)); - weather.setClouds(parseClouds(rootNode)); - weather.setLocation(parseLocation(rootNode)); + final List weatherStateList = new ArrayList<>(); + if (weatherArrayNode != null && weatherArrayNode.isArray()) { + for (JsonNode weatherNode : weatherArrayNode) { + weatherStateList.add(objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class)); + } + weather.setWeatherStates(weatherStateList); + } + + weather.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("main")), Temperature.class)); + weather.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("main")), AtmosphericPressure.class)); + weather.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("main")), Humidity.class)); + weather.setWind(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("wind")), Wind.class)); + if (rootNode.has("rain")) { + weather.setRain(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("rain")), Rain.class)); + } + if (rootNode.has("snow")) { + weather.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("snow")), Snow.class)); + } + weather.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("clouds")), Clouds.class)); + weather.setLocation(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Location.class)); final JsonNode dtNode = rootNode.get("dt"); if (dtNode != null) { - weather.setCalculationTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(dtNode.asInt()), TimeZone.getDefault().toZoneId())); + weather.setCalculationTime(parseDateTime(dtNode)); } + weather.setBase(rootNode.get("base").asText()); + return weather; } - - /** - * Gets list of results. - * - * @param json the json string - * @return the list of weathers - */ - public List getList(String json) { - final ObjectMapper objectMapper = new ObjectMapper(); - final List weatherList = new ArrayList<>(); - try { - final JsonNode root = objectMapper.readTree(json); - final JsonNode listNode = root.get("list"); - listNode.forEach(jsonNode -> weatherList.add(getSingle(jsonNode))); - } catch (JsonProcessingException e) { - throw new RuntimeException("Cannot parse Weather response"); - } - - return weatherList; - } - - private WeatherState parseWeatherState(JsonNode weatherNode) { - if (weatherNode == null) { - return null; - } - final WeatherState weatherState = new WeatherState( - weatherNode.get("id").asInt(), - weatherNode.get("main").asText(), - weatherNode.get("description").asText() - ); - weatherState.setIconId(weatherNode.get("icon").asText()); - - return weatherState; - } - - private Temperature parseTemperature(JsonNode rootNode) { - final JsonNode mainNode = rootNode.get("main"); - final double tempValue = mainNode.get("temp").asDouble(); - final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit()); - - final JsonNode feelsLikeNode = mainNode.get("feels_like"); - if (feelsLikeNode != null) { - temperature.setFeelsLike(feelsLikeNode.asDouble()); - } - final JsonNode tempMaxNode = mainNode.get("temp_max"); - if (tempMaxNode != null) { - temperature.setMaxTemperature(tempMaxNode.asDouble()); - } - final JsonNode tempMinNode = mainNode.get("temp_min"); - if (tempMinNode != null) { - temperature.setMinTemperature(tempMinNode.asDouble()); - } - - return temperature; - } - - private AtmosphericPressure parsePressure(JsonNode rootNode) { - final JsonNode mainNode = rootNode.get("main"); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(mainNode.get("pressure").asDouble()); - - final JsonNode seaLevelNode = mainNode.get("sea_level"); - final JsonNode groundLevelNode = mainNode.get("grnd_level"); - if (seaLevelNode != null) { - atmosphericPressure.setSeaLevelValue(seaLevelNode.asDouble()); - } - if (groundLevelNode != null) { - atmosphericPressure.setGroundLevelValue(groundLevelNode.asDouble()); - } - - return atmosphericPressure; - } - - private Humidity parseHumidity(JsonNode rootNode) { - final JsonNode mainNode = rootNode.get("main"); - - return Humidity.withValue((byte) (mainNode.get("humidity").asInt())); - } - - private Wind parseWind(JsonNode rootNode) { - final JsonNode windNode = rootNode.get("wind"); - double speed = windNode.get("speed").asDouble(); - - final Wind wind = Wind.withValue(speed, unitSystem.getWindUnit()); - - final JsonNode degNode = windNode.get("deg"); - if (degNode != null) { - wind.setDegrees(degNode.asDouble()); - } - final JsonNode gustNode = windNode.get("gust"); - if (gustNode != null) { - wind.setGust(gustNode.asDouble()); - } - - return wind; - } - - private Rain parseRain(JsonNode rootNode) { - final JsonNode rainNode = rootNode.get("rain"); - if (rainNode != null) { - final JsonNode oneHourNode = rainNode.get("1h"); - final JsonNode threeHourNode = rainNode.get("3h"); - if (oneHourNode != null && threeHourNode != null) { - return Rain.withValues(oneHourNode.asDouble(), threeHourNode.asDouble()); - } else if (oneHourNode != null) { - return Rain.withOneHourLevelValue(oneHourNode.asDouble()); - } else if (threeHourNode != null) { - return Rain.withThreeHourLevelValue(threeHourNode.asDouble()); - } - } - return null; - } - - private Snow parseSnow(JsonNode rootNode) { - final JsonNode snowNode = rootNode.get("snow"); - if (snowNode != null) { - final JsonNode oneHourNode = snowNode.get("1h"); - final JsonNode threeHourNode = snowNode.get("3h"); - if (oneHourNode != null && threeHourNode != null) { - return Snow.withValues(oneHourNode.asDouble(), threeHourNode.asDouble()); - } else if (oneHourNode != null) { - return Snow.withOneHourLevelValue(oneHourNode.asDouble()); - } else if (threeHourNode != null) { - return Snow.withThreeHourLevelValue(threeHourNode.asDouble()); - } - } - return null; - } - - private Clouds parseClouds(JsonNode rootNode) { - final JsonNode cloudsNode = rootNode.get("clouds"); - final JsonNode allValueNode = cloudsNode.get("all"); - if (allValueNode != null) { - return Clouds.withValue((byte) allValueNode.asInt()); - } - - return null; - } - - private Location parseLocation(JsonNode rootNode) { - final Location location = Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText()); - - final JsonNode timezoneNode = rootNode.get("timezone"); - if (timezoneNode != null) { - location.setZoneOffset(ZoneOffset.ofTotalSeconds(timezoneNode.asInt())); - } - - final JsonNode sysNode = rootNode.get("sys"); - if (sysNode != null) { - final JsonNode countryNode = sysNode.get("country"); - if (countryNode != null) { - location.setCountryCode(countryNode.asText()); - } - - final JsonNode sunriseNode = sysNode.get("sunrise"); - final JsonNode sunsetNode = sysNode.get("sunset"); - if (sunriseNode != null) { - location.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunriseNode.asInt()), TimeZone.getDefault().toZoneId())); - } - if (sunsetNode != null) { - location.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunsetNode.asInt()), TimeZone.getDefault().toZoneId())); - } - } - - final JsonNode coordNode = rootNode.get("coord"); - if (coordNode != null) { - location.setCoordinate(parseCoordinate(coordNode)); - } - - return location; - } - - private Coordinate parseCoordinate(JsonNode rootNode) { - final JsonNode latitudeNode = rootNode.get("lat"); - final JsonNode longitudeNode = rootNode.get("lon"); - if (latitudeNode != null && longitudeNode != null) { - return Coordinate.of(latitudeNode.asDouble(), longitudeNode.asDouble()); - } - return null; - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapper.java new file mode 100644 index 0000000..99bb0e9 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapper.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.mapper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.Clouds; +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.Humidity; +import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.Wind; +import com.github.prominence.openweathermap.api.model.forecast.daily.*; + +import java.io.IOException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.List; +import java.util.TimeZone; + +/** + * Official API response documentation: https://openweathermap.org/forecast16#JSON. + */ +public class DailyForecastResponseMapper { + private final ObjectMapper objectMapper = new ObjectMapper(); + private final UnitSystem unitSystem; + + public DailyForecastResponseMapper(UnitSystem unitSystem) { + this.unitSystem = unitSystem; + } + + /** + * Maps forecast response into java object. + * + * @param json the json string + * @return the forecast + */ + public Forecast mapToForecast(String json) { + Forecast forecast; + try { + final JsonNode root = objectMapper.readTree(json); + forecast = mapToForecast(root); + } catch (IOException e) { + throw new RuntimeException("Cannot parse Forecast response"); + } + + return forecast; + } + + private Forecast mapToForecast(JsonNode root) throws IOException { + final Forecast forecast = new Forecast(); + forecast.setLocation(parseLocation(root.get("city"))); + + final List forecasts = new ArrayList<>(root.get("cnt").asInt()); + + final JsonNode forecastListNode = root.get("list"); + for (JsonNode forecastNode : forecastListNode) { + forecasts.add(parseWeatherForecast(forecastNode)); + } + + forecast.setWeatherForecasts(forecasts); + + return forecast; + } + + private WeatherForecast parseWeatherForecast(JsonNode rootNode) throws IOException { + final WeatherForecast weatherForecast = new WeatherForecast(); + final JsonNode weatherArrayNode = rootNode.get("weather"); + if (weatherArrayNode != null) { + final JsonNode weatherNode = weatherArrayNode.get(0); + weatherForecast.setWeatherState(parseWeatherState(weatherNode)); + } + + final JsonNode mainNode = rootNode.get("main"); + weatherForecast.setTemperature(parseTemperature(mainNode)); + weatherForecast.setAtmosphericPressure(parsePressure(mainNode)); + weatherForecast.setHumidity(parseHumidity(mainNode)); + weatherForecast.setClouds(parseClouds(rootNode)); + weatherForecast.setWind(parseWind(rootNode)); + weatherForecast.setRain(parseRain(rootNode)); + weatherForecast.setSnow(parseSnow(rootNode)); + + weatherForecast.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(rootNode.get("dt").asLong()), TimeZone.getDefault().toZoneId())); + + return weatherForecast; + } + + private WeatherState parseWeatherState(JsonNode weatherNode) throws IOException { + if (weatherNode == null) { + return null; + } + return objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class); + } + + private Temperature parseTemperature(JsonNode rootNode) { + final Temperature temperature = new Temperature(); + final JsonNode tempNode = rootNode.get("temp"); + temperature.setMorning(tempNode.get("morn").asDouble()); + temperature.setDay(tempNode.get("day").asDouble()); + temperature.setEve(tempNode.get("eve").asDouble()); + temperature.setNight(tempNode.get("night").asDouble()); + temperature.setMin(tempNode.get("min").asDouble()); + temperature.setMax(tempNode.get("max").asDouble()); + + final JsonNode feelsLikeNode = rootNode.get("feels_like"); + temperature.setMorningFeelsLike(feelsLikeNode.get("morn").asDouble()); + temperature.setDayFeelsLike(feelsLikeNode.get("day").asDouble()); + temperature.setEveFeelsLike(feelsLikeNode.get("eve").asDouble()); + temperature.setNightFeelsLike(feelsLikeNode.get("night").asDouble()); + + return temperature; + } + + private AtmosphericPressure parsePressure(JsonNode rootNode) { + return AtmosphericPressure.withValue(rootNode.get("pressure").asDouble()); + } + + private Humidity parseHumidity(JsonNode rootNode) { + return Humidity.withValue((byte) (rootNode.get("humidity").asInt())); + } + + private Wind parseWind(JsonNode root) throws IOException { + final JsonNode windNode = root.get("wind"); + return objectMapper.readValue(objectMapper.treeAsTokens(windNode), Wind.class); + } + + private Rain parseRain(JsonNode root) { + final JsonNode rainNode = root.get("rain"); + if (rainNode != null) { + final JsonNode threeHourNode = rainNode.get("3h"); + if (threeHourNode != null) { + return Rain.withThreeHourLevelValue(threeHourNode.asDouble()); + } + } + return null; + } + + private Snow parseSnow(JsonNode root) { + final JsonNode snowNode = root.get("snow"); + if (snowNode != null) { + final JsonNode threeHourNode = snowNode.get("3h"); + if (threeHourNode != null) { + return Snow.withThreeHourLevelValue(threeHourNode.asDouble()); + } + } + return null; + } + + private Clouds parseClouds(JsonNode rootNode) { + final JsonNode cloudsNode = rootNode.get("clouds"); + final JsonNode allValueNode = cloudsNode.get("all"); + if (allValueNode != null) { + return Clouds.withValue((byte) allValueNode.asInt()); + } + + return null; + } + + private Location parseLocation(JsonNode rootNode) { + final Location location = Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText()); + + final JsonNode timezoneNode = rootNode.get("timezone"); + if (timezoneNode != null) { + location.setZoneOffset(ZoneOffset.ofTotalSeconds(timezoneNode.asInt())); + } + + final JsonNode countryNode = rootNode.get("country"); + if (countryNode != null) { + location.setCountryCode(countryNode.asText()); + } + + final JsonNode coordNode = rootNode.get("coord"); + if (coordNode != null) { + location.setCoordinate(parseCoordinate(coordNode)); + } + + return location; + } + + private Coordinates parseCoordinate(JsonNode rootNode) { + final JsonNode latitudeNode = rootNode.get("lat"); + final JsonNode longitudeNode = rootNode.get("lon"); + if (latitudeNode != null && longitudeNode != null) { + return Coordinates.of(latitudeNode.asDouble(), longitudeNode.asDouble()); + } + return null; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapper.java index 9517b7a..3a7d693 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapper.java +++ b/src/main/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapper.java @@ -22,17 +22,19 @@ package com.github.prominence.openweathermap.api.mapper; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.InjectableValues; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.deserializer.AtmosphericPressureDeserializer; +import com.github.prominence.openweathermap.api.deserializer.TemperatureDeserializer; +import com.github.prominence.openweathermap.api.deserializer.WeatherStateDeserializer; +import com.github.prominence.openweathermap.api.deserializer.WindDeserializer; import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.model.*; -import com.github.prominence.openweathermap.api.model.forecast.*; -import com.github.prominence.openweathermap.api.model.forecast.Location; -import com.github.prominence.openweathermap.api.model.forecast.Rain; -import com.github.prominence.openweathermap.api.model.forecast.Snow; -import com.github.prominence.openweathermap.api.model.Temperature; +import com.github.prominence.openweathermap.api.model.forecast.free.*; +import java.io.IOException; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; @@ -41,53 +43,10 @@ import java.util.List; import java.util.TimeZone; /** - * Official API response documentation. - * Parameters(but the real response can differ): - * --- cod Internal parameter - * --- message Internal parameter - * --- cnt A number of timestamps returned in the API response - * --- list - * |- list.dt Time of data forecasted, unix, UTC - * |- list.main - * |- list.main.temp Temperature. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit. - * |- list.main.feels_like This temperature parameter accounts for the human perception of weather. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit. - * |- list.main.temp_min Minimum temperature at the moment of calculation. This is minimal forecasted temperature (within large megalopolises and urban areas), use this parameter optionally. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit. - * |- list.main.temp_max Maximum temperature at the moment of calculation. This is maximal forecasted temperature (within large megalopolises and urban areas), use this parameter optionally. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit. - * |- list.main.pressure Atmospheric pressure on the sea level by default, hPa - * |- list.main.sea_level Atmospheric pressure on the sea level, hPa - * |- list.main.grnd_level Atmospheric pressure on the ground level, hPa - * |- list.main.humidity Humidity, % - * |- list.main.temp_kf Internal par - * |- list.weather - * |- list.weather.id Weather condition id - * |- list.weather.main Group of weather parameters (Rain, Snow, Extreme etc.) - * |- list.weather.description Weather condition within the group. You can get the output in your language. - * |- list.weather.icon Weather icon id - * |- list.clouds - * |- list.clouds.all Cloudiness, % - * |- list.wind - * |- list.wind.speed Wind speed. Unit Default: meter/sec, Metric: meter/sec, Imperial: miles/hour. - * |- list.wind.deg Wind direction, degrees (meteorological) - * |- list.visibility Average visibility, metres - * |- list.pop Probability of precipitation - * |- list.rain - * |- list.rain.3h Rain volume for last 3 hours, mm - * |- list.snow - * |- list.snow.3h Snow volume for last 3 hours - * |- list.sys - * |- list.sys.pod Part of the day (n - night, d - day) - * |- list.dt_txt Time of data forecasted, ISO, UTC - * --- city - * |- city.id City ID - * |- city.name City name - * |- city.coord - * |- city.coord.lat City geo location, latitude - * |- city.coord.lon City geo location, longitude - * |- city.country Country code (GB, JP etc.) - * |- city.timezone Shift in seconds from UTC + * Official API response documentation: https://openweathermap.org/forecast5#JSON. */ public class FiveDayThreeHourStepForecastResponseMapper { - private final UnitSystem unitSystem; + private final ObjectMapper objectMapper = new ObjectMapper(); /** * Instantiates a new forecast response mapper. @@ -95,7 +54,14 @@ public class FiveDayThreeHourStepForecastResponseMapper { * @param unitSystem the unit system */ public FiveDayThreeHourStepForecastResponseMapper(UnitSystem unitSystem) { - this.unitSystem = unitSystem; + objectMapper.setInjectableValues(new InjectableValues.Std().addValue("unitSystem", unitSystem != null ? unitSystem : UnitSystem.STANDARD)); + final SimpleModule module = new SimpleModule(); + module.addDeserializer(WeatherState.class, new WeatherStateDeserializer()); + module.addDeserializer(Temperature.class, new TemperatureDeserializer()); + module.addDeserializer(AtmosphericPressure.class, new AtmosphericPressureDeserializer()); + module.addDeserializer(Wind.class, new WindDeserializer()); + objectMapper.registerModule(module); + } /** @@ -105,33 +71,35 @@ public class FiveDayThreeHourStepForecastResponseMapper { * @return the forecast */ public Forecast mapToForecast(String json) { - final ObjectMapper objectMapper = new ObjectMapper(); + Forecast forecast; try { final JsonNode root = objectMapper.readTree(json); forecast = mapToForecast(root); - } catch (JsonProcessingException e) { - throw new RuntimeException("Cannot parse Forecast response"); + } catch (IOException e) { + throw new RuntimeException("Cannot parse Forecast response", e); } return forecast; } - private Forecast mapToForecast(JsonNode root) { + private Forecast mapToForecast(JsonNode root) throws IOException { final Forecast forecast = new Forecast(); forecast.setLocation(parseLocation(root.get("city"))); final List forecasts = new ArrayList<>(root.get("cnt").asInt()); final JsonNode forecastListNode = root.get("list"); - forecastListNode.forEach(forecastNode -> forecasts.add(parseWeatherForecast(forecastNode))); + for (JsonNode forecastNode : forecastListNode) { + forecasts.add(parseWeatherForecast(forecastNode)); + } forecast.setWeatherForecasts(forecasts); return forecast; } - private WeatherForecast parseWeatherForecast(JsonNode rootNode) { + private WeatherForecast parseWeatherForecast(JsonNode rootNode) throws IOException { final WeatherForecast weatherForecast = new WeatherForecast(); final JsonNode weatherArrayNode = rootNode.get("weather"); if (weatherArrayNode != null) { @@ -159,70 +127,28 @@ public class FiveDayThreeHourStepForecastResponseMapper { return weatherForecast; } - private WeatherState parseWeatherState(JsonNode weatherNode) { + private WeatherState parseWeatherState(JsonNode weatherNode) throws IOException { if (weatherNode == null) { return null; } - final WeatherState weatherState = new WeatherState( - weatherNode.get("id").asInt(), - weatherNode.get("main").asText(), - weatherNode.get("description").asText() - ); - weatherState.setIconId(weatherNode.get("icon").asText()); - - return weatherState; + return objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class); } - private Temperature parseTemperature(JsonNode rootNode) { - final double tempValue = rootNode.get("temp").asDouble(); - final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit()); - - final JsonNode tempMaxNode = rootNode.get("temp_max"); - if (tempMaxNode != null) { - temperature.setMaxTemperature(tempMaxNode.asDouble()); - } - final JsonNode tempMinNode = rootNode.get("temp_min"); - if (tempMinNode != null) { - temperature.setMinTemperature(tempMinNode.asDouble()); - } - final JsonNode tempFeelsLike = rootNode.get("feels_like"); - if (tempFeelsLike != null) { - temperature.setFeelsLike(tempFeelsLike.asDouble()); - } - - return temperature; + private Temperature parseTemperature(JsonNode rootNode) throws IOException { + return objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Temperature.class); } - private AtmosphericPressure parsePressure(JsonNode rootNode) { - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(rootNode.get("pressure").asDouble()); - - final JsonNode seaLevelNode = rootNode.get("sea_level"); - final JsonNode groundLevelNode = rootNode.get("grnd_level"); - if (seaLevelNode != null) { - atmosphericPressure.setSeaLevelValue(seaLevelNode.asDouble()); - } - if (groundLevelNode != null) { - atmosphericPressure.setGroundLevelValue(groundLevelNode.asDouble()); - } - - return atmosphericPressure; + private AtmosphericPressure parsePressure(JsonNode rootNode) throws IOException { + return objectMapper.readValue(objectMapper.treeAsTokens(rootNode), AtmosphericPressure.class); } private Humidity parseHumidity(JsonNode rootNode) { return Humidity.withValue((byte) (rootNode.get("humidity").asInt())); } - private Wind parseWind(JsonNode root) { + private Wind parseWind(JsonNode root) throws IOException { final JsonNode windNode = root.get("wind"); - double speed = windNode.get("speed").asDouble(); - - final Wind wind = Wind.withValue(speed, unitSystem.getWindUnit()); - final JsonNode degNode = windNode.get("deg"); - if (degNode != null) { - wind.setDegrees(degNode.asDouble()); - } - - return wind; + return objectMapper.readValue(objectMapper.treeAsTokens(windNode), Wind.class); } private Rain parseRain(JsonNode root) { @@ -292,11 +218,11 @@ public class FiveDayThreeHourStepForecastResponseMapper { return location; } - private Coordinate parseCoordinate(JsonNode rootNode) { + private Coordinates parseCoordinate(JsonNode rootNode) { final JsonNode latitudeNode = rootNode.get("lat"); final JsonNode longitudeNode = rootNode.get("lon"); if (latitudeNode != null && longitudeNode != null) { - return Coordinate.of(latitudeNode.asDouble(), longitudeNode.asDouble()); + return Coordinates.of(latitudeNode.asDouble(), longitudeNode.asDouble()); } return null; } diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapper.java new file mode 100644 index 0000000..6f76190 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapper.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.mapper; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.deserializer.GeocodingRecordDeserializer; +import com.github.prominence.openweathermap.api.deserializer.ZipCodeGeocodingDeserializer; +import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingRecord; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord; + +import java.util.List; + +/** + * Official API response documentation: https://openweathermap.org/api/geocoding-api. + */ +public class GeocodingResponseMapper { + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public GeocodingResponseMapper() { + final SimpleModule module = new SimpleModule(); + module.addDeserializer(GeocodingRecord.class, new GeocodingRecordDeserializer()); + module.addDeserializer(ZipCodeGeocodingRecord.class, new ZipCodeGeocodingDeserializer()); + objectMapper.registerModule(module); + } + + public List mapGeocodingResponse(String json) { + try { + return objectMapper.readValue(json, new TypeReference>() {}); + } catch (JsonProcessingException e) { + throw new RuntimeException("Cannot parse ReverseGeocoding response.", e); + } + } + + public ZipCodeGeocodingRecord mapZipCodeGeocodingResponse(String json) { + try { + return objectMapper.readValue(json, ZipCodeGeocodingRecord.class); + } catch (JsonProcessingException e) { + throw new RuntimeException("Cannot parse GeocodingInfo response.", e); + } + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapper.java new file mode 100644 index 0000000..fa83130 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapper.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.mapper; + +import com.fasterxml.jackson.databind.InjectableValues; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.deserializer.*; +import com.github.prominence.openweathermap.api.deserializer.forecast.hourly.HourlyForecastLocationDeserializer; +import com.github.prominence.openweathermap.api.deserializer.forecast.hourly.HourlyForecastRainDeserializer; +import com.github.prominence.openweathermap.api.deserializer.forecast.hourly.HourlyForecastSnowDeserializer; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.*; +import com.github.prominence.openweathermap.api.model.forecast.hourly.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + + +/** + * Official API response documentation: https://openweathermap.org/api/hourly-forecast#JSON. + */ +public class HourlyForecastResponseMapper extends AbstractMapper { + /** + * Instantiates a new forecast response mapper. + * + * @param unitSystem the unit system + */ + public HourlyForecastResponseMapper(UnitSystem unitSystem) { + objectMapper.setInjectableValues(new InjectableValues.Std().addValue("unitSystem", unitSystem != null ? unitSystem : UnitSystem.STANDARD)); + final SimpleModule module = new SimpleModule(); + module.addDeserializer(WeatherState.class, new WeatherStateDeserializer()); + module.addDeserializer(Temperature.class, new TemperatureDeserializer()); + module.addDeserializer(AtmosphericPressure.class, new AtmosphericPressureDeserializer()); + module.addDeserializer(Wind.class, new WindDeserializer()); + module.addDeserializer(Humidity.class, new HumidityDeserializer()); + module.addDeserializer(Clouds.class, new CloudsDeserializer()); + module.addDeserializer(Rain.class, new HourlyForecastRainDeserializer()); + module.addDeserializer(Snow.class, new HourlyForecastSnowDeserializer()); + module.addDeserializer(Location.class, new HourlyForecastLocationDeserializer()); + objectMapper.registerModule(module); + } + + /** + * Maps forecast response into java object. + * + * @param json the json string + * @return the forecast + */ + public HourlyForecast mapToForecast(String json) { + HourlyForecast hourlyForecast; + try { + final JsonNode root = objectMapper.readTree(json); + hourlyForecast = mapToForecast(root); + } catch (IOException e) { + throw new RuntimeException("Cannot parse Forecast response"); + } + + return hourlyForecast; + } + + private HourlyForecast mapToForecast(JsonNode root) throws IOException { + final HourlyForecast hourlyForecast = new HourlyForecast(); + hourlyForecast.setLocation(objectMapper.readValue(objectMapper.treeAsTokens(root.get("city")), Location.class)); + + final List forecasts = new ArrayList<>(root.get("cnt").asInt()); + + final JsonNode forecastListNode = root.get("list"); + for (JsonNode forecastNode : forecastListNode) { + forecasts.add(parseWeatherForecast(forecastNode)); + } + + hourlyForecast.setWeatherForecasts(forecasts); + + return hourlyForecast; + } + + private WeatherForecast parseWeatherForecast(JsonNode rootNode) throws IOException { + final WeatherForecast weatherForecast = new WeatherForecast(); + + final JsonNode weatherArrayNode = rootNode.get("weather"); + if (weatherArrayNode != null && weatherArrayNode.isArray()) { + List weatherStateList = new ArrayList<>(); + for (JsonNode weatherNode : weatherArrayNode) { + weatherStateList.add(objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class)); + } + + weatherForecast.setWeatherStates(weatherStateList); + } + + final JsonNode mainNode = rootNode.get("main"); + weatherForecast.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(mainNode), Temperature.class)); + weatherForecast.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(mainNode), AtmosphericPressure.class)); + weatherForecast.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(mainNode), Humidity.class)); + weatherForecast.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("clouds")), Clouds.class)); + weatherForecast.setWind(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("wind")), Wind.class)); + if (rootNode.has("rain")) { + weatherForecast.setRain(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("rain")), Rain.class)); + } + if (rootNode.has("snow")) { + weatherForecast.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("snow")), Snow.class)); + } + + final JsonNode sysNode = rootNode.get("sys"); + if (sysNode != null) { + weatherForecast.setDayTime("d".equals(sysNode.get("pod").asText()) ? DayTime.DAY : DayTime.NIGHT); + } + + if (rootNode.has("visibility")) { + weatherForecast.setAverageVisibilityInMetres(rootNode.get("visibility").asInt()); + } + + if (rootNode.has("pop")) { + weatherForecast.setProbabilityOfPrecipitation(rootNode.get("pop").asDouble()); + } + + weatherForecast.setForecastTime(parseDateTime(rootNode.get("dt"))); + weatherForecast.setForecastTimeISO(rootNode.get("dt_txt").asText()); + + return weatherForecast; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapper.java index d3477b4..4af0cb1 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapper.java +++ b/src/main/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapper.java @@ -22,41 +22,55 @@ package com.github.prominence.openweathermap.api.mapper; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.InjectableValues; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.deserializer.*; +import com.github.prominence.openweathermap.api.deserializer.onecall.*; import com.github.prominence.openweathermap.api.enums.UnitSystem; -import com.github.prominence.openweathermap.api.model.Clouds; -import com.github.prominence.openweathermap.api.model.Coordinate; -import com.github.prominence.openweathermap.api.model.Humidity; -import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.*; +import com.github.prominence.openweathermap.api.model.onecall.AtmosphericPressure; +import com.github.prominence.openweathermap.api.model.onecall.Temperature; import com.github.prominence.openweathermap.api.model.onecall.*; import com.github.prominence.openweathermap.api.model.onecall.current.*; import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeather; -import com.github.prominence.openweathermap.api.model.onecall.historical.HourlyHistorical; import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeatherData; +import com.github.prominence.openweathermap.api.model.onecall.historical.HourlyHistorical; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.ZoneOffset; +import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.TimeZone; /** - * Object mapper for OneCall API response. + * Official API response documentation: + * */ -public class OneCallWeatherResponseMapper { - private final UnitSystem unitSystem; - +public class OneCallWeatherResponseMapper extends AbstractMapper { /** * Instantiates a new forecast response mapper. * * @param unitSystem the unit system */ public OneCallWeatherResponseMapper(UnitSystem unitSystem) { - this.unitSystem = unitSystem; + objectMapper.setInjectableValues(new InjectableValues.Std().addValue("unitSystem", unitSystem != null ? unitSystem : UnitSystem.STANDARD)); + final SimpleModule module = new SimpleModule(); + module.addDeserializer(Coordinates.class, new CoordinatesDeserializer()); + module.addDeserializer(AtmosphericPressure.class, new OneCallAtmosphericPressureDeserializer()); + module.addDeserializer(Temperature.class, new OneCallTemperatureDeserializer()); + module.addDeserializer(WeatherState.class, new WeatherStateDeserializer()); + module.addDeserializer(Humidity.class, new HumidityDeserializer()); + module.addDeserializer(Wind.class, new WindDeserializer()); + module.addDeserializer(Clouds.class, new CloudsDeserializer()); + module.addDeserializer(Rain.class, new OneCallRainDeserializer()); + module.addDeserializer(Snow.class, new OneCallSnowDeserializer()); + module.addDeserializer(DailyTemperature.class, new OneCallDailyTemperatureDeserializer()); + module.addDeserializer(DailyRain.class, new OneCallDailyRainDeserializer()); + module.addDeserializer(DailySnow.class, new OneCallDailySnowDeserializer()); + module.addDeserializer(Alert.class, new AlertDeserializer()); + objectMapper.registerModule(module); } /** @@ -66,13 +80,12 @@ public class OneCallWeatherResponseMapper { * @return the current data object */ public CurrentWeatherData mapToCurrent(String json) { - final ObjectMapper objectMapper = new ObjectMapper(); CurrentWeatherData currentData; try { final JsonNode root = objectMapper.readTree(json); currentData = mapToCurrent(root); - } catch (JsonProcessingException e) { - throw new RuntimeException("Cannot parse OneCall response"); + } catch (IOException e) { + throw new RuntimeException("Cannot parse OneCall response", e); } return currentData; @@ -85,23 +98,23 @@ public class OneCallWeatherResponseMapper { * @return the current data object */ public HistoricalWeatherData mapToHistorical(String json) { - final ObjectMapper objectMapper = new ObjectMapper(); HistoricalWeatherData historicalData; try { final JsonNode root = objectMapper.readTree(json); historicalData = mapToHistorical(root); - } catch (JsonProcessingException e) { + } catch (IOException e) { throw new RuntimeException("Cannot parse OneCall response"); } return historicalData; } - private CurrentWeatherData mapToCurrent(JsonNode rootNode) { + private CurrentWeatherData mapToCurrent(JsonNode rootNode) throws IOException { final CurrentWeatherData currentData = new CurrentWeatherData(); - currentData.setCoordinate(Coordinate.of(rootNode.get("lat").asDouble(), rootNode.get("lon").asDouble())); - currentData.setTimezone(ZoneId.of(rootNode.get("timezone").asText())); - currentData.setTimezoneOffset(ZoneOffset.ofTotalSeconds(rootNode.get("timezone_offset").asInt())); + currentData.setCoordinate(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Coordinates.class)); + currentData.setTimezone(parseZoneId(rootNode.get("timezone"))); + currentData.setTimezoneOffset(parseZoneOffset(rootNode.get("timezone_offset"))); + currentData.setCurrent(parseCurrent(rootNode.get("current"))); currentData.setMinutelyList(parseMinutelyList(rootNode.get("minutely"))); currentData.setHourlyList(parseHourlyList(rootNode.get("hourly"))); @@ -111,28 +124,31 @@ public class OneCallWeatherResponseMapper { return currentData; } - private Current parseCurrent(JsonNode currentNode) { + private Current parseCurrent(JsonNode currentNode) throws IOException { if (currentNode == null) { return null; } final Current current = new Current(); - current.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("dt").asInt()), TimeZone.getDefault().toZoneId())); - current.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("sunrise").asInt()), TimeZone.getDefault().toZoneId())); - current.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("sunset").asInt()), TimeZone.getDefault().toZoneId())); + current.setForecastTime(parseDateTime(currentNode.get("dt"))); + current.setSunriseTime(parseDateTime(currentNode.get("sunrise"))); + current.setSunsetTime(parseDateTime(currentNode.get("sunset"))); + + current.setWeatherStates(parseWeatherStates(currentNode.get("weather"))); + + current.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Temperature.class)); + current.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), AtmosphericPressure.class)); + current.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Humidity.class)); + current.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Clouds.class)); - current.setWeatherState(parseWeatherState(currentNode.get("weather").get(0))); - current.setTemperature(parseTemperature(currentNode)); - current.setAtmosphericPressure(parsePressure(currentNode)); - current.setHumidity(parseHumidity(currentNode)); - current.setClouds(parseClouds(currentNode)); current.setUvIndex(currentNode.get("uvi").asDouble()); final JsonNode visibilityNode = currentNode.get("visibility"); if (visibilityNode != null) { current.setVisibilityInMetres(visibilityNode.asDouble()); } - current.setWind(parseWind(currentNode)); - current.setRain(parseRain(currentNode)); - current.setSnow(parseSnow(currentNode)); + + current.setWind(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Wind.class)); + current.setRain(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Rain.class)); + current.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Snow.class)); return current; } @@ -144,7 +160,7 @@ public class OneCallWeatherResponseMapper { final List minutelyList = new ArrayList<>(); for (final JsonNode minutelyNode : minutelyListNode) { minutelyList.add(Minutely.withValue( - LocalDateTime.ofInstant(Instant.ofEpochSecond(minutelyNode.get("dt").asInt()), TimeZone.getDefault().toZoneId()), + parseDateTime(minutelyNode.get("dt")), minutelyNode.get("precipitation").asDouble() )); } @@ -152,20 +168,21 @@ public class OneCallWeatherResponseMapper { return minutelyList; } - private List parseHourlyList(JsonNode hourlyListNode) { + private List parseHourlyList(JsonNode hourlyListNode) throws IOException { if (hourlyListNode == null) { return null; } final List hourlyList = new ArrayList<>(); for (final JsonNode hourlyNode : hourlyListNode) { final Hourly hourly = new Hourly(); - hourly.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(hourlyNode.get("dt").asInt()), TimeZone.getDefault().toZoneId())); + hourly.setForecastTime(parseDateTime(hourlyNode.get("dt"))); - hourly.setWeatherState(parseWeatherState(hourlyNode.get("weather").get(0))); - hourly.setTemperature(parseTemperature(hourlyNode)); - hourly.setAtmosphericPressure(parsePressure(hourlyNode)); - hourly.setHumidity(parseHumidity(hourlyNode)); - hourly.setClouds(parseClouds(hourlyNode)); + hourly.setWeatherStates(parseWeatherStates(hourlyNode.get("weather"))); + + hourly.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Temperature.class)); + hourly.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), AtmosphericPressure.class)); + hourly.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Humidity.class)); + hourly.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Clouds.class)); final JsonNode uviNode = hourlyNode.get("uvi"); if (uviNode != null) { @@ -176,13 +193,13 @@ public class OneCallWeatherResponseMapper { if (visibilityNode != null) { hourly.setVisibilityInMetres(visibilityNode.asDouble()); } - hourly.setWind(parseWind(hourlyNode)); + hourly.setWind(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Wind.class)); final JsonNode popNode = hourlyNode.get("pop"); if (popNode != null) { hourly.setProbabilityOfPrecipitation(popNode.asDouble()); } - hourly.setRain(parseRain(hourlyNode)); - hourly.setSnow(parseSnow(hourlyNode)); + hourly.setRain(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Rain.class)); + hourly.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Snow.class)); hourlyList.add(hourly); } @@ -190,39 +207,40 @@ public class OneCallWeatherResponseMapper { return hourlyList; } - private List parseDailyList(JsonNode dailyListNode) { + private List parseDailyList(JsonNode dailyListNode) throws IOException { if (dailyListNode == null) { return null; } final List dailyList = new ArrayList<>(); for (final JsonNode dailyNode : dailyListNode) { final Daily daily = new Daily(); - daily.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(dailyNode.get("dt").asInt()), TimeZone.getDefault().toZoneId())); - daily.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(dailyNode.get("sunrise").asInt()), TimeZone.getDefault().toZoneId())); - daily.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(dailyNode.get("sunset").asInt()), TimeZone.getDefault().toZoneId())); + daily.setForecastTime(parseDateTime(dailyNode.get("dt"))); + daily.setSunriseTime(parseDateTime(dailyNode.get("sunrise"))); + daily.setSunsetTime(parseDateTime(dailyNode.get("sunset"))); final JsonNode moonriseTimeNode = dailyNode.get("moonrise"); if (moonriseTimeNode != null) { - daily.setMoonriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(moonriseTimeNode.asInt()), TimeZone.getDefault().toZoneId())); + daily.setMoonriseTime(parseDateTime(moonriseTimeNode)); } final JsonNode moonsetTimeNode = dailyNode.get("moonset"); if (moonsetTimeNode != null) { - daily.setMoonsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(moonsetTimeNode.asInt()), TimeZone.getDefault().toZoneId())); + daily.setMoonsetTime(parseDateTime(moonsetTimeNode)); } final JsonNode moonPhaseNode = dailyNode.get("moon_phase"); if (moonPhaseNode != null) { daily.setMoonPhase(new MoonPhase(moonPhaseNode.asDouble())); } - daily.setWeatherState(parseWeatherState(dailyNode.get("weather").get(0))); - daily.setTemperature(parseDailyTemperature(dailyNode)); - daily.setAtmosphericPressure(parsePressure(dailyNode)); - daily.setHumidity(parseHumidity(dailyNode)); - daily.setWind(parseWind(dailyNode)); - daily.setClouds(parseClouds(dailyNode)); + daily.setWeatherStates(parseWeatherStates(dailyNode.get("weather"))); + + daily.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), DailyTemperature.class)); + daily.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), AtmosphericPressure.class)); + daily.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), Humidity.class)); + daily.setWind(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), Wind.class)); + daily.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), Clouds.class)); daily.setUvIndex(dailyNode.get("uvi").asDouble()); daily.setProbabilityOfPrecipitation(dailyNode.get("pop").asDouble()); - daily.setRain(parseDailyRain(dailyNode)); - daily.setSnow(parseDailySnow(dailyNode)); + daily.setRain(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), DailyRain.class)); + daily.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), DailySnow.class)); dailyList.add(daily); } @@ -230,213 +248,87 @@ public class OneCallWeatherResponseMapper { return dailyList; } - private List parseAlerts(JsonNode alertsNode) { - if (alertsNode == null) { + private List parseAlerts(JsonNode alertsNode) throws IOException { + if (alertsNode == null || !alertsNode.isArray()) { return null; } final List alerts = new ArrayList<>(); for (final JsonNode alertNode : alertsNode) { - Alert alert = new Alert(); - alert.setSenderName(alertNode.get("sender_name").asText()); - alert.setEventName(alertNode.get("event").asText()); - alert.setStartTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(alertNode.get("start").asInt()), TimeZone.getDefault().toZoneId())); - alert.setEndTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(alertNode.get("end").asInt()), TimeZone.getDefault().toZoneId())); - alert.setDescription(alertNode.get("description").asText()); - alerts.add(alert); + alerts.add(objectMapper.readValue(objectMapper.treeAsTokens(alertNode), Alert.class)); } return alerts; } - private HistoricalWeatherData mapToHistorical(JsonNode rootNode) { + private HistoricalWeatherData mapToHistorical(JsonNode rootNode) throws IOException { final HistoricalWeatherData historicalData = new HistoricalWeatherData(); - historicalData.setCoordinate(Coordinate.of(rootNode.get("lat").asDouble(), rootNode.get("lon").asDouble())); - historicalData.setTimezone(ZoneId.of(rootNode.get("timezone").asText())); - historicalData.setTimezoneOffset(ZoneOffset.ofTotalSeconds(rootNode.get("timezone_offset").asInt())); + historicalData.setCoordinate(Coordinates.of(rootNode.get("lat").asDouble(), rootNode.get("lon").asDouble())); + historicalData.setTimezone(parseZoneId(rootNode.get("timezone"))); + historicalData.setTimezoneOffset(parseZoneOffset(rootNode.get("timezone_offset"))); historicalData.setHistoricalWeather(parseHistoricalWeather(rootNode.get("current"))); historicalData.setHourlyList(parseHourlyHistoricalList(rootNode.get("hourly"))); return historicalData; } - private HistoricalWeather parseHistoricalWeather(JsonNode currentNode) { + private HistoricalWeather parseHistoricalWeather(JsonNode currentNode) throws IOException { if (currentNode == null) { return null; } final HistoricalWeather historicalWeather = new HistoricalWeather(); - historicalWeather.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("dt").asInt()), TimeZone.getDefault().toZoneId())); - historicalWeather.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("sunrise").asInt()), TimeZone.getDefault().toZoneId())); - historicalWeather.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("sunset").asInt()), TimeZone.getDefault().toZoneId())); + historicalWeather.setForecastTime(parseDateTime(currentNode.get("dt"))); + historicalWeather.setSunriseTime(parseDateTime(currentNode.get("sunrise"))); + historicalWeather.setSunsetTime(parseDateTime(currentNode.get("sunset"))); - final JsonNode weatherListNode = currentNode.get("weather"); - if (weatherListNode != null) { - historicalWeather.setWeatherState(parseWeatherState(weatherListNode.get(0))); + historicalWeather.setWeatherStates(parseWeatherStates(currentNode.get("weather"))); + + historicalWeather.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Temperature.class)); + historicalWeather.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), AtmosphericPressure.class)); + historicalWeather.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Humidity.class)); + historicalWeather.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Clouds.class)); + + final JsonNode uviNode = currentNode.get("uvi"); + if (uviNode != null) { + historicalWeather.setUvIndex(uviNode.asDouble()); } - historicalWeather.setTemperature(parseTemperature(currentNode)); - historicalWeather.setAtmosphericPressure(parsePressure(currentNode)); - historicalWeather.setHumidity(parseHumidity(currentNode)); - historicalWeather.setClouds(parseClouds(currentNode)); - historicalWeather.setUvIndex(currentNode.get("uvi").asDouble()); - final JsonNode visibilityMode = currentNode.get("visibility"); - if (visibilityMode != null) { - historicalWeather.setVisibilityInMetres(visibilityMode.asDouble()); + + final JsonNode visibilityNode = currentNode.get("visibility"); + if (visibilityNode != null) { + historicalWeather.setVisibilityInMetres(visibilityNode.asDouble()); } - historicalWeather.setWind(parseWind(currentNode)); - historicalWeather.setRain(parseRain(currentNode)); - historicalWeather.setSnow(parseSnow(currentNode)); + historicalWeather.setWind(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Wind.class)); + historicalWeather.setRain(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Rain.class)); + historicalWeather.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Snow.class)); return historicalWeather; } - private List parseHourlyHistoricalList(JsonNode hourlyListNode) { + private List parseHourlyHistoricalList(JsonNode hourlyListNode) throws IOException { if (hourlyListNode == null) { return null; } final List hourlyList = new ArrayList<>(); for (final JsonNode hourlyNode : hourlyListNode) { final HourlyHistorical hourly = new HourlyHistorical(); - hourly.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(hourlyNode.get("dt").asInt()), TimeZone.getDefault().toZoneId())); + hourly.setForecastTime(parseDateTime(hourlyNode.get("dt"))); - hourly.setWeatherState(parseWeatherState(hourlyNode.get("weather").get(0))); - hourly.setTemperature(parseTemperature(hourlyNode)); - hourly.setAtmosphericPressure(parsePressure(hourlyNode)); - hourly.setHumidity(parseHumidity(hourlyNode)); - hourly.setClouds(parseClouds(hourlyNode)); + hourly.setWeatherStates(parseWeatherStates(hourlyNode.get("weather"))); + + hourly.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Temperature.class)); + hourly.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), AtmosphericPressure.class)); + hourly.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Humidity.class)); + hourly.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Clouds.class)); final JsonNode visibilityNode = hourlyNode.get("visibility"); if (visibilityNode != null) { hourly.setVisibilityInMetres(visibilityNode.asDouble()); } - hourly.setWind(parseWind(hourlyNode)); - hourly.setRain(parseRain(hourlyNode)); - hourly.setSnow(parseSnow(hourlyNode)); + hourly.setWind(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Wind.class)); + hourly.setRain(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Rain.class)); + hourly.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Snow.class)); hourlyList.add(hourly); } return hourlyList; } - - private WeatherState parseWeatherState(JsonNode weatherNode) { - if (weatherNode == null) { - return null; - } - final WeatherState weatherState = new WeatherState( - weatherNode.get("id").asInt(), - weatherNode.get("main").asText(), - weatherNode.get("description").asText() - ); - weatherState.setIconId(weatherNode.get("icon").asText()); - - return weatherState; - } - - private Temperature parseTemperature(JsonNode rootNode) { - final double tempValue = rootNode.get("temp").asDouble(); - final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit()); - - final JsonNode tempFeelsLike = rootNode.get("feels_like"); - if (tempFeelsLike != null) { - temperature.setFeelsLike(tempFeelsLike.asDouble()); - } - final JsonNode dewPoint = rootNode.get("dew_point"); - if (dewPoint != null) { - temperature.setDewPoint(dewPoint.asDouble()); - } - - return temperature; - } - - private DailyTemperature parseDailyTemperature(JsonNode dailyNode) { - final DailyTemperature temperature = new DailyTemperature(); - final JsonNode tempNode = dailyNode.get("temp"); - temperature.setMorning(tempNode.get("morn").asDouble()); - temperature.setDay(tempNode.get("day").asDouble()); - temperature.setEve(tempNode.get("eve").asDouble()); - temperature.setNight(tempNode.get("night").asDouble()); - temperature.setMin(tempNode.get("min").asDouble()); - temperature.setMax(tempNode.get("max").asDouble()); - - final JsonNode feelsLikeNode = dailyNode.get("feels_like"); - temperature.setMorningFeelsLike(feelsLikeNode.get("morn").asDouble()); - temperature.setDayFeelsLike(feelsLikeNode.get("day").asDouble()); - temperature.setEveFeelsLike(feelsLikeNode.get("eve").asDouble()); - temperature.setNightFeelsLike(feelsLikeNode.get("night").asDouble()); - - return temperature; - } - - private AtmosphericPressure parsePressure(JsonNode rootNode) { - return AtmosphericPressure.withValue(rootNode.get("pressure").asDouble()); - } - - private Humidity parseHumidity(JsonNode rootNode) { - return Humidity.withValue((byte) (rootNode.get("humidity").asInt())); - } - - private Wind parseWind(JsonNode rootNode) { - final JsonNode windSpeedNode = rootNode.get("wind_speed"); - if (windSpeedNode == null) { - return null; - } - - final Wind wind = Wind.withValue(windSpeedNode.asDouble(), unitSystem.getWindUnit()); - - final JsonNode degNode = rootNode.get("wind_deg"); - if (degNode != null) { - wind.setDegrees(degNode.asDouble()); - } - final JsonNode gustNode = rootNode.get("wind_gust"); - if (gustNode != null) { - wind.setGust(gustNode.asDouble()); - } - - return wind; - } - - private Rain parseRain(JsonNode root) { - final JsonNode rainNode = root.get("rain"); - if (rainNode != null) { - final JsonNode oneHourNode = rainNode.get("1h"); - if (oneHourNode != null) { - return Rain.withOneHourLevelValue(oneHourNode.asDouble()); - } - } - return null; - } - - private DailyRain parseDailyRain(JsonNode dailyNode) { - final JsonNode valueNode = dailyNode.get("rain"); - if (valueNode != null) { - return DailyRain.withValue(valueNode.asDouble()); - } - return null; - } - - private Snow parseSnow(JsonNode root) { - final JsonNode snowNode = root.get("snow"); - if (snowNode != null) { - final JsonNode OneHourNode = snowNode.get("1h"); - if (OneHourNode != null) { - Rain.withOneHourLevelValue(OneHourNode.asDouble()); - } - } - return null; - } - - private DailySnow parseDailySnow(JsonNode dailyNode) { - final JsonNode valueNode = dailyNode.get("snow"); - if (valueNode != null) { - return DailySnow.withValue(valueNode.asDouble()); - } - return null; - } - - private Clouds parseClouds(JsonNode rootNode) { - final JsonNode cloudsNode = rootNode.get("clouds"); - if (cloudsNode != null) { - return Clouds.withValue((byte) cloudsNode.asInt()); - } - - return null; - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/AtmosphericPressure.java b/src/main/java/com/github/prominence/openweathermap/api/model/AtmosphericPressure.java index b486a8b..663f39b 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/AtmosphericPressure.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/AtmosphericPressure.java @@ -48,11 +48,12 @@ public class AtmosphericPressure { /** * Static method for {@link AtmosphericPressure} creation with value checking. + * * @param value atmospheric pressure value. * @return instantiated {@link AtmosphericPressure} object. */ public static AtmosphericPressure withValue(double value) { - if (value < 0) { + if (value < 0) { throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range."); } return new AtmosphericPressure(value); @@ -74,7 +75,7 @@ public class AtmosphericPressure { * @throws IllegalArgumentException in case if provided value isn't in allowed range. */ public void setValue(double value) { - if (value < 0) { + if (value < 0) { throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range."); } this.value = value; @@ -96,7 +97,7 @@ public class AtmosphericPressure { * @throws IllegalArgumentException in case if provided value isn't in allowed range. */ public void setSeaLevelValue(double seaLevelValue) { - if (seaLevelValue < 0) { + if (seaLevelValue < 0) { throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range."); } this.seaLevelValue = seaLevelValue; @@ -118,7 +119,7 @@ public class AtmosphericPressure { * @throws IllegalArgumentException in case if provided value isn't in allowed range. */ public void setGroundLevelValue(double groundLevelValue) { - if (groundLevelValue < 0) { + if (groundLevelValue < 0) { throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range."); } this.groundLevelValue = groundLevelValue; diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/Clouds.java b/src/main/java/com/github/prominence/openweathermap/api/model/Clouds.java index e5f3fa4..ad4cd5e 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Clouds.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/Clouds.java @@ -45,11 +45,12 @@ public class Clouds { /** * Static method for {@link Clouds} creation with value checking. + * * @param value clouds percentage value. * @return instantiated {@link Clouds} object. */ public static Clouds withValue(byte value) { - if (value < 0 || value > 100) { + if (value < 0 || value > 100) { throw new IllegalArgumentException("Cloudiness value must be in [0, 100] range."); } return new Clouds(value); diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/Coordinate.java b/src/main/java/com/github/prominence/openweathermap/api/model/Coordinates.java similarity index 83% rename from src/main/java/com/github/prominence/openweathermap/api/model/Coordinate.java rename to src/main/java/com/github/prominence/openweathermap/api/model/Coordinates.java index b46a9fd..0066b8f 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Coordinate.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/Coordinates.java @@ -22,34 +22,40 @@ package com.github.prominence.openweathermap.api.model; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.Objects; /** * Represents some location by its latitude and longitude. */ -public class Coordinate { +public class Coordinates { + @JsonProperty("lat") private double latitude; + @JsonProperty("lon") private double longitude; - private Coordinate() { + private Coordinates() { } /** - * Method for {@link Coordinate} creation with correctness check. - * @param latitude latitude + * Method for {@link Coordinates} creation with correctness check. + * + * @param latitude latitude * @param longitude longitude * @return coordinate object. */ - public static Coordinate of(double latitude, double longitude) { - final Coordinate coordinate = new Coordinate(); - coordinate.setLatitude(latitude); - coordinate.setLongitude(longitude); - return coordinate; + public static Coordinates of(double latitude, double longitude) { + final Coordinates coordinates = new Coordinates(); + coordinates.setLatitude(latitude); + coordinates.setLongitude(longitude); + return coordinates; } /** * Sets latitude with checks. + * * @param latitude latitude value */ public void setLatitude(double latitude) { @@ -61,6 +67,7 @@ public class Coordinate { /** * Sets longitude with checks. + * * @param longitude longitude value */ public void setLongitude(double longitude) { @@ -72,6 +79,7 @@ public class Coordinate { /** * Returns latitude. + * * @return latitude */ public double getLatitude() { @@ -80,6 +88,7 @@ public class Coordinate { /** * Returns longitude. + * * @return longitude */ public double getLongitude() { @@ -89,8 +98,8 @@ public class Coordinate { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Coordinate)) return false; - Coordinate that = (Coordinate) o; + if (!(o instanceof Coordinates)) return false; + Coordinates that = (Coordinates) o; return Double.compare(that.latitude, latitude) == 0 && Double.compare(that.longitude, longitude) == 0; } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/CoordinateRectangle.java b/src/main/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangle.java similarity index 87% rename from src/main/java/com/github/prominence/openweathermap/api/model/CoordinateRectangle.java rename to src/main/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangle.java index 2aec240..5e70c55 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/CoordinateRectangle.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangle.java @@ -27,13 +27,13 @@ import java.util.Objects; /** * Represents coordinate rectangle by its bottom-left and top-right coordinates. */ -public class CoordinateRectangle { +public class CoordinatesRectangle { private final double longitudeLeft; private final double latitudeBottom; private final double longitudeRight; private final double latitudeTop; - private CoordinateRectangle(double longitudeLeft, double latitudeBottom, double longitudeRight, double latitudeTop) { + private CoordinatesRectangle(double longitudeLeft, double latitudeBottom, double longitudeRight, double latitudeTop) { this.longitudeLeft = longitudeLeft; this.latitudeBottom = latitudeBottom; this.longitudeRight = longitudeRight; @@ -41,21 +41,21 @@ public class CoordinateRectangle { } /** - * Method for {@link CoordinateRectangle} creation with correctness check. + * Method for {@link CoordinatesRectangle} creation with correctness check. * @param longitudeLeft left longitude * @param latitudeBottom bottom latitude * @param longitudeRight right longitude * @param latitudeTop tip latitude * @return coordinate rectangle object. */ - public static CoordinateRectangle withValues(double longitudeLeft, double latitudeBottom, double longitudeRight, double latitudeTop) { + public static CoordinatesRectangle withValues(double longitudeLeft, double latitudeBottom, double longitudeRight, double latitudeTop) { if (latitudeBottom < -90 || latitudeTop < -90 || latitudeBottom > 90 || latitudeTop > 90) { throw new IllegalArgumentException("Latitude value must be in the next range: [-90.0; 90.0]."); } if (longitudeLeft < -180 || longitudeRight < -180 || longitudeLeft > 180 || longitudeRight > 180) { throw new IllegalArgumentException("Longitude value must be in the next range: [-180.0; 180.0]."); } - return new CoordinateRectangle(longitudeLeft, latitudeBottom, longitudeRight, latitudeTop); + return new CoordinatesRectangle(longitudeLeft, latitudeBottom, longitudeRight, latitudeTop); } /** @@ -101,8 +101,8 @@ public class CoordinateRectangle { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof CoordinateRectangle)) return false; - CoordinateRectangle rectangle = (CoordinateRectangle) o; + if (!(o instanceof CoordinatesRectangle)) return false; + CoordinatesRectangle rectangle = (CoordinatesRectangle) o; return Double.compare(rectangle.longitudeLeft, longitudeLeft) == 0 && Double.compare(rectangle.latitudeBottom, latitudeBottom) == 0 && Double.compare(rectangle.longitudeRight, longitudeRight) == 0 && @@ -187,14 +187,14 @@ public class CoordinateRectangle { } /** - * Builds {@link CoordinateRectangle} object with correctness check. - * @return {@link CoordinateRectangle} built object. + * Builds {@link CoordinatesRectangle} object with correctness check. + * @return {@link CoordinatesRectangle} built object. */ - public CoordinateRectangle build() { + public CoordinatesRectangle build() { if (longitudeLeft == null || latitudeBottom == null || longitudeRight == null || latitudeTop == null) { throw new IllegalStateException("Not all fields were set."); } - return new CoordinateRectangle(longitudeLeft, latitudeBottom, longitudeRight, latitudeTop); + return new CoordinatesRectangle(longitudeLeft, latitudeBottom, longitudeRight, latitudeTop); } } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/Humidity.java b/src/main/java/com/github/prominence/openweathermap/api/model/Humidity.java index ebd9d3a..6ae7322 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Humidity.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/Humidity.java @@ -45,11 +45,12 @@ public class Humidity { /** * Creates {@link Humidity} object with correctness check. + * * @param value humidity * @return created {@link Humidity} object */ public static Humidity withValue(byte value) { - if (value < 0 || value > 100) { + if (value < 0 || value > 100) { throw new IllegalArgumentException("Humidity value must be in [0, 100] range."); } return new Humidity(value); @@ -71,7 +72,7 @@ public class Humidity { * @throws IllegalArgumentException in case if provided value isn't in allowed range. */ public void setValue(int value) { - if (value < 0 || value > 100) { + if (value < 0 || value > 100) { throw new IllegalArgumentException("Humidity value must be in [0, 100] range."); } this.value = value; diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/Temperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/Temperature.java index 66b4fc6..b400e99 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Temperature.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/Temperature.java @@ -41,8 +41,9 @@ public class Temperature { /** * Creates {@link Temperature} object with correctness check. + * * @param value temperature value - * @param unit temperature unit + * @param unit temperature unit * @return temperature object */ public static Temperature withValue(double value, String unit) { @@ -54,6 +55,7 @@ public class Temperature { /** * Returns temperature value. + * * @return value */ public double getValue() { @@ -62,6 +64,7 @@ public class Temperature { /** * Sets temperature value. + * * @param value temperature */ public void setValue(double value) { @@ -70,6 +73,7 @@ public class Temperature { /** * Returns maximal temperature value. + * * @return maximal temperature value */ public Double getMaxTemperature() { @@ -78,6 +82,7 @@ public class Temperature { /** * Sets maximal temperature value. + * * @param maxTemperature maximal temperature */ public void setMaxTemperature(Double maxTemperature) { @@ -86,6 +91,7 @@ public class Temperature { /** * Returns minimal temperature value. + * * @return minimal temperature value */ public Double getMinTemperature() { @@ -94,6 +100,7 @@ public class Temperature { /** * Sets minimal temperature value. + * * @param minTemperature minimal temperature */ public void setMinTemperature(Double minTemperature) { @@ -102,6 +109,7 @@ public class Temperature { /** * Returns 'feels like' temperature value. + * * @return 'feels like' temperature value */ public Double getFeelsLike() { @@ -110,6 +118,7 @@ public class Temperature { /** * Sets 'feels like' temperature value. + * * @param feelsLike 'feels like' temperature */ public void setFeelsLike(Double feelsLike) { @@ -118,6 +127,7 @@ public class Temperature { /** * Returns temperature unit. + * * @return unit */ public String getUnit() { @@ -126,6 +136,7 @@ public class Temperature { /** * Sets temperature unit with correctness check. + * * @param unit temperature unit */ public void setUnit(String unit) { @@ -138,8 +149,7 @@ public class Temperature { @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Temperature)) return false; - Temperature that = (Temperature) o; + if (!(o instanceof Temperature that)) return false; return Double.compare(that.value, value) == 0 && Objects.equals(maxTemperature, that.maxTemperature) && Objects.equals(minTemperature, that.minTemperature) && diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Wind.java b/src/main/java/com/github/prominence/openweathermap/api/model/Wind.java similarity index 95% rename from src/main/java/com/github/prominence/openweathermap/api/model/weather/Wind.java rename to src/main/java/com/github/prominence/openweathermap/api/model/Wind.java index 3d9b4a8..282da8a 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Wind.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/Wind.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.weather; +package com.github.prominence.openweathermap.api.model; import java.util.Objects; @@ -46,8 +46,9 @@ public class Wind { /** * Creates {@link Wind} object with correctness check. + * * @param speed the speed - * @param unit the unitSystem + * @param unit the unitSystem * @return wind object */ public static Wind withValue(double speed, String unit) { @@ -83,6 +84,7 @@ public class Wind { /** * Gets gust value. + * * @return the gust */ public Double getGust() { @@ -91,6 +93,7 @@ public class Wind { /** * Sets gust value. + * * @param gust the gust. */ public void setGust(double gust) { @@ -115,7 +118,7 @@ public class Wind { * @param degrees the degrees */ public void setDegrees(double degrees) { - if (degrees < 0 || degrees > 360) { + if (degrees < 0 || degrees > 360) { throw new IllegalArgumentException("Wind direction value must be in [0, 360] range."); } this.degrees = degrees; diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetails.java b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetails.java index c4e7112..7afc9e4 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetails.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetails.java @@ -24,7 +24,7 @@ package com.github.prominence.openweathermap.api.model.air.pollution; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import java.util.List; import java.util.Objects; @@ -33,7 +33,7 @@ import java.util.Objects; * The type Air pollution. */ public class AirPollutionDetails { - private Coordinate coordinate; + private Coordinates coordinates; private List airPollutionRecords; /** @@ -41,17 +41,17 @@ public class AirPollutionDetails { * * @return the coordinate */ - public Coordinate getCoordinate() { - return coordinate; + public Coordinates getCoordinate() { + return coordinates; } /** * Sets coordinate. * - * @param coordinate the coordinate + * @param coordinates the coordinate */ - public void setCoordinate(Coordinate coordinate) { - this.coordinate = coordinate; + public void setCoordinate(Coordinates coordinates) { + this.coordinates = coordinates; } /** @@ -77,11 +77,11 @@ public class AirPollutionDetails { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AirPollutionDetails that = (AirPollutionDetails) o; - return Objects.equals(coordinate, that.coordinate) && Objects.equals(airPollutionRecords, that.airPollutionRecords); + return Objects.equals(coordinates, that.coordinates) && Objects.equals(airPollutionRecords, that.airPollutionRecords); } @Override public int hashCode() { - return Objects.hash(coordinate, airPollutionRecords); + return Objects.hash(coordinates, airPollutionRecords); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Wind.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Wind.java deleted file mode 100644 index d54af6d..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Wind.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2021 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 com.github.prominence.openweathermap.api.model.forecast; - -import java.util.Objects; - -/** - * Represents wind information. - */ -public class Wind { - private double speed; - private Double degrees; - private String unit; - - /** - * Instantiates a new Wind. - * - * @param speed the speed - * @param unit the unitSystem - */ - private Wind(double speed, String unit) { - this.speed = speed; - this.unit = unit; - } - - /** - * Creates {@link Wind} object with correctness check - * @param speed the wind - * @param unit the unitSystem - * @return created wind object - */ - public static Wind withValue(double speed, String unit) { - if (speed < 0) { - throw new IllegalArgumentException("Wind speed value must be in positive or zero."); - } - if (unit == null) { - throw new IllegalArgumentException("Unit must be set."); - } - return new Wind(speed, unit); - } - - /** - * Gets speed. - * - * @return the speed - */ - public double getSpeed() { - return speed; - } - - /** - * Sets speed. - * - * @param speed the speed - */ - public void setSpeed(double speed) { - if (speed < 0) { - throw new IllegalArgumentException("Wind speed value must be in positive or zero."); - } - this.speed = speed; - } - - /** - * Gets degrees. - * - * @return the degrees - */ - public Double getDegrees() { - return degrees; - } - - /** - * Sets degrees. - * - * @param degrees the degrees - */ - public void setDegrees(double degrees) { - if (degrees < 0 || degrees > 360) { - throw new IllegalArgumentException("Wind direction value must be in [0, 360] range."); - } - this.degrees = degrees; - } - - /** - * Gets unitSystem. - * - * @return the unitSystem - */ - public String getUnit() { - return unit; - } - - /** - * Sets unitSystem. - * - * @param unit the unitSystem - */ - public void setUnit(String unit) { - if (unit == null) { - throw new IllegalArgumentException("Unit must be set."); - } - this.unit = unit; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Wind)) return false; - Wind wind = (Wind) o; - return Double.compare(wind.speed, speed) == 0 && - Objects.equals(degrees, wind.degrees) && - Objects.equals(unit, wind.unit); - } - - @Override - public int hashCode() { - return Objects.hash(speed, degrees, unit); - } - - @Override - public String toString() { - return "Wind speed: " + speed + " " + unit + - ", degrees: " + degrees; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/AtmosphericPressure.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/AtmosphericPressure.java new file mode 100644 index 0000000..7404966 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/AtmosphericPressure.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021 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 com.github.prominence.openweathermap.api.model.forecast.daily; + +import java.util.Objects; + +/** + * The AtmosphericPressure type represents atmospheric pressure value. + * Its value can only be a double in [0, +∞) range. + */ +public class AtmosphericPressure { + private static final String DEFAULT_UNIT = "hPa"; + + private double seaLevelValue; + + private AtmosphericPressure() { + } + + /** + * Static method for {@link AtmosphericPressure} creation with value checking. + * @param seaLevelValue atmospheric pressure value. + * @return instantiated {@link AtmosphericPressure} object. + */ + public static AtmosphericPressure withValue(double seaLevelValue) { + final AtmosphericPressure atmosphericPressure = new AtmosphericPressure(); + atmosphericPressure.setSeaLevelValue(seaLevelValue); + return atmosphericPressure; + } + + /** + * Gets sea level value. + * + * @return the sea level value. + */ + public Double getSeaLevelValue() { + return seaLevelValue; + } + + /** + * Sets sea level value. + * + * @param seaLevelValue the sea level value. + * @throws IllegalArgumentException in case if provided value isn't in allowed range. + */ + public void setSeaLevelValue(double seaLevelValue) { + if (seaLevelValue < 0) { + throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range."); + } + this.seaLevelValue = seaLevelValue; + } + + /** + * Returns pressure unitSystem. Constantly equals to 'hPa'. + * + * @return the pressure unitSystem. + */ + public String getUnit() { + return DEFAULT_UNIT; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AtmosphericPressure that = (AtmosphericPressure) o; + return Double.compare(that.seaLevelValue, seaLevelValue) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(seaLevelValue); + } + + @Override + public String toString() { + return "Pressure: " + seaLevelValue + ' ' + getUnit(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Forecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Forecast.java new file mode 100644 index 0000000..6f2bbff --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Forecast.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.daily; + + +import java.util.List; +import java.util.Objects; + +/** + * Represents information about forecast for different timestamps. + */ +public class Forecast { + private Location location; + private List weatherForecasts; + + /** + * Returns location information. + * @return location + */ + public Location getLocation() { + return location; + } + + /** + * Sets forecast location. + * @param location forecast location + */ + public void setLocation(Location location) { + this.location = location; + } + + /** + * Returns list of weather forecasts for different timestamps. + * @return list of forecast-per-timestamp information. + */ + public List getWeatherForecasts() { + return weatherForecasts; + } + + /** + * Sets list of weather forecasts for different timestamps. + * @param weatherForecasts list of forecast information + */ + public void setWeatherForecasts(List weatherForecasts) { + this.weatherForecasts = weatherForecasts; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Forecast forecast = (Forecast) o; + return Objects.equals(location, forecast.location) && Objects.equals(weatherForecasts, forecast.weatherForecasts); + } + + @Override + public int hashCode() { + return Objects.hash(location, weatherForecasts); + } + + @Override + public String toString() { + return "A forecast for " + location.getName() + " with " + weatherForecasts.size() + " timestamps."; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Location.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Location.java new file mode 100644 index 0000000..d876f45 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Location.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.daily; + +import com.github.prominence.openweathermap.api.model.Coordinates; + +import java.time.ZoneOffset; +import java.util.Objects; + +/** + * Represents location information. + */ +public class Location { + private int id; + private String name; + private String countryCode; + + private ZoneOffset zoneOffset; + + private Coordinates coordinates; + + private Long population; + + private Location(int id, String name) { + this.id = id; + this.name = name; + } + + /** + * Creates {@link Location} object with correctness check. + * @param id location id + * @param name location name + * @return location object + */ + public static Location withValues(int id, String name) { + if (name == null) { + throw new IllegalArgumentException("Name must be set."); + } + return new Location(id, name); + } + + /** + * Returns ID. + * @return location ID + */ + public int getId() { + return id; + } + + /** + * Sets location ID. + * @param id location id + */ + public void setId(int id) { + this.id = id; + } + + /** + * Returns location name. + * @return location name + */ + public String getName() { + return name; + } + + /** + * Sets location name. + * @param name location name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns country code. + * @return location country code + */ + public String getCountryCode() { + return countryCode; + } + + /** + * Sets location country code. + * @param countryCode location country code + */ + public void setCountryCode(String countryCode) { + this.countryCode = countryCode; + } + + /** + * Returns location timezone offset. + * @return timezone offset + */ + public ZoneOffset getZoneOffset() { + return zoneOffset; + } + + /** + * Sets location timezone offset. + * @param zoneOffset timezone offset + */ + public void setZoneOffset(ZoneOffset zoneOffset) { + this.zoneOffset = zoneOffset; + } + + /** + * Returns location coordinates. + * @return location coordinates. + */ + public Coordinates getCoordinate() { + return coordinates; + } + + /** + * Sets location coordinates. + * @param coordinates location coordinates + */ + public void setCoordinate(Coordinates coordinates) { + this.coordinates = coordinates; + } + + /** + * Sets location population. + * @return location population + */ + public Long getPopulation() { + return population; + } + + /** + * Sets location population. + * @param population location population + */ + public void setPopulation(Long population) { + this.population = population; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Location)) return false; + Location location = (Location) o; + return id == location.id && + Objects.equals(name, location.name) && + Objects.equals(countryCode, location.countryCode) && + Objects.equals(zoneOffset, location.zoneOffset) && + Objects.equals(coordinates, location.coordinates) && + Objects.equals(population, location.population); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, countryCode, zoneOffset, coordinates, population); + } + + @Override + public String toString() { + final StringBuilder stringBuilder = new StringBuilder(); + if (coordinates != null) { + stringBuilder.append(coordinates); + stringBuilder.append(". "); + } + stringBuilder.append("ID: "); + stringBuilder.append(id); + stringBuilder.append(", Name: "); + stringBuilder.append(name); + if (countryCode != null) { + stringBuilder.append('('); + stringBuilder.append(countryCode); + stringBuilder.append(')'); + } + if (population != null) { + stringBuilder.append(", Population: "); + stringBuilder.append(population); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Rain.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Rain.java new file mode 100644 index 0000000..10806fd --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Rain.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.daily; + +import java.util.Objects; + +/** + * Represents rain information. + */ +public class Rain { + private static final String DEFAULT_UNIT = "mm"; + + private double level; + + private Rain(double level) { + this.level = level; + } + + /** + * Creates {@link Rain} object with correctness check. + * @param threeHourLevel 3-hour rain level value + * @return rain object. + */ + public static Rain withThreeHourLevelValue(double threeHourLevel) { + if (threeHourLevel < 0) { + throw new IllegalArgumentException("Rain level value cannot be negative."); + } + return new Rain(threeHourLevel); + } + + /** + * Returns 3-hour rain level value. + * @return 3-hour rain level value + */ + public double getLevel() { + return level; + } + + /** + * Sets 3-hour rain level value with correctness check. + * @param level 3-hour rain level value + */ + public void setLevel(double level) { + if (level < 0) { + throw new IllegalArgumentException("Rain level value cannot be negative."); + } + this.level = level; + } + + /** + * Returns rain level unit of measure. Currently is constant. + * @return rain level unit of measure + */ + public String getUnit() { + return DEFAULT_UNIT; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Rain rain = (Rain) o; + return Double.compare(rain.level, level) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(level); + } + + @Override + public String toString() { + return "3-hour rain level: " + + level + ' ' + + getUnit(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Snow.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Snow.java new file mode 100644 index 0000000..258163f --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Snow.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.daily; + +import java.util.Objects; + +/** + * Represents snow information. + */ +public class Snow { + private static final String DEFAULT_UNIT = "mm"; + + private double level; + + private Snow(double level) { + this.level = level; + } + + /** + * Creates {@link Snow} object with correctness check. + * @param threeHourLevel 3-hour snow level value + * @return snow object. + */ + public static Snow withThreeHourLevelValue(double threeHourLevel) { + if (threeHourLevel < 0) { + throw new IllegalArgumentException("Snow level value cannot be negative."); + } + return new Snow(threeHourLevel); + } + + /** + * Returns 3-hour snow level value. + * @return 3-hour snow level value + */ + public double getLevel() { + return level; + } + + /** + * Sets 3-hour snow level value with correctness check. + * @param level 3-hour snow level value + */ + public void setLevel(double level) { + if (level < 0) { + throw new IllegalArgumentException("Snow level value cannot be negative."); + } + this.level = level; + } + + /** + * Returns snow level unit of measure. Currently is constant. + * @return snow level unit of measure + */ + public String getUnit() { + return DEFAULT_UNIT; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Snow snow = (Snow) o; + return Double.compare(snow.level, level) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(level); + } + + @Override + public String toString() { + return "3-hour snow level: " + + level + ' ' + + getUnit(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Temperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Temperature.java new file mode 100644 index 0000000..f7027bf --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Temperature.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2021 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 com.github.prominence.openweathermap.api.model.forecast.daily; + +import java.util.Objects; + +/** + * The type Daily temperature. + */ +public class Temperature { + private Double morning; + private Double morningFeelsLike; + private Double day; + private Double dayFeelsLike; + private Double eve; + private Double eveFeelsLike; + private Double night; + private Double nightFeelsLike; + private Double min; + private Double max; + private String unit; + + /** + * Gets morning temperature. + * + * @return the morning + */ + public Double getMorning() { + return morning; + } + + /** + * Sets morning temperature. + * + * @param morning the morning + */ + public void setMorning(Double morning) { + this.morning = morning; + } + + /** + * Gets morning feels like temperature. + * + * @return the morning feels like temperature + */ + public Double getMorningFeelsLike() { + return morningFeelsLike; + } + + /** + * Sets morning feels like temperature. + * + * @param morningFeelsLike the morning feels like temperature + */ + public void setMorningFeelsLike(Double morningFeelsLike) { + this.morningFeelsLike = morningFeelsLike; + } + + /** + * Gets day temperature. + * + * @return the day temperature + */ + public Double getDay() { + return day; + } + + /** + * Sets day temperature. + * + * @param day the day temperature + */ + public void setDay(Double day) { + this.day = day; + } + + /** + * Gets day feels like temperature. + * + * @return the day feels like temperature + */ + public Double getDayFeelsLike() { + return dayFeelsLike; + } + + /** + * Sets day feels like temperature. + * + * @param dayFeelsLike the day feels like temperature + */ + public void setDayFeelsLike(Double dayFeelsLike) { + this.dayFeelsLike = dayFeelsLike; + } + + /** + * Gets eve temperature. + * + * @return the eve temperature + */ + public Double getEve() { + return eve; + } + + /** + * Sets eve temperature. + * + * @param eve the eve temperature + */ + public void setEve(Double eve) { + this.eve = eve; + } + + /** + * Gets eve feels like temperature. + * + * @return the eve feels like temperature + */ + public Double getEveFeelsLike() { + return eveFeelsLike; + } + + /** + * Sets eve feels like temperature. + * + * @param eveFeelsLike the eve feels like temperature + */ + public void setEveFeelsLike(Double eveFeelsLike) { + this.eveFeelsLike = eveFeelsLike; + } + + /** + * Gets night temperature. + * + * @return the night temperature + */ + public Double getNight() { + return night; + } + + /** + * Sets night temperature. + * + * @param night the night temperature + */ + public void setNight(Double night) { + this.night = night; + } + + /** + * Gets night feels like temperature. + * + * @return the night feels like temperature + */ + public Double getNightFeelsLike() { + return nightFeelsLike; + } + + /** + * Sets night feels like temperature. + * + * @param nightFeelsLike the night feels like temperature + */ + public void setNightFeelsLike(Double nightFeelsLike) { + this.nightFeelsLike = nightFeelsLike; + } + + /** + * Gets min temperature. + * + * @return the min temperature + */ + public Double getMin() { + return min; + } + + /** + * Sets min temperature. + * + * @param min the min temperature + */ + public void setMin(Double min) { + this.min = min; + } + + /** + * Gets max temperature. + * + * @return the max temperature + */ + public Double getMax() { + return max; + } + + /** + * Sets max temperature. + * + * @param max the max temperature + */ + public void setMax(Double max) { + this.max = max; + } + + /** + * Gets unit temperature. + * + * @return the unit temperature + */ + public String getUnit() { + return unit; + } + + /** + * Sets unit temperature. + * + * @param unit the unit temperature + */ + public void setUnit(String unit) { + this.unit = unit; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Temperature that = (Temperature) o; + return Objects.equals(morning, that.morning) && + Objects.equals(morningFeelsLike, that.morningFeelsLike) && + Objects.equals(day, that.day) && + Objects.equals(dayFeelsLike, that.dayFeelsLike) && + Objects.equals(eve, that.eve) && + Objects.equals(eveFeelsLike, that.eveFeelsLike) && + Objects.equals(night, that.night) && + Objects.equals(nightFeelsLike, that.nightFeelsLike) && + Objects.equals(min, that.min) && + Objects.equals(max, that.max) && + Objects.equals(unit, that.unit); + } + + @Override + public int hashCode() { + return Objects.hash(morning, morningFeelsLike, day, dayFeelsLike, eve, eveFeelsLike, night, nightFeelsLike, min, max, unit); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/WeatherForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/WeatherForecast.java new file mode 100644 index 0000000..6d9d3b9 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/WeatherForecast.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.daily; + + +import com.github.prominence.openweathermap.api.model.Clouds; +import com.github.prominence.openweathermap.api.model.Humidity; +import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.Wind; + +import java.time.LocalDateTime; +import java.util.Objects; + +/** + * Represents weather forecast information for a particular timestamp. + */ +public class WeatherForecast { + private LocalDateTime forecastTime; + + private LocalDateTime sunriseTime; + + private LocalDateTime sunsetTime; + + private WeatherState weatherState; + private Temperature temperature; + private AtmosphericPressure atmosphericPressure; + private Humidity humidity; + + private Wind wind; + private Rain rain; + private Snow snow; + private Clouds clouds; + + /** + * Gets forecast time. + * + * @return the forecast time + */ + public LocalDateTime getForecastTime() { + return forecastTime; + } + + /** + * Sets forecast time. + * + * @param forecastTime the forecast time + */ + public void setForecastTime(LocalDateTime forecastTime) { + this.forecastTime = forecastTime; + } + + /** + * Gets weather state. + * + * @return the weather state + */ + public WeatherState getWeatherState() { + return weatherState; + } + + /** + * Sets weather state. + * + * @param weatherState the weather state + */ + public void setWeatherState(WeatherState weatherState) { + this.weatherState = weatherState; + } + + /** + * Gets temperature. + * + * @return the temperature + */ + public Temperature getTemperature() { + return temperature; + } + + /** + * Sets temperature. + * + * @param temperature the temperature + */ + public void setTemperature(Temperature temperature) { + this.temperature = temperature; + } + + /** + * Gets atmospheric pressure. + * + * @return the atmospheric pressure + */ + public AtmosphericPressure getAtmosphericPressure() { + return atmosphericPressure; + } + + /** + * Sets atmospheric pressure. + * + * @param atmosphericPressure the atmospheric pressure + */ + public void setAtmosphericPressure(AtmosphericPressure atmosphericPressure) { + this.atmosphericPressure = atmosphericPressure; + } + + /** + * Gets humidity. + * + * @return the humidity + */ + public Humidity getHumidity() { + return humidity; + } + + /** + * Sets humidity. + * + * @param humidity the humidity + */ + public void setHumidity(Humidity humidity) { + this.humidity = humidity; + } + + /** + * Gets wind. + * + * @return the wind + */ + public Wind getWind() { + return wind; + } + + /** + * Sets wind. + * + * @param wind the wind + */ + public void setWind(Wind wind) { + this.wind = wind; + } + + /** + * Gets rain. + * + * @return the rain + */ + public Rain getRain() { + return rain; + } + + /** + * Sets rain. + * + * @param rain the rain + */ + public void setRain(Rain rain) { + this.rain = rain; + } + + /** + * Gets snow. + * + * @return the snow + */ + public Snow getSnow() { + return snow; + } + + /** + * Sets snow. + * + * @param snow the snow + */ + public void setSnow(Snow snow) { + this.snow = snow; + } + + /** + * Gets clouds. + * + * @return the clouds + */ + public Clouds getClouds() { + return clouds; + } + + /** + * Sets clouds. + * + * @param clouds the clouds + */ + public void setClouds(Clouds clouds) { + this.clouds = clouds; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WeatherForecast that = (WeatherForecast) o; + return Objects.equals(forecastTime, that.forecastTime) && + Objects.equals(weatherState, that.weatherState) && + Objects.equals(temperature, that.temperature) && + Objects.equals(atmosphericPressure, that.atmosphericPressure) && + Objects.equals(humidity, that.humidity) && + Objects.equals(wind, that.wind) && + Objects.equals(rain, that.rain) && + Objects.equals(snow, that.snow) && + Objects.equals(clouds, that.clouds); + } + + @Override + public int hashCode() { + return Objects.hash(forecastTime, weatherState, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds); + } + + @Override + public String toString() { + final StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Timestamp: "); + stringBuilder.append(forecastTime); + if (weatherState != null) { + stringBuilder.append(", Weather: "); + stringBuilder.append(weatherState.getDescription()); + } + if (temperature != null) { + stringBuilder.append(", Min temperature: "); + stringBuilder.append(temperature.getMin()); + stringBuilder.append(temperature.getUnit()); + stringBuilder.append(", Max temperature: "); + stringBuilder.append(temperature.getMax()); + stringBuilder.append(temperature.getUnit()); + } + if (atmosphericPressure != null) { + stringBuilder.append(", "); + stringBuilder.append(atmosphericPressure.getSeaLevelValue()); + stringBuilder.append(' '); + stringBuilder.append(atmosphericPressure.getUnit()); + } + if (clouds != null) { + stringBuilder.append(", "); + stringBuilder.append(clouds.toString()); + } + if (rain != null) { + stringBuilder.append(", Rain: "); + stringBuilder.append(rain.getLevel()); + stringBuilder.append(' '); + stringBuilder.append(rain.getUnit()); + } + if (snow != null) { + stringBuilder.append(", Snow: "); + stringBuilder.append(snow.getLevel()); + stringBuilder.append(' '); + stringBuilder.append(snow.getUnit()); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Forecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Forecast.java similarity index 96% rename from src/main/java/com/github/prominence/openweathermap/api/model/forecast/Forecast.java rename to src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Forecast.java index 093beb2..3c8a120 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Forecast.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Forecast.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; import java.util.List; import java.util.Objects; diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Location.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Location.java similarity index 91% rename from src/main/java/com/github/prominence/openweathermap/api/model/forecast/Location.java rename to src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Location.java index bec34d3..e45c629 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Location.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Location.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,9 +20,9 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import java.time.LocalDateTime; import java.time.ZoneOffset; @@ -40,7 +40,7 @@ public class Location { private LocalDateTime sunsetTime; private ZoneOffset zoneOffset; - private Coordinate coordinate; + private Coordinates coordinates; private Long population; @@ -162,16 +162,16 @@ public class Location { * Returns location coordinates. * @return location coordinates. */ - public Coordinate getCoordinate() { - return coordinate; + public Coordinates getCoordinate() { + return coordinates; } /** * Sets location coordinates. - * @param coordinate location coordinates + * @param coordinates location coordinates */ - public void setCoordinate(Coordinate coordinate) { - this.coordinate = coordinate; + public void setCoordinate(Coordinates coordinates) { + this.coordinates = coordinates; } /** @@ -201,20 +201,20 @@ public class Location { Objects.equals(sunriseTime, location.sunriseTime) && Objects.equals(sunsetTime, location.sunsetTime) && Objects.equals(zoneOffset, location.zoneOffset) && - Objects.equals(coordinate, location.coordinate) && + Objects.equals(coordinates, location.coordinates) && Objects.equals(population, location.population); } @Override public int hashCode() { - return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinate, population); + return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinates, population); } @Override public String toString() { final StringBuilder stringBuilder = new StringBuilder(); - if (coordinate != null) { - stringBuilder.append(coordinate.toString()); + if (coordinates != null) { + stringBuilder.append(coordinates.toString()); stringBuilder.append(". "); } stringBuilder.append("ID: "); diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Rain.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Rain.java similarity index 96% rename from src/main/java/com/github/prominence/openweathermap/api/model/forecast/Rain.java rename to src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Rain.java index 99719ae..d35f4d0 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Rain.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Rain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; import java.util.Objects; diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Snow.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Snow.java similarity index 96% rename from src/main/java/com/github/prominence/openweathermap/api/model/forecast/Snow.java rename to src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Snow.java index 4363b52..3b16fdf 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Snow.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Snow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; import java.util.Objects; diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/WeatherForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecast.java similarity index 97% rename from src/main/java/com/github/prominence/openweathermap/api/model/forecast/WeatherForecast.java rename to src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecast.java index e5c7a22..0b682bf 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/WeatherForecast.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecast.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,9 +20,10 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; import com.github.prominence.openweathermap.api.model.*; +import com.github.prominence.openweathermap.api.model.Wind; import java.time.LocalDateTime; import java.util.Objects; diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyForecast.java new file mode 100644 index 0000000..4b54e3f --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyForecast.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.hourly; + +import java.util.List; +import java.util.Objects; + +/** + * Represents information about forecast for different timestamps. + */ +public class HourlyForecast { + private Location location; + private List weatherForecasts; + + /** + * Returns location information. + * @return location + */ + public Location getLocation() { + return location; + } + + /** + * Sets forecast location. + * @param location forecast location + */ + public void setLocation(Location location) { + this.location = location; + } + + /** + * Returns list of weather forecasts for different timestamps. + * @return list of forecast-per-timestamp information. + */ + public List getWeatherForecasts() { + return weatherForecasts; + } + + /** + * Sets list of weather forecasts for different timestamps. + * @param weatherForecasts list of forecast information + */ + public void setWeatherForecasts(List weatherForecasts) { + this.weatherForecasts = weatherForecasts; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + HourlyForecast hourlyForecast = (HourlyForecast) o; + return Objects.equals(location, hourlyForecast.location) && Objects.equals(weatherForecasts, hourlyForecast.weatherForecasts); + } + + @Override + public int hashCode() { + return Objects.hash(location, weatherForecasts); + } + + @Override + public String toString() { + return "A forecast for " + location.getName() + " with " + weatherForecasts.size() + " timestamps."; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Location.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Location.java new file mode 100644 index 0000000..2a3a738 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Location.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.hourly; + +import com.github.prominence.openweathermap.api.model.Coordinates; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Objects; + +/** + * Represents location information. + */ +public class Location { + private int id; + private String name; + private String countryCode; + + private LocalDateTime sunriseTime; + private LocalDateTime sunsetTime; + private ZoneOffset zoneOffset; + + private Coordinates coordinates; + + private Location(int id, String name) { + this.id = id; + this.name = name; + } + + /** + * Creates {@link Location} object with correctness check. + * @param id location id + * @param name location name + * @return location object + */ + public static Location withValues(int id, String name) { + if (name == null) { + throw new IllegalArgumentException("Name must be set."); + } + return new Location(id, name); + } + + /** + * Returns ID. + * @return location ID + */ + public int getId() { + return id; + } + + /** + * Sets location ID. + * @param id location id + */ + public void setId(int id) { + this.id = id; + } + + /** + * Returns location name. + * @return location name + */ + public String getName() { + return name; + } + + /** + * Sets location name. + * @param name location name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Returns country code. + * @return location country code + */ + public String getCountryCode() { + return countryCode; + } + + /** + * Sets location country code. + * @param countryCode location country code + */ + public void setCountryCode(String countryCode) { + this.countryCode = countryCode; + } + + /** + * Returns location sunrise time. + * @return sunrise time + */ + public LocalDateTime getSunriseTime() { + return sunriseTime; + } + + /** + * Sets location sunrise time. + * @param sunriseTime sunrise time + */ + public void setSunriseTime(LocalDateTime sunriseTime) { + this.sunriseTime = sunriseTime; + } + + /** + * Returns location sunset time. + * @return sunset time + */ + public LocalDateTime getSunsetTime() { + return sunsetTime; + } + + /** + * Sets location sunset time. + * @param sunsetTime sunset time + */ + public void setSunsetTime(LocalDateTime sunsetTime) { + this.sunsetTime = sunsetTime; + } + + /** + * Returns location timezone offset. + * @return timezone offset + */ + public ZoneOffset getZoneOffset() { + return zoneOffset; + } + + /** + * Sets location timezone offset. + * @param zoneOffset timezone offset + */ + public void setZoneOffset(ZoneOffset zoneOffset) { + this.zoneOffset = zoneOffset; + } + + /** + * Returns location coordinates. + * @return location coordinates. + */ + public Coordinates getCoordinate() { + return coordinates; + } + + /** + * Sets location coordinates. + * @param coordinates location coordinates + */ + public void setCoordinate(Coordinates coordinates) { + this.coordinates = coordinates; + } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Location)) return false; + Location location = (Location) o; + return id == location.id && + Objects.equals(name, location.name) && + Objects.equals(countryCode, location.countryCode) && + Objects.equals(sunriseTime, location.sunriseTime) && + Objects.equals(sunsetTime, location.sunsetTime) && + Objects.equals(zoneOffset, location.zoneOffset) && + Objects.equals(coordinates, location.coordinates); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinates); + } + + @Override + public String toString() { + final StringBuilder stringBuilder = new StringBuilder(); + if (coordinates != null) { + stringBuilder.append(coordinates.toString()); + stringBuilder.append(". "); + } + stringBuilder.append("ID: "); + stringBuilder.append(id); + stringBuilder.append(", Name: "); + stringBuilder.append(name); + if (countryCode != null) { + stringBuilder.append('('); + stringBuilder.append(countryCode); + stringBuilder.append(')'); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Rain.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Rain.java new file mode 100644 index 0000000..6482f3f --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Rain.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.hourly; + +import java.util.Objects; + +/** + * Represents rain information. + */ +public class Rain { + private static final String DEFAULT_UNIT = "mm"; + + private double oneHourLevel; + + private Rain(double oneHourLevel) { + this.oneHourLevel = oneHourLevel; + } + + /** + * Creates {@link Rain} object with correctness check. + * @param oneHourLevel 1-hour rain level value + * @return rain object. + */ + public static Rain withOneHourLevelValue(double oneHourLevel) { + if (oneHourLevel < 0) { + throw new IllegalArgumentException("Rain level value cannot be negative."); + } + return new Rain(oneHourLevel); + } + + /** + * Returns 1-hour rain level value. + * @return 1-hour rain level value + */ + public double getOneHourLevel() { + return oneHourLevel; + } + + /** + * Sets 1-hour rain level value with correctness check. + * @param oneHourLevel 1-hour rain level value + */ + public void setOneHourLevel(double oneHourLevel) { + if (oneHourLevel < 0) { + throw new IllegalArgumentException("Rain level value cannot be negative."); + } + this.oneHourLevel = oneHourLevel; + } + + /** + * Returns rain level unit of measure. Currently, is constant. + * @return rain level unit of measure + */ + public String getUnit() { + return DEFAULT_UNIT; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Rain rain = (Rain) o; + return Double.compare(rain.oneHourLevel, oneHourLevel) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(oneHourLevel); + } + + @Override + public String toString() { + return "1-hour rain level: " + + oneHourLevel + ' ' + + getUnit(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Snow.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Snow.java new file mode 100644 index 0000000..4451474 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Snow.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.hourly; + +import java.util.Objects; + +/** + * Represents snow information. + */ +public class Snow { + private static final String DEFAULT_UNIT = "mm"; + + private double oneHourLevel; + + private Snow(double oneHourLevel) { + this.oneHourLevel = oneHourLevel; + } + + /** + * Creates {@link Snow} object with correctness check. + * @param oneHourLevel 1-hour snow level value + * @return snow object. + */ + public static Snow withOneHourLevelValue(double oneHourLevel) { + if (oneHourLevel < 0) { + throw new IllegalArgumentException("Snow level value cannot be negative."); + } + return new Snow(oneHourLevel); + } + + /** + * Returns 1-hour snow level value. + * @return 1-hour snow level value + */ + public double getOneHourLevel() { + return oneHourLevel; + } + + /** + * Sets 1-hour snow level value with correctness check. + * @param oneHourLevel 1-hour snow level value + */ + public void setOneHourLevel(double oneHourLevel) { + if (oneHourLevel < 0) { + throw new IllegalArgumentException("Snow level value cannot be negative."); + } + this.oneHourLevel = oneHourLevel; + } + + /** + * Returns snow level unit of measure. Currently, is constant. + * @return snow level unit of measure + */ + public String getUnit() { + return DEFAULT_UNIT; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Snow snow = (Snow) o; + return Double.compare(snow.oneHourLevel, oneHourLevel) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(oneHourLevel); + } + + @Override + public String toString() { + return "1-hour snow level: " + + oneHourLevel + ' ' + + getUnit(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/WeatherForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/WeatherForecast.java new file mode 100644 index 0000000..eaa1d63 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/WeatherForecast.java @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.forecast.hourly; + +import com.github.prominence.openweathermap.api.model.*; +import com.github.prominence.openweathermap.api.model.Wind; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + +/** + * Represents weather forecast information for a particular timestamp. + */ +public class WeatherForecast { + private LocalDateTime forecastTime; + + private List weatherStates; + private Temperature temperature; + private AtmosphericPressure atmosphericPressure; + private Humidity humidity; + + private Wind wind; + private Rain rain; + private Snow snow; + private Clouds clouds; + + private String forecastTimeISO; + private DayTime dayTime; + + private Integer averageVisibilityInMetres; + + private Double probabilityOfPrecipitation; + + /** + * Gets forecast time. + * + * @return the forecast time + */ + public LocalDateTime getForecastTime() { + return forecastTime; + } + + /** + * Sets forecast time. + * + * @param forecastTime the forecast time + */ + public void setForecastTime(LocalDateTime forecastTime) { + this.forecastTime = forecastTime; + } + + /** + * Gets weather state. + * + * @return the weather state + */ + public List getWeatherStates() { + return weatherStates; + } + + /** + * Sets weather state. + * + * @param weatherStates the weather state + */ + public void setWeatherStates(List weatherStates) { + this.weatherStates = weatherStates; + } + + /** + * Gets temperature. + * + * @return the temperature + */ + public Temperature getTemperature() { + return temperature; + } + + /** + * Sets temperature. + * + * @param temperature the temperature + */ + public void setTemperature(Temperature temperature) { + this.temperature = temperature; + } + + /** + * Gets atmospheric pressure. + * + * @return the atmospheric pressure + */ + public AtmosphericPressure getAtmosphericPressure() { + return atmosphericPressure; + } + + /** + * Sets atmospheric pressure. + * + * @param atmosphericPressure the atmospheric pressure + */ + public void setAtmosphericPressure(AtmosphericPressure atmosphericPressure) { + this.atmosphericPressure = atmosphericPressure; + } + + /** + * Gets humidity. + * + * @return the humidity + */ + public Humidity getHumidity() { + return humidity; + } + + /** + * Sets humidity. + * + * @param humidity the humidity + */ + public void setHumidity(Humidity humidity) { + this.humidity = humidity; + } + + /** + * Gets wind. + * + * @return the wind + */ + public Wind getWind() { + return wind; + } + + /** + * Sets wind. + * + * @param wind the wind + */ + public void setWind(Wind wind) { + this.wind = wind; + } + + /** + * Gets rain. + * + * @return the rain + */ + public Rain getRain() { + return rain; + } + + /** + * Sets rain. + * + * @param rain the rain + */ + public void setRain(Rain rain) { + this.rain = rain; + } + + /** + * Gets snow. + * + * @return the snow + */ + public Snow getSnow() { + return snow; + } + + /** + * Sets snow. + * + * @param snow the snow + */ + public void setSnow(Snow snow) { + this.snow = snow; + } + + /** + * Gets clouds. + * + * @return the clouds + */ + public Clouds getClouds() { + return clouds; + } + + /** + * Sets clouds. + * + * @param clouds the clouds + */ + public void setClouds(Clouds clouds) { + this.clouds = clouds; + } + + /** + * Gets forecast time iso. + * + * @return the forecast time iso + */ + public String getForecastTimeISO() { + return forecastTimeISO; + } + + /** + * Sets forecast time iso. + * + * @param forecastTimeISO the forecast time iso + */ + public void setForecastTimeISO(String forecastTimeISO) { + this.forecastTimeISO = forecastTimeISO; + } + + /** + * Gets day time. + * + * @return the day time + */ + public DayTime getDayTime() { + return dayTime; + } + + /** + * Sets day time. + * + * @param dayTime the day time + */ + public void setDayTime(DayTime dayTime) { + this.dayTime = dayTime; + } + + public Integer getAverageVisibilityInMetres() { + return averageVisibilityInMetres; + } + + public void setAverageVisibilityInMetres(Integer averageVisibilityInMetres) { + this.averageVisibilityInMetres = averageVisibilityInMetres; + } + + public Double getProbabilityOfPrecipitation() { + return probabilityOfPrecipitation; + } + + public void setProbabilityOfPrecipitation(Double probabilityOfPrecipitation) { + this.probabilityOfPrecipitation = probabilityOfPrecipitation; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WeatherForecast that = (WeatherForecast) o; + return Objects.equals(forecastTime, that.forecastTime) && + Objects.equals(weatherStates, that.weatherStates) && + Objects.equals(temperature, that.temperature) && + Objects.equals(atmosphericPressure, that.atmosphericPressure) && + Objects.equals(humidity, that.humidity) && + Objects.equals(wind, that.wind) && + Objects.equals(rain, that.rain) && + Objects.equals(snow, that.snow) && + Objects.equals(clouds, that.clouds) && + Objects.equals(forecastTimeISO, that.forecastTimeISO) && + dayTime == that.dayTime && + Objects.equals(averageVisibilityInMetres, that.averageVisibilityInMetres) && + Objects.equals(probabilityOfPrecipitation, that.probabilityOfPrecipitation); + } + + @Override + public int hashCode() { + return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, forecastTimeISO, dayTime, averageVisibilityInMetres, probabilityOfPrecipitation); + } + + @Override + public String toString() { + final StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Timestamp: "); + stringBuilder.append(forecastTimeISO); + if (weatherStates != null && weatherStates.size() > 0) { + stringBuilder.append(", Weather: "); + stringBuilder.append(weatherStates.get(0).getDescription()); + } + if (temperature != null) { + stringBuilder.append(", "); + stringBuilder.append(temperature.getValue()); + stringBuilder.append(' '); + stringBuilder.append(temperature.getUnit()); + } + if (atmosphericPressure != null) { + stringBuilder.append(", "); + stringBuilder.append(atmosphericPressure.getValue()); + stringBuilder.append(' '); + stringBuilder.append(atmosphericPressure.getUnit()); + } + if (clouds != null) { + stringBuilder.append(", "); + stringBuilder.append(clouds); + } + if (rain != null) { + stringBuilder.append(", Rain: "); + stringBuilder.append(rain.getOneHourLevel()); + stringBuilder.append(' '); + stringBuilder.append(rain.getUnit()); + } + if (snow != null) { + stringBuilder.append(", Snow: "); + stringBuilder.append(snow.getOneHourLevel()); + stringBuilder.append(' '); + stringBuilder.append(snow.getUnit()); + } + if (averageVisibilityInMetres != null) { + stringBuilder.append(", Average visibility: "); + stringBuilder.append(averageVisibilityInMetres); + stringBuilder.append(" metres"); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/GeocodingRecord.java b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/GeocodingRecord.java new file mode 100644 index 0000000..ebaa064 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/GeocodingRecord.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.geocoding; + +import com.github.prominence.openweathermap.api.model.Coordinates; + +import java.util.Map; +import java.util.Objects; + +public final class GeocodingRecord { + private final String name; + private final Map localNames; + private final Coordinates coordinates; + private final String countryCode; + + public GeocodingRecord(String name, Map localNames, Coordinates coordinates, String countryCode) { + this.name = name; + this.localNames = localNames; + this.coordinates = coordinates; + this.countryCode = countryCode; + } + + public String getName() { + return name; + } + + public Map getLocalNames() { + return localNames; + } + + public Coordinates getCoordinates() { + return coordinates; + } + + public String getCountryCode() { + return countryCode; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (GeocodingRecord) obj; + return Objects.equals(this.name, that.name) && + Objects.equals(this.localNames, that.localNames) && + Objects.equals(this.coordinates, that.coordinates) && + Objects.equals(this.countryCode, that.countryCode); + } + + @Override + public int hashCode() { + return Objects.hash(name, localNames, coordinates, countryCode); + } + + @Override + public String toString() { + return "GeocodingRecord[" + + "name=" + name + ", " + + "localNames=" + localNames + ", " + + "coordinates=" + coordinates + ", " + + "countryCode=" + countryCode + ']'; + } + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocodingRecord.java b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocodingRecord.java new file mode 100644 index 0000000..a003c43 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocodingRecord.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.model.geocoding; + +import com.github.prominence.openweathermap.api.model.Coordinates; + +import java.util.Objects; + +public final class ZipCodeGeocodingRecord { + private final String zip; + private final String name; + private final Coordinates coordinates; + private final String countryCode; + + public ZipCodeGeocodingRecord(String zip, String name, Coordinates coordinates, String countryCode) { + this.zip = zip; + this.name = name; + this.coordinates = coordinates; + this.countryCode = countryCode; + } + + public String getZip() { + return zip; + } + + public String getName() { + return name; + } + + public Coordinates getCoordinates() { + return coordinates; + } + + public String getCountryCode() { + return countryCode; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (ZipCodeGeocodingRecord) obj; + return Objects.equals(this.zip, that.zip) && + Objects.equals(this.name, that.name) && + Objects.equals(this.coordinates, that.coordinates) && + Objects.equals(this.countryCode, that.countryCode); + } + + @Override + public int hashCode() { + return Objects.hash(zip, name, coordinates, countryCode); + } + + @Override + public String toString() { + return "ZipCodeGeocodingRecord[" + + "zip=" + zip + ", " + + "name=" + name + ", " + + "coordinates=" + coordinates + ", " + + "countryCode=" + countryCode + ']'; + } + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Current.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Current.java index f619512..0acbec9 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Current.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Current.java @@ -25,8 +25,10 @@ package com.github.prominence.openweathermap.api.model.onecall; import com.github.prominence.openweathermap.api.model.Clouds; import com.github.prominence.openweathermap.api.model.Humidity; import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.Wind; import java.time.LocalDateTime; +import java.util.List; import java.util.Objects; /** @@ -37,7 +39,7 @@ public class Current { protected LocalDateTime sunriseTime; protected LocalDateTime sunsetTime; - protected WeatherState weatherState; + protected List weatherStates; protected Temperature temperature; protected AtmosphericPressure atmosphericPressure; protected Humidity humidity; @@ -107,17 +109,17 @@ public class Current { * * @return the weather state */ - public WeatherState getWeatherState() { - return weatherState; + public List getWeatherStates() { + return weatherStates; } /** * Sets weather state. * - * @param weatherState the weather state + * @param weatherStates the weather state */ - public void setWeatherState(WeatherState weatherState) { - this.weatherState = weatherState; + public void setWeatherStates(List weatherStates) { + this.weatherStates = weatherStates; } /** @@ -296,7 +298,7 @@ public class Current { return Objects.equals(forecastTime, current.forecastTime) && Objects.equals(sunriseTime, current.sunriseTime) && Objects.equals(sunsetTime, current.sunsetTime) && - Objects.equals(weatherState, current.weatherState) && + Objects.equals(weatherStates, current.weatherStates) && Objects.equals(temperature, current.temperature) && Objects.equals(atmosphericPressure, current.atmosphericPressure) && Objects.equals(humidity, current.humidity) && @@ -310,7 +312,7 @@ public class Current { @Override public int hashCode() { - return Objects.hash(forecastTime, sunriseTime, sunsetTime, weatherState, temperature, atmosphericPressure, humidity, clouds, uvIndex, visibilityInMetres, wind, rain, snow); + return Objects.hash(forecastTime, sunriseTime, sunsetTime, weatherStates, temperature, atmosphericPressure, humidity, clouds, uvIndex, visibilityInMetres, wind, rain, snow); } @Override diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Wind.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Wind.java deleted file mode 100644 index c2ec55a..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Wind.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2021 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 com.github.prominence.openweathermap.api.model.onecall; - -import java.util.Objects; - -/** - * The type Wind. - */ -public class Wind { - private double speed; - private Double degrees; - private Double gust; - private String unit; - - private Wind() { - } - - /** - * Creates {@link Wind} object with correctness check. - * @param speed the speed - * @param unit the unitSystem - * @return wind object - */ - public static Wind withValue(double speed, String unit) { - final Wind wind = new Wind(); - wind.setSpeed(speed); - wind.setUnit(unit); - return wind; - } - - /** - * Gets speed. - * - * @return the speed - */ - public double getSpeed() { - return speed; - } - - /** - * Sets speed. - * - * @param speed the speed - */ - public void setSpeed(double speed) { - if (speed < 0) { - throw new IllegalArgumentException("Wind speed value must be in positive or zero."); - } - this.speed = speed; - } - - /** - * Gets gust value. - * @return the gust - */ - public Double getGust() { - return gust; - } - - /** - * Sets gust value. - * @param gust the gust. - */ - public void setGust(double gust) { - if (gust < 0) { - throw new IllegalArgumentException("Gust value must be positive or zero."); - } - this.gust = gust; - } - - /** - * Gets degrees. - * - * @return the degrees - */ - public Double getDegrees() { - return degrees; - } - - /** - * Sets degrees. - * - * @param degrees the degrees - */ - public void setDegrees(double degrees) { - if (degrees < 0 || degrees > 360) { - throw new IllegalArgumentException("Wind direction value must be in [0, 360] range."); - } - this.degrees = degrees; - } - - /** - * Gets unitSystem. - * - * @return the unitSystem - */ - public String getUnit() { - return unit; - } - - /** - * Sets unitSystem. - * - * @param unit the unitSystem - */ - public void setUnit(String unit) { - if (unit == null) { - throw new IllegalArgumentException("Unit must be set."); - } - this.unit = unit; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Wind)) return false; - Wind wind = (Wind) o; - return Double.compare(wind.speed, speed) == 0 && - Objects.equals(degrees, wind.degrees) && - Objects.equals(gust, wind.gust) && - Objects.equals(unit, wind.unit); - } - - @Override - public int hashCode() { - return Objects.hash(speed, degrees, gust, unit); - } - - @Override - public String toString() { - String output = "Wind speed: " + speed + " " + unit + - ", degrees: " + degrees; - if (gust != null) { - output += ", Gust: " + gust + " " + unit; - } - return output; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Alert.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Alert.java index 58e22e6..3b5aa81 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Alert.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Alert.java @@ -23,6 +23,7 @@ package com.github.prominence.openweathermap.api.model.onecall.current; import java.time.LocalDateTime; +import java.util.List; import java.util.Objects; /** @@ -35,6 +36,8 @@ public class Alert { private LocalDateTime endTime; private String description; + private List tags; + /** * Instantiates a new Alert. */ @@ -49,13 +52,15 @@ public class Alert { * @param startTime the start time * @param endTime the end time * @param description the description + * @param tags the tags */ - public Alert(String senderName, String eventName, LocalDateTime startTime, LocalDateTime endTime, String description) { + public Alert(String senderName, String eventName, LocalDateTime startTime, LocalDateTime endTime, String description, List tags) { this.senderName = senderName; this.eventName = eventName; this.startTime = startTime; this.endTime = endTime; this.description = description; + this.tags = tags; } /** @@ -148,6 +153,14 @@ public class Alert { this.description = description; } + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -157,12 +170,13 @@ public class Alert { Objects.equals(eventName, alert.eventName) && Objects.equals(startTime, alert.startTime) && Objects.equals(endTime, alert.endTime) && - Objects.equals(description, alert.description); + Objects.equals(description, alert.description) && + Objects.equals(tags, alert.tags); } @Override public int hashCode() { - return Objects.hash(senderName, eventName, startTime, endTime, description); + return Objects.hash(senderName, eventName, startTime, endTime, description, tags); } @Override diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherData.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherData.java index 836852c..3057dd8 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherData.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherData.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.model.onecall.current; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.model.onecall.Current; import java.time.ZoneId; @@ -34,7 +34,7 @@ import java.util.Objects; * The type Current weather data. */ public class CurrentWeatherData { - private Coordinate coordinate; + private Coordinates coordinates; private ZoneId timezone; private ZoneOffset timezoneOffset; @@ -49,17 +49,17 @@ public class CurrentWeatherData { * * @return the coordinate */ - public Coordinate getCoordinate() { - return coordinate; + public Coordinates getCoordinate() { + return coordinates; } /** * Sets coordinate. * - * @param coordinate the coordinate + * @param coordinates the coordinate */ - public void setCoordinate(Coordinate coordinate) { - this.coordinate = coordinate; + public void setCoordinate(Coordinates coordinates) { + this.coordinates = coordinates; } /** @@ -193,7 +193,7 @@ public class CurrentWeatherData { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CurrentWeatherData that = (CurrentWeatherData) o; - return Objects.equals(coordinate, that.coordinate) && + return Objects.equals(coordinates, that.coordinates) && Objects.equals(timezone, that.timezone) && Objects.equals(timezoneOffset, that.timezoneOffset) && Objects.equals(current, that.current) && @@ -205,11 +205,11 @@ public class CurrentWeatherData { @Override public int hashCode() { - return Objects.hash(coordinate, timezone, timezoneOffset, current, minutelyList, hourlyList, dailyList, alerts); + return Objects.hash(coordinates, timezone, timezoneOffset, current, minutelyList, hourlyList, dailyList, alerts); } @Override public String toString() { - return "Current weather data for " + coordinate + "."; + return "Current weather data for " + coordinates + "."; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Daily.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Daily.java index e2f8b45..b3232bc 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Daily.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Daily.java @@ -26,9 +26,10 @@ import com.github.prominence.openweathermap.api.model.Clouds; import com.github.prominence.openweathermap.api.model.Humidity; import com.github.prominence.openweathermap.api.model.WeatherState; import com.github.prominence.openweathermap.api.model.onecall.AtmosphericPressure; -import com.github.prominence.openweathermap.api.model.onecall.Wind; +import com.github.prominence.openweathermap.api.model.Wind; import java.time.LocalDateTime; +import java.util.List; import java.util.Objects; /** @@ -43,7 +44,7 @@ public class Daily { private LocalDateTime moonsetTime; private MoonPhase moonPhase; - private WeatherState weatherState; + private List weatherStates; private DailyTemperature temperature; private AtmosphericPressure atmosphericPressure; private Humidity humidity; @@ -167,17 +168,17 @@ public class Daily { * * @return the weather state */ - public WeatherState getWeatherState() { - return weatherState; + public List getWeatherStates() { + return weatherStates; } /** * Sets weather state. * - * @param weatherState the weather state + * @param weatherStates the weather state */ - public void setWeatherState(WeatherState weatherState) { - this.weatherState = weatherState; + public void setWeatherStates(List weatherStates) { + this.weatherStates = weatherStates; } /** @@ -372,7 +373,7 @@ public class Daily { Objects.equals(moonriseTime, daily.moonriseTime) && Objects.equals(moonsetTime, daily.moonsetTime) && Objects.equals(moonPhase, daily.moonPhase) && - Objects.equals(weatherState, daily.weatherState) && + Objects.equals(weatherStates, daily.weatherStates) && Objects.equals(temperature, daily.temperature) && Objects.equals(atmosphericPressure, daily.atmosphericPressure) && Objects.equals(humidity, daily.humidity) && @@ -386,7 +387,7 @@ public class Daily { @Override public int hashCode() { - return Objects.hash(forecastTime, sunriseTime, sunsetTime, moonriseTime, moonsetTime, moonPhase, weatherState, temperature, atmosphericPressure, humidity, wind, clouds, uvIndex, probabilityOfPrecipitation, rain, snow); + return Objects.hash(forecastTime, sunriseTime, sunsetTime, moonriseTime, moonsetTime, moonPhase, weatherStates, temperature, atmosphericPressure, humidity, wind, clouds, uvIndex, probabilityOfPrecipitation, rain, snow); } @Override @@ -395,9 +396,9 @@ public class Daily { stringBuilder.append("Weather on "); stringBuilder.append(forecastTime); stringBuilder.append("."); - if (weatherState != null) { + if (weatherStates != null && weatherStates.size() > 0) { stringBuilder.append(" Weather: "); - stringBuilder.append(weatherState.getDescription()); + stringBuilder.append(weatherStates.get(0).getDescription()); stringBuilder.append('.'); } if (temperature != null) { diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Hourly.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Hourly.java index 6833db1..a587071 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Hourly.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Hourly.java @@ -25,9 +25,11 @@ package com.github.prominence.openweathermap.api.model.onecall.current; import com.github.prominence.openweathermap.api.model.Clouds; import com.github.prominence.openweathermap.api.model.Humidity; import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.Wind; import com.github.prominence.openweathermap.api.model.onecall.*; import java.time.LocalDateTime; +import java.util.List; import java.util.Objects; /** @@ -36,7 +38,7 @@ import java.util.Objects; public class Hourly { private LocalDateTime forecastTime; - private WeatherState weatherState; + private List weatherStates; private Temperature temperature; private AtmosphericPressure atmosphericPressure; private Humidity humidity; @@ -71,17 +73,17 @@ public class Hourly { * * @return the weather state */ - public WeatherState getWeatherState() { - return weatherState; + public List getWeatherStates() { + return weatherStates; } /** * Sets weather state. * - * @param weatherState the weather state + * @param weatherStates the weather state */ - public void setWeatherState(WeatherState weatherState) { - this.weatherState = weatherState; + public void setWeatherStates(List weatherStates) { + this.weatherStates = weatherStates; } /** @@ -286,7 +288,7 @@ public class Hourly { if (o == null || getClass() != o.getClass()) return false; Hourly hourly = (Hourly) o; return Objects.equals(forecastTime, hourly.forecastTime) && - Objects.equals(weatherState, hourly.weatherState) && + Objects.equals(weatherStates, hourly.weatherStates) && Objects.equals(temperature, hourly.temperature) && Objects.equals(atmosphericPressure, hourly.atmosphericPressure) && Objects.equals(humidity, hourly.humidity) && @@ -301,7 +303,7 @@ public class Hourly { @Override public int hashCode() { - return Objects.hash(forecastTime, weatherState, temperature, atmosphericPressure, humidity, uvIndex, clouds, visibilityInMetres, wind, probabilityOfPrecipitation, rain, snow); + return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, uvIndex, clouds, visibilityInMetres, wind, probabilityOfPrecipitation, rain, snow); } @Override diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherData.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherData.java index d5da701..5fa7f6f 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherData.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherData.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.model.onecall.historical; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import java.time.ZoneId; import java.time.ZoneOffset; @@ -33,7 +33,7 @@ import java.util.Objects; * The type Historical weather data. */ public class HistoricalWeatherData { - private Coordinate coordinate; + private Coordinates coordinates; private ZoneId timezone; private ZoneOffset timezoneOffset; @@ -45,17 +45,17 @@ public class HistoricalWeatherData { * * @return the coordinate */ - public Coordinate getCoordinate() { - return coordinate; + public Coordinates getCoordinate() { + return coordinates; } /** * Sets coordinate. * - * @param coordinate the coordinate + * @param coordinates the coordinate */ - public void setCoordinate(Coordinate coordinate) { - this.coordinate = coordinate; + public void setCoordinate(Coordinates coordinates) { + this.coordinates = coordinates; } /** @@ -135,7 +135,7 @@ public class HistoricalWeatherData { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; HistoricalWeatherData that = (HistoricalWeatherData) o; - return Objects.equals(coordinate, that.coordinate) && + return Objects.equals(coordinates, that.coordinates) && Objects.equals(timezone, that.timezone) && Objects.equals(timezoneOffset, that.timezoneOffset) && Objects.equals(historicalWeather, that.historicalWeather) && @@ -144,11 +144,11 @@ public class HistoricalWeatherData { @Override public int hashCode() { - return Objects.hash(coordinate, timezone, timezoneOffset, historicalWeather, hourlyList); + return Objects.hash(coordinates, timezone, timezoneOffset, historicalWeather, hourlyList); } @Override public String toString() { - return "Historical weather data for " + coordinate + "."; + return "Historical weather data for " + coordinates + "."; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistorical.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistorical.java index 6b7ec68..e59e8d1 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistorical.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistorical.java @@ -25,9 +25,11 @@ package com.github.prominence.openweathermap.api.model.onecall.historical; import com.github.prominence.openweathermap.api.model.Clouds; import com.github.prominence.openweathermap.api.model.Humidity; import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.Wind; import com.github.prominence.openweathermap.api.model.onecall.*; import java.time.LocalDateTime; +import java.util.List; import java.util.Objects; /** @@ -36,7 +38,7 @@ import java.util.Objects; public class HourlyHistorical { private LocalDateTime forecastTime; - private WeatherState weatherState; + private List weatherStates; private Temperature temperature; private AtmosphericPressure atmosphericPressure; private Humidity humidity; @@ -69,17 +71,17 @@ public class HourlyHistorical { * * @return the weather state */ - public WeatherState getWeatherState() { - return weatherState; + public List getWeatherStates() { + return weatherStates; } /** * Sets weather state. * - * @param weatherState the weather state + * @param weatherStates the weather state */ - public void setWeatherState(WeatherState weatherState) { - this.weatherState = weatherState; + public void setWeatherStates(List weatherStates) { + this.weatherStates = weatherStates; } /** @@ -232,7 +234,7 @@ public class HourlyHistorical { if (o == null || getClass() != o.getClass()) return false; HourlyHistorical that = (HourlyHistorical) o; return Objects.equals(forecastTime, that.forecastTime) && - Objects.equals(weatherState, that.weatherState) && + Objects.equals(weatherStates, that.weatherStates) && Objects.equals(temperature, that.temperature) && Objects.equals(atmosphericPressure, that.atmosphericPressure) && Objects.equals(humidity, that.humidity) && @@ -245,7 +247,7 @@ public class HourlyHistorical { @Override public int hashCode() { - return Objects.hash(forecastTime, weatherState, temperature, atmosphericPressure, humidity, clouds, visibilityInMetres, wind, rain, snow); + return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, clouds, visibilityInMetres, wind, rain, snow); } @Override diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Location.java b/src/main/java/com/github/prominence/openweathermap/api/model/weather/Location.java index 4390e36..fae0cd7 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Location.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/weather/Location.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.model.weather; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import java.time.LocalDateTime; import java.time.ZoneOffset; @@ -40,7 +40,7 @@ public class Location { private LocalDateTime sunsetTime; private ZoneOffset zoneOffset; - private Coordinate coordinate; + private Coordinates coordinates; private Location(int id, String name) { this.id = id; @@ -49,7 +49,8 @@ public class Location { /** * Creates {@link Location} object with correctness check. - * @param id location id + * + * @param id location id * @param name location name * @return location object */ @@ -62,6 +63,7 @@ public class Location { /** * Returns ID. + * * @return location ID */ public int getId() { @@ -70,6 +72,7 @@ public class Location { /** * Sets location ID. + * * @param id location id */ public void setId(int id) { @@ -78,6 +81,7 @@ public class Location { /** * Returns location name. + * * @return location name */ public String getName() { @@ -86,6 +90,7 @@ public class Location { /** * Sets location name. + * * @param name location name */ public void setName(String name) { @@ -94,6 +99,7 @@ public class Location { /** * Returns country code. + * * @return location country code */ public String getCountryCode() { @@ -102,6 +108,7 @@ public class Location { /** * Sets location country code. + * * @param countryCode location country code */ public void setCountryCode(String countryCode) { @@ -110,6 +117,7 @@ public class Location { /** * Returns location sunrise time. + * * @return sunrise time */ public LocalDateTime getSunriseTime() { @@ -118,6 +126,7 @@ public class Location { /** * Sets location sunrise time. + * * @param sunriseTime sunrise time */ public void setSunriseTime(LocalDateTime sunriseTime) { @@ -126,6 +135,7 @@ public class Location { /** * Returns location sunset time. + * * @return sunset time */ public LocalDateTime getSunsetTime() { @@ -134,6 +144,7 @@ public class Location { /** * Sets location sunset time. + * * @param sunsetTime sunset time */ public void setSunsetTime(LocalDateTime sunsetTime) { @@ -142,6 +153,7 @@ public class Location { /** * Returns location timezone offset. + * * @return timezone offset */ public ZoneOffset getZoneOffset() { @@ -150,6 +162,7 @@ public class Location { /** * Sets location timezone offset. + * * @param zoneOffset timezone offset */ public void setZoneOffset(ZoneOffset zoneOffset) { @@ -158,18 +171,20 @@ public class Location { /** * Returns location coordinates. + * * @return location coordinates. */ - public Coordinate getCoordinate() { - return coordinate; + public Coordinates getCoordinate() { + return coordinates; } /** * Sets location coordinates. - * @param coordinate location coordinates + * + * @param coordinates location coordinates */ - public void setCoordinate(Coordinate coordinate) { - this.coordinate = coordinate; + public void setCoordinate(Coordinates coordinates) { + this.coordinates = coordinates; } @Override @@ -183,19 +198,19 @@ public class Location { Objects.equals(sunriseTime, location.sunriseTime) && Objects.equals(sunsetTime, location.sunsetTime) && Objects.equals(zoneOffset, location.zoneOffset) && - Objects.equals(coordinate, location.coordinate); + Objects.equals(coordinates, location.coordinates); } @Override public int hashCode() { - return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinate); + return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinates); } @Override public String toString() { final StringBuilder stringBuilder = new StringBuilder(); - if (coordinate != null) { - stringBuilder.append(coordinate.toString()); + if (coordinates != null) { + stringBuilder.append(coordinates.toString()); stringBuilder.append(". "); } stringBuilder.append("ID: "); diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Weather.java b/src/main/java/com/github/prominence/openweathermap/api/model/weather/Weather.java index 0c3e231..7503b2c 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Weather.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/weather/Weather.java @@ -25,6 +25,7 @@ package com.github.prominence.openweathermap.api.model.weather; import com.github.prominence.openweathermap.api.model.*; import java.time.LocalDateTime; +import java.util.List; import java.util.Objects; /** @@ -33,7 +34,7 @@ import java.util.Objects; public class Weather { private LocalDateTime calculationTime; - private WeatherState weatherState; + private List weatherStates; private Temperature temperature; private AtmosphericPressure atmosphericPressure; private Humidity humidity; @@ -45,6 +46,8 @@ public class Weather { private Location location; + private String base; + /** * Gets calculated on. * @@ -68,17 +71,17 @@ public class Weather { * * @return the weather state */ - public WeatherState getWeatherState() { - return weatherState; + public List getWeatherStates() { + return weatherStates; } /** * Sets weather state. * - * @param weatherState the weather state + * @param weatherStates the weather state */ - public void setWeatherState(WeatherState weatherState) { - this.weatherState = weatherState; + public void setWeatherStates(List weatherStates) { + this.weatherStates = weatherStates; } /** @@ -225,13 +228,20 @@ public class Weather { this.location = location; } + public String getBase() { + return base; + } + + public void setBase(String base) { + this.base = base; + } + @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof Weather)) return false; - Weather weather = (Weather) o; + if (!(o instanceof Weather weather)) return false; return Objects.equals(calculationTime, weather.calculationTime) && - Objects.equals(weatherState, weather.weatherState) && + Objects.equals(weatherStates, weather.weatherStates) && Objects.equals(temperature, weather.temperature) && Objects.equals(atmosphericPressure, weather.atmosphericPressure) && Objects.equals(humidity, weather.humidity) && @@ -239,12 +249,13 @@ public class Weather { Objects.equals(rain, weather.rain) && Objects.equals(snow, weather.snow) && Objects.equals(clouds, weather.clouds) && - Objects.equals(location, weather.location); + Objects.equals(location, weather.location) && + Objects.equals(base, weather.base); } @Override public int hashCode() { - return Objects.hash(calculationTime, weatherState, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, location); + return Objects.hash(calculationTime, weatherStates, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, location, base); } @Override @@ -261,9 +272,9 @@ public class Weather { stringBuilder.append(')'); } } - if (weatherState != null) { + if (weatherStates != null && weatherStates.size() > 0) { stringBuilder.append(", Weather: "); - stringBuilder.append(weatherState.getDescription()); + stringBuilder.append(weatherStates.get(0).getDescription()); } if (temperature != null) { stringBuilder.append(", "); @@ -279,7 +290,7 @@ public class Weather { } if (clouds != null) { stringBuilder.append(", "); - stringBuilder.append(clouds.toString()); + stringBuilder.append(clouds); } if (rain != null && rain.getOneHourLevel() != null) { stringBuilder.append(", Rain: "); diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/RequestSettings.java b/src/main/java/com/github/prominence/openweathermap/api/request/RequestSettings.java index db0b103..56218d6 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/RequestSettings.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/RequestSettings.java @@ -41,7 +41,9 @@ public class RequestSettings { private final Map requestParameters = new HashMap<>(8); - private final StringBuilder urlAppenderBuilder = new StringBuilder(""); + private final StringBuilder urlAppenderBuilder = new StringBuilder(); + + private String subdomain = "api"; private Language language = Language.ENGLISH; private UnitSystem unitSystem = UnitSystem.STANDARD; @@ -56,6 +58,14 @@ public class RequestSettings { return timeoutSettings; } + public String getSubdomain() { + return subdomain; + } + + public void setSubdomain(String subdomain) { + this.subdomain = subdomain; + } + public UnitSystem getUnitSystem() { return unitSystem; } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminator.java index 06e64e0..e09a9e4 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminator.java @@ -42,7 +42,7 @@ public class AirPollutionAsyncRequestTerminator { * * @param requestSettings request settings object. */ - public AirPollutionAsyncRequestTerminator(RequestSettings requestSettings) { + AirPollutionAsyncRequestTerminator(RequestSettings requestSettings) { this.requestSettings = requestSettings; } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestCustomizer.java index 6bd8b3c..1f63687 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestCustomizer.java @@ -37,7 +37,7 @@ public class AirPollutionRequestCustomizer { * * @param requestSettings request settings object. */ - public AirPollutionRequestCustomizer(RequestSettings requestSettings) { + AirPollutionRequestCustomizer(RequestSettings requestSettings) { this.requestSettings = requestSettings; } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminator.java index 4aeb066..5582f9d 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminator.java @@ -40,7 +40,7 @@ public class AirPollutionRequestTerminator { * * @param requestSettings request settings object. */ - public AirPollutionRequestTerminator(RequestSettings requestSettings) { + AirPollutionRequestTerminator(RequestSettings requestSettings) { this.requestSettings = requestSettings; } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequester.java index cb7a913..6ded2cf 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequester.java @@ -39,20 +39,20 @@ public class AirPollutionRequester { */ public AirPollutionRequester(RequestSettings requestSettings) { this.requestSettings = requestSettings; + requestSettings.appendToURL("data/2.5/air_pollution"); } public CurrentAirPollutionRequester current() { - requestSettings.appendToURL("air_pollution"); return new CurrentAirPollutionRequester(requestSettings); } public ForecastAirPollutionRequester forecast() { - requestSettings.appendToURL("air_pollution/forecast"); + requestSettings.appendToURL("/forecast"); return new ForecastAirPollutionRequester(requestSettings); } public HistoricalAirPollutionRequester historical() { - requestSettings.appendToURL("air_pollution/history"); + requestSettings.appendToURL("/history"); return new HistoricalAirPollutionRequester(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/CurrentAirPollutionRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/CurrentAirPollutionRequester.java index 7ab4630..1ee503e 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/CurrentAirPollutionRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/CurrentAirPollutionRequester.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.request.air.pollution; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; /** @@ -36,13 +36,13 @@ public class CurrentAirPollutionRequester { * * @param requestSettings request settings object. */ - public CurrentAirPollutionRequester(RequestSettings requestSettings) { + CurrentAirPollutionRequester(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public AirPollutionRequestCustomizer byCoordinate(Coordinate coordinate) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude())); + public AirPollutionRequestCustomizer byCoordinates(Coordinates coordinates) { + requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); return new AirPollutionRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/ForecastAirPollutionRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/ForecastAirPollutionRequester.java index 0dfd06c..46449ca 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/ForecastAirPollutionRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/ForecastAirPollutionRequester.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.request.air.pollution; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; /** @@ -36,13 +36,13 @@ public class ForecastAirPollutionRequester { * * @param requestSettings request settings object. */ - public ForecastAirPollutionRequester(RequestSettings requestSettings) { + ForecastAirPollutionRequester(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public AirPollutionRequestCustomizer byCoordinate(Coordinate coordinate) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude())); + public AirPollutionRequestCustomizer byCoordinates(Coordinates coordinates) { + requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); return new AirPollutionRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/HistoricalAirPollutionRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/HistoricalAirPollutionRequester.java index 506c8b2..8856cdf 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/HistoricalAirPollutionRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/HistoricalAirPollutionRequester.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.request.air.pollution; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; /** @@ -36,13 +36,13 @@ public class HistoricalAirPollutionRequester { * * @param requestSettings request settings object. */ - public HistoricalAirPollutionRequester(RequestSettings requestSettings) { + HistoricalAirPollutionRequester(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public AirPollutionRequestCustomizer byCoordinateAndPeriod(Coordinate coordinate, long startUnixTime, long endUnixTime) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude())); + public AirPollutionRequestCustomizer byCoordinateAndPeriod(Coordinates coordinates, long startUnixTime, long endUnixTime) { + requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); requestSettings.putRequestParameter("start", String.valueOf(startUnixTime)); requestSettings.putRequestParameter("end", String.valueOf(endUnixTime)); return new AirPollutionRequestCustomizer(requestSettings); diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminator.java similarity index 68% rename from src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator.java rename to src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminator.java index bd32b97..7d873ad 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminator.java @@ -20,34 +20,25 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.multiple; +package com.github.prominence.openweathermap.api.request.forecast.daily; import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.model.weather.Weather; +import com.github.prominence.openweathermap.api.mapper.DailyForecastResponseMapper; +import com.github.prominence.openweathermap.api.model.forecast.daily.Forecast; import com.github.prominence.openweathermap.api.request.RequestSettings; -import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper; import com.github.prominence.openweathermap.api.utils.RequestUtils; -import java.util.List; import java.util.concurrent.CompletableFuture; -/** - * The type Multiple result current weather async request terminator. - */ -public class MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator { +class DailyForecastAsyncRequestTerminator { private final RequestSettings requestSettings; - /** - * Instantiates a new Multiple result current weather async request terminator. - * - * @param requestSettings request settings object. - */ - MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator(RequestSettings requestSettings) { + DailyForecastAsyncRequestTerminator(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public CompletableFuture> asJava() { - return CompletableFuture.supplyAsync(() -> new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getList(getRawResponse())); + public CompletableFuture asJava() { + return CompletableFuture.supplyAsync(() -> new DailyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse())); } public CompletableFuture asJSON() { diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestCustomizer.java similarity index 56% rename from src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer.java rename to src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestCustomizer.java index d9663c9..03b7e0a 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,42 +20,48 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.multiple; +package com.github.prominence.openweathermap.api.request.forecast.daily; import com.github.prominence.openweathermap.api.enums.Language; import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class DailyForecastRequestCustomizer { + private static final Logger logger = LoggerFactory.getLogger(DailyForecastRequestCustomizer.class); -/** - * The type Multiple result current weather request customizer. - */ -public class MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer { private final RequestSettings requestSettings; - /** - * Instantiates a new Multiple result current weather request customizer. - * - * @param requestSettings request settings object. - */ - MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer(RequestSettings requestSettings) { + public DailyForecastRequestCustomizer(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer language(Language language) { + public DailyForecastRequestCustomizer language(Language language) { requestSettings.setLanguage(language); return this; } - public MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer unitSystem(UnitSystem unitSystem) { + public DailyForecastRequestCustomizer unitSystem(UnitSystem unitSystem) { requestSettings.setUnitSystem(unitSystem); return this; } - public MultipleResultCitiesInCircleCurrentWeatherRequestTerminator retrieve() { - return new MultipleResultCitiesInCircleCurrentWeatherRequestTerminator(requestSettings); + public DailyForecastRequestCustomizer numberOfDays(int numberOfDays) { + int days = numberOfDays; + if (days > 16) { + logger.warn("Cannot use more than 16 days for this api request. Please, specify 16 or less days. !!! Requesting information for 16 days..."); + days = 16; + } + requestSettings.putRequestParameter("cnt", Integer.toString(days)); + return this; } - public MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator retrieveAsync() { - return new MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator(requestSettings); + public DailyForecastRequestTerminator retrieve() { + return new DailyForecastRequestTerminator(requestSettings); } -} \ No newline at end of file + + public DailyForecastAsyncRequestTerminator retrieveAsync() { + return new DailyForecastAsyncRequestTerminator(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCitiesInCircleCurrentWeatherRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminator.java similarity index 68% rename from src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCitiesInCircleCurrentWeatherRequestTerminator.java rename to src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminator.java index 6341bf1..627780f 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCitiesInCircleCurrentWeatherRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminator.java @@ -20,33 +20,23 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.multiple; +package com.github.prominence.openweathermap.api.request.forecast.daily; import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.model.weather.Weather; +import com.github.prominence.openweathermap.api.mapper.DailyForecastResponseMapper; +import com.github.prominence.openweathermap.api.model.forecast.daily.Forecast; import com.github.prominence.openweathermap.api.request.RequestSettings; -import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper; import com.github.prominence.openweathermap.api.utils.RequestUtils; -import java.util.List; - -/** - * The type Multiple result current weather request terminator. - */ -public class MultipleResultCitiesInCircleCurrentWeatherRequestTerminator { +class DailyForecastRequestTerminator { private final RequestSettings requestSettings; - /** - * Instantiates a new Multiple result current weather request terminator. - * - * @param requestSettings request settings object. - */ - MultipleResultCitiesInCircleCurrentWeatherRequestTerminator(RequestSettings requestSettings) { + DailyForecastRequestTerminator(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public List asJava() { - return new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getList(getRawResponse()); + public Forecast asJava() { + return new DailyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse()); } public String asJSON() { diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequester.java new file mode 100644 index 0000000..0c6fbba --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequester.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.forecast.daily; + +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.request.RequestSettings; + +public class DailyForecastRequester { + private final RequestSettings requestSettings; + + public DailyForecastRequester(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + this.requestSettings.appendToURL("data/2.5/forecast/hourly"); + } + + public DailyForecastRequestCustomizer byCoordinates(Coordinates coordinates) { + requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + return new DailyForecastRequestCustomizer(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminator.java index ea442dc..c9e42dc 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminator.java @@ -24,7 +24,7 @@ package com.github.prominence.openweathermap.api.request.forecast.free; import com.github.prominence.openweathermap.api.enums.ResponseType; import com.github.prominence.openweathermap.api.mapper.FiveDayThreeHourStepForecastResponseMapper; -import com.github.prominence.openweathermap.api.model.forecast.Forecast; +import com.github.prominence.openweathermap.api.model.forecast.free.Forecast; import com.github.prominence.openweathermap.api.request.RequestSettings; import com.github.prominence.openweathermap.api.utils.RequestUtils; @@ -33,7 +33,7 @@ import java.util.concurrent.CompletableFuture; /** * Async request terminator. */ -public class FiveDayThreeHourStepForecastAsyncRequestTerminator { +class FiveDayThreeHourStepForecastAsyncRequestTerminator { private final RequestSettings requestSettings; /** diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestCustomizer.java index 33c4ea3..925319e 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestCustomizer.java @@ -29,7 +29,7 @@ import com.github.prominence.openweathermap.api.request.RequestSettings; /** * The forecast request customizer. */ -public class FiveDayThreeHourStepForecastRequestCustomizer { +class FiveDayThreeHourStepForecastRequestCustomizer { private final RequestSettings requestSettings; /** diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminator.java index 16bcf76..3f6f37a 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminator.java @@ -24,14 +24,14 @@ package com.github.prominence.openweathermap.api.request.forecast.free; import com.github.prominence.openweathermap.api.enums.ResponseType; import com.github.prominence.openweathermap.api.mapper.FiveDayThreeHourStepForecastResponseMapper; -import com.github.prominence.openweathermap.api.model.forecast.Forecast; +import com.github.prominence.openweathermap.api.model.forecast.free.Forecast; import com.github.prominence.openweathermap.api.request.RequestSettings; import com.github.prominence.openweathermap.api.utils.RequestUtils; /** * The forecast request terminator. */ -public class FiveDayThreeHourStepForecastRequestTerminator { +class FiveDayThreeHourStepForecastRequestTerminator { private final RequestSettings requestSettings; /** diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequester.java index 54a829f..f65a15f 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequester.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.request.forecast.free; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; /** @@ -38,7 +38,7 @@ public class FiveDayThreeHourStepForecastRequester { */ public FiveDayThreeHourStepForecastRequester(RequestSettings requestSettings) { this.requestSettings = requestSettings; - this.requestSettings.appendToURL("forecast"); + this.requestSettings.appendToURL("data/2.5/forecast"); } public FiveDayThreeHourStepForecastRequestCustomizer byCityName(String cityName) { @@ -61,9 +61,9 @@ public class FiveDayThreeHourStepForecastRequester { return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings); } - public FiveDayThreeHourStepForecastRequestCustomizer byCoordinate(Coordinate coordinate) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude())); + public FiveDayThreeHourStepForecastRequestCustomizer byCoordinates(Coordinates coordinates) { + requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminator.java similarity index 66% rename from src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherAsyncRequestTerminator.java rename to src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminator.java index 3b74133..f0e7cf8 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminator.java @@ -20,39 +20,36 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.multiple; +package com.github.prominence.openweathermap.api.request.forecast.hourly; -import com.github.prominence.openweathermap.api.model.weather.Weather; +import com.github.prominence.openweathermap.api.enums.ResponseType; +import com.github.prominence.openweathermap.api.mapper.HourlyForecastResponseMapper; +import com.github.prominence.openweathermap.api.model.forecast.hourly.HourlyForecast; import com.github.prominence.openweathermap.api.request.RequestSettings; -import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper; import com.github.prominence.openweathermap.api.utils.RequestUtils; -import java.util.List; import java.util.concurrent.CompletableFuture; -/** - * The type Multiple result current weather async request terminator. - */ -public class MultipleResultCurrentWeatherAsyncRequestTerminator { +class FourDaysHourlyForecastAsyncRequestTerminator { private final RequestSettings requestSettings; - /** - * Instantiates a new Multiple result current weather async request terminator. - * - * @param requestSettings request settings object. - */ - MultipleResultCurrentWeatherAsyncRequestTerminator(RequestSettings requestSettings) { + FourDaysHourlyForecastAsyncRequestTerminator(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public CompletableFuture> asJava() { - return CompletableFuture.supplyAsync(() -> new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getList(getRawResponse())); + public CompletableFuture asJava() { + return CompletableFuture.supplyAsync(() -> new HourlyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse())); } public CompletableFuture asJSON() { return CompletableFuture.supplyAsync(this::getRawResponse); } + public CompletableFuture asXML() { + requestSettings.setResponseType(ResponseType.XML); + return CompletableFuture.supplyAsync(this::getRawResponse); + } + private String getRawResponse() { return RequestUtils.getResponse(requestSettings); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestCustomizer.java similarity index 56% rename from src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherRequestCustomizer.java rename to src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestCustomizer.java index 522bcd9..8a1133a 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,42 +20,33 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.multiple; +package com.github.prominence.openweathermap.api.request.forecast.hourly; import com.github.prominence.openweathermap.api.enums.Language; -import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.request.RequestSettings; -/** - * The type Multiple result current weather request customizer. - */ -public class MultipleResultCurrentWeatherRequestCustomizer { +class FourDaysHourlyForecastRequestCustomizer { private final RequestSettings requestSettings; - /** - * Instantiates a new Multiple result current weather request customizer. - * - * @param requestSettings request settings object. - */ - MultipleResultCurrentWeatherRequestCustomizer(RequestSettings requestSettings) { + public FourDaysHourlyForecastRequestCustomizer(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public MultipleResultCurrentWeatherRequestCustomizer language(Language language) { + public FourDaysHourlyForecastRequestCustomizer language(Language language) { requestSettings.setLanguage(language); return this; } - public MultipleResultCurrentWeatherRequestCustomizer unitSystem(UnitSystem unitSystem) { - requestSettings.setUnitSystem(unitSystem); + public FourDaysHourlyForecastRequestCustomizer count(int numberOfTimestamps) { + requestSettings.putRequestParameter("cnt", Integer.toString(numberOfTimestamps)); return this; } - public MultipleResultCurrentWeatherRequestTerminator retrieve() { - return new MultipleResultCurrentWeatherRequestTerminator(requestSettings); + public FourDaysHourlyForecastRequestTerminator retrieve() { + return new FourDaysHourlyForecastRequestTerminator(requestSettings); } - public MultipleResultCurrentWeatherAsyncRequestTerminator retrieveAsync() { - return new MultipleResultCurrentWeatherAsyncRequestTerminator(requestSettings); + public FourDaysHourlyForecastAsyncRequestTerminator retrieveAsync() { + return new FourDaysHourlyForecastAsyncRequestTerminator(requestSettings); } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminator.java similarity index 66% rename from src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherRequestTerminator.java rename to src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminator.java index 1c9859f..af68410 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminator.java @@ -20,38 +20,34 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.multiple; +package com.github.prominence.openweathermap.api.request.forecast.hourly; -import com.github.prominence.openweathermap.api.model.weather.Weather; +import com.github.prominence.openweathermap.api.enums.ResponseType; +import com.github.prominence.openweathermap.api.mapper.HourlyForecastResponseMapper; +import com.github.prominence.openweathermap.api.model.forecast.hourly.HourlyForecast; import com.github.prominence.openweathermap.api.request.RequestSettings; -import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper; import com.github.prominence.openweathermap.api.utils.RequestUtils; -import java.util.List; - -/** - * The type Multiple result current weather request terminator. - */ -public class MultipleResultCurrentWeatherRequestTerminator { +class FourDaysHourlyForecastRequestTerminator { private final RequestSettings requestSettings; - /** - * Instantiates a new Multiple result current weather request terminator. - * - * @param requestSettings request settings object. - */ - MultipleResultCurrentWeatherRequestTerminator(RequestSettings requestSettings) { + FourDaysHourlyForecastRequestTerminator(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public List asJava() { - return new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getList(getRawResponse()); + public HourlyForecast asJava() { + return new HourlyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse()); } public String asJSON() { return getRawResponse(); } + public String asXML() { + requestSettings.setResponseType(ResponseType.XML); + return getRawResponse(); + } + private String getRawResponse() { return RequestUtils.getResponse(requestSettings); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequester.java new file mode 100644 index 0000000..d93965e --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequester.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.forecast.hourly; + +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.request.RequestSettings; + +public class FourDaysHourlyForecastRequester { + private final RequestSettings requestSettings; + + public FourDaysHourlyForecastRequester(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + this.requestSettings.appendToURL("data/2.5/forecast/hourly"); + this.requestSettings.setSubdomain("pro"); + } + + public FourDaysHourlyForecastRequestCustomizer byCoordinates(Coordinates coordinates) { + requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + return new FourDaysHourlyForecastRequestCustomizer(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/GeocodingRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/GeocodingRequester.java new file mode 100644 index 0000000..ffbe819 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/GeocodingRequester.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.geocoding; + +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.geocoding.direct.DirectGeocodingRequester; +import com.github.prominence.openweathermap.api.request.geocoding.reverse.ReverseGeocodingRequester; + +public class GeocodingRequester { + private final RequestSettings requestSettings; + + public GeocodingRequester(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + this.requestSettings.appendToURL("geo/1.0"); + } + + public DirectGeocodingRequester direct() { + return new DirectGeocodingRequester(requestSettings); + } + + public ReverseGeocodingRequester reverse() { + return new ReverseGeocodingRequester(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestAsyncTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestAsyncTerminator.java new file mode 100644 index 0000000..efcf8a2 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestAsyncTerminator.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.geocoding.direct; + +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.utils.RequestUtils; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +public class DirectGeocodingRequestAsyncTerminator { + private final RequestSettings requestSettings; + private final Function mapperFunction; + + DirectGeocodingRequestAsyncTerminator(RequestSettings requestSettings, Function mapperFunction) { + this.requestSettings = requestSettings; + this.mapperFunction = mapperFunction; + } + + public CompletableFuture asJava() { + return CompletableFuture.supplyAsync(() -> mapperFunction.apply(getRawResponse())); + } + + public CompletableFuture asJSON() { + return CompletableFuture.supplyAsync(this::getRawResponse); + } + + private String getRawResponse() { + return RequestUtils.getResponse(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestCustomizer.java new file mode 100644 index 0000000..3e44225 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestCustomizer.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.geocoding.direct; + +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.geocoding.reverse.ReverseGeocodingRequestAsyncTerminator; +import com.github.prominence.openweathermap.api.request.geocoding.reverse.ReverseGeocodingRequestTerminator; + +import java.util.function.Function; + +public class DirectGeocodingRequestCustomizer { + private final RequestSettings requestSettings; + private final Function mapperFunction; + + DirectGeocodingRequestCustomizer(RequestSettings requestSettings, Function mapperFunction) { + this.requestSettings = requestSettings; + this.mapperFunction = mapperFunction; + } + + public DirectGeocodingRequestCustomizer limit(int locationsNumber) { + requestSettings.putRequestParameter("limit", Integer.toString(locationsNumber)); + return this; + } + + public DirectGeocodingRequestTerminator retrieve() { + return new DirectGeocodingRequestTerminator(requestSettings, mapperFunction); + } + + public DirectGeocodingRequestAsyncTerminator retrieveAsync() { + return new DirectGeocodingRequestAsyncTerminator(requestSettings, mapperFunction); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestTerminator.java new file mode 100644 index 0000000..a7388f4 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestTerminator.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.geocoding.direct; + +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.utils.RequestUtils; + +import java.util.function.Function; + +public class DirectGeocodingRequestTerminator { + private final RequestSettings requestSettings; + private final Function mapperFunction; + + DirectGeocodingRequestTerminator(RequestSettings requestSettings, Function mapperFunction) { + this.requestSettings = requestSettings; + this.mapperFunction = mapperFunction; + } + + public R asJava() { + return mapperFunction.apply(asJSON()); + } + + public String asJSON() { + return getRawResponse(); + } + + private String getRawResponse() { + return RequestUtils.getResponse(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequester.java new file mode 100644 index 0000000..4285c7b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequester.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.geocoding.direct; + +import com.github.prominence.openweathermap.api.mapper.GeocodingResponseMapper; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord; +import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingRecord; +import com.github.prominence.openweathermap.api.request.RequestSettings; + +import java.util.List; + +public class DirectGeocodingRequester { + private final RequestSettings requestSettings; + + public DirectGeocodingRequester(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + public DirectGeocodingRequestCustomizer> byLocationName(String cityName, String stateCode, String countryCode) { + requestSettings.appendToURL("direct"); + requestSettings.putRequestParameter("q", cityName + "," + stateCode + "," + countryCode); + return new DirectGeocodingRequestCustomizer<>(requestSettings, (String json) -> new GeocodingResponseMapper().mapGeocodingResponse(json)); + } + + public DirectGeocodingRequestCustomizer byZipCode(String zipCode, String countryCode) { + requestSettings.appendToURL("zip"); + requestSettings.putRequestParameter("zip", zipCode + "," + countryCode); + return new DirectGeocodingRequestCustomizer<>(requestSettings, (String json) -> new GeocodingResponseMapper().mapZipCodeGeocodingResponse(json)); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestAsyncTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestAsyncTerminator.java new file mode 100644 index 0000000..09e530b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestAsyncTerminator.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.geocoding.reverse; + +import com.github.prominence.openweathermap.api.mapper.GeocodingResponseMapper; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.utils.RequestUtils; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public class ReverseGeocodingRequestAsyncTerminator { + private final RequestSettings requestSettings; + + ReverseGeocodingRequestAsyncTerminator(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + public CompletableFuture> asJava() { + return CompletableFuture.supplyAsync(() -> new GeocodingResponseMapper().mapGeocodingResponse(getRawResponse())); + } + + public CompletableFuture asJSON() { + return CompletableFuture.supplyAsync(this::getRawResponse); + } + + private String getRawResponse() { + return RequestUtils.getResponse(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestCustomizer.java new file mode 100644 index 0000000..acd240b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestCustomizer.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.geocoding.reverse; + +import com.github.prominence.openweathermap.api.request.RequestSettings; + +public class ReverseGeocodingRequestCustomizer { + private final RequestSettings requestSettings; + + ReverseGeocodingRequestCustomizer(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + public ReverseGeocodingRequestCustomizer limit(int locationsNumber) { + requestSettings.putRequestParameter("limit", Integer.toString(locationsNumber)); + return this; + } + + public ReverseGeocodingRequestTerminator retrieve() { + return new ReverseGeocodingRequestTerminator(requestSettings); + } + + public ReverseGeocodingRequestAsyncTerminator retrieveAsync() { + return new ReverseGeocodingRequestAsyncTerminator(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestTerminator.java new file mode 100644 index 0000000..6e61b5a --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestTerminator.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.geocoding.reverse; + +import com.github.prominence.openweathermap.api.mapper.GeocodingResponseMapper; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.utils.RequestUtils; + +import java.util.List; + +public class ReverseGeocodingRequestTerminator { + private final RequestSettings requestSettings; + + ReverseGeocodingRequestTerminator(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + public List asJava() { + return new GeocodingResponseMapper().mapGeocodingResponse(asJSON()); + } + + public String asJSON() { + return getRawResponse(); + } + + private String getRawResponse() { + return RequestUtils.getResponse(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequester.java new file mode 100644 index 0000000..2db7d9c --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequester.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.request.geocoding.reverse; + +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.request.RequestSettings; + +public class ReverseGeocodingRequester { + private final RequestSettings requestSettings; + + public ReverseGeocodingRequester(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + this.requestSettings.appendToURL("reverse"); + } + + public ReverseGeocodingRequestCustomizer byCoordinates(Coordinates coordinates) { + requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + return new ReverseGeocodingRequestCustomizer(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherRequester.java index 9440d15..007bb53 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherRequester.java @@ -39,6 +39,7 @@ public class OneCallWeatherRequester { */ public OneCallWeatherRequester(RequestSettings requestSettings) { this.requestSettings = requestSettings; + this.requestSettings.appendToURL("data/2.5/onecall"); } public OneCallCurrentWeatherRequester current() { diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherAsyncRequestTerminator.java index d2acb66..d0ecc70 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherAsyncRequestTerminator.java @@ -32,7 +32,7 @@ import java.util.concurrent.CompletableFuture; /** * The type One call current weather async request terminator. */ -public class OneCallCurrentWeatherAsyncRequestTerminator { +class OneCallCurrentWeatherAsyncRequestTerminator { private final RequestSettings requestSettings; /** diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestCustomizer.java index 7ed9b7c..ccccaf2 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestCustomizer.java @@ -33,7 +33,7 @@ import java.util.stream.Stream; /** * The type One call current weather request customizer. */ -public class OneCallCurrentWeatherRequestCustomizer { +class OneCallCurrentWeatherRequestCustomizer { private final RequestSettings requestSettings; /** diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestTerminator.java index 9cf97ee..81b7f27 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestTerminator.java @@ -30,7 +30,7 @@ import com.github.prominence.openweathermap.api.utils.RequestUtils; /** * The type One call current weather request terminator. */ -public class OneCallCurrentWeatherRequestTerminator { +class OneCallCurrentWeatherRequestTerminator { private final RequestSettings requestSettings; /** diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequester.java index e756bb9..621a487 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequester.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.request.onecall.current; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; /** @@ -38,12 +38,11 @@ public class OneCallCurrentWeatherRequester { */ public OneCallCurrentWeatherRequester(RequestSettings requestSettings) { this.requestSettings = requestSettings; - this.requestSettings.appendToURL("onecall"); } - public OneCallCurrentWeatherRequestCustomizer byCoordinate(Coordinate coordinate) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude())); + public OneCallCurrentWeatherRequestCustomizer byCoordinates(Coordinates coordinates) { + requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); return new OneCallCurrentWeatherRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherAsyncRequestTerminator.java index d17ea54..6be81d7 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherAsyncRequestTerminator.java @@ -32,7 +32,7 @@ import java.util.concurrent.CompletableFuture; /** * The type One call historical weather async request terminator. */ -public class OneCallHistoricalWeatherAsyncRequestTerminator { +class OneCallHistoricalWeatherAsyncRequestTerminator { private final RequestSettings requestSettings; /** diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestCustomizer.java index 47b978d..b34b744 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestCustomizer.java @@ -29,7 +29,7 @@ import com.github.prominence.openweathermap.api.request.RequestSettings; /** * The type One call historical weather request customizer. */ -public class OneCallHistoricalWeatherRequestCustomizer { +class OneCallHistoricalWeatherRequestCustomizer { private final RequestSettings requestSettings; /** diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestTerminator.java index 7c89d9d..7aa2461 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestTerminator.java @@ -30,7 +30,7 @@ import com.github.prominence.openweathermap.api.utils.RequestUtils; /** * The type One call historical weather request terminator. */ -public class OneCallHistoricalWeatherRequestTerminator { +class OneCallHistoricalWeatherRequestTerminator { private final RequestSettings requestSettings; /** diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequester.java index 17a6c95..3d04dc3 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequester.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.request.onecall.historical; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; /** @@ -38,12 +38,12 @@ public class OneCallHistoricalWeatherRequester { */ public OneCallHistoricalWeatherRequester(RequestSettings requestSettings) { this.requestSettings = requestSettings; - this.requestSettings.appendToURL("onecall/timemachine"); + this.requestSettings.appendToURL("/timemachine"); } - public OneCallHistoricalWeatherRequestCustomizer byCoordinateAndTimestamp(Coordinate coordinate, long unixTime) { - requestSettings.putRequestParameter("lat", Double.toString(coordinate.getLatitude())); - requestSettings.putRequestParameter("lon", Double.toString(coordinate.getLongitude())); + public OneCallHistoricalWeatherRequestCustomizer byCoordinateAndTimestamp(Coordinates coordinates, long unixTime) { + requestSettings.putRequestParameter("lat", Double.toString(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", Double.toString(coordinates.getLongitude())); requestSettings.putRequestParameter("dt", Long.toString(unixTime)); return new OneCallHistoricalWeatherRequestCustomizer(requestSettings); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherAsyncRequestTerminator.java similarity index 90% rename from src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherAsyncRequestTerminator.java rename to src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherAsyncRequestTerminator.java index bfb0136..a0f1b77 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherAsyncRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.single; +package com.github.prominence.openweathermap.api.request.weather; import com.github.prominence.openweathermap.api.enums.ResponseType; import com.github.prominence.openweathermap.api.request.RequestSettings; @@ -33,7 +33,7 @@ import java.util.concurrent.CompletableFuture; /** * The type Single result current weather async request terminator. */ -public class SingleResultCurrentWeatherAsyncRequestTerminator { +public class CurrentWeatherAsyncRequestTerminator { private final RequestSettings requestSettings; /** @@ -41,12 +41,12 @@ public class SingleResultCurrentWeatherAsyncRequestTerminator { * * @param requestSettings request settings object. */ - SingleResultCurrentWeatherAsyncRequestTerminator(RequestSettings requestSettings) { + CurrentWeatherAsyncRequestTerminator(RequestSettings requestSettings) { this.requestSettings = requestSettings; } public CompletableFuture asJava() { - return CompletableFuture.supplyAsync(() -> new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getSingle(getRawResponse())); + return CompletableFuture.supplyAsync(() -> new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).mapToWeather(getRawResponse())); } public CompletableFuture asJSON() { diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestCustomizer.java similarity index 73% rename from src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherRequestCustomizer.java rename to src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestCustomizer.java index 982ffe2..3499232 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.single; +package com.github.prominence.openweathermap.api.request.weather; import com.github.prominence.openweathermap.api.enums.Language; import com.github.prominence.openweathermap.api.enums.UnitSystem; @@ -29,7 +29,7 @@ import com.github.prominence.openweathermap.api.request.RequestSettings; /** * The type Single result current weather request customizer. */ -public class SingleResultCurrentWeatherRequestCustomizer { +public class CurrentWeatherRequestCustomizer { private final RequestSettings requestSettings; /** @@ -37,25 +37,25 @@ public class SingleResultCurrentWeatherRequestCustomizer { * * @param requestSettings request settings object. */ - SingleResultCurrentWeatherRequestCustomizer(RequestSettings requestSettings) { + CurrentWeatherRequestCustomizer(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public SingleResultCurrentWeatherRequestCustomizer language(Language language) { + public CurrentWeatherRequestCustomizer language(Language language) { requestSettings.setLanguage(language); return this; } - public SingleResultCurrentWeatherRequestCustomizer unitSystem(UnitSystem unitSystem) { + public CurrentWeatherRequestCustomizer unitSystem(UnitSystem unitSystem) { requestSettings.setUnitSystem(unitSystem); return this; } - public SingleResultCurrentWeatherRequestTerminator retrieve() { - return new SingleResultCurrentWeatherRequestTerminator(requestSettings); + public CurrentWeatherRequestTerminator retrieve() { + return new CurrentWeatherRequestTerminator(requestSettings); } - public SingleResultCurrentWeatherAsyncRequestTerminator retrieveAsync() { - return new SingleResultCurrentWeatherAsyncRequestTerminator(requestSettings); + public CurrentWeatherAsyncRequestTerminator retrieveAsync() { + return new CurrentWeatherAsyncRequestTerminator(requestSettings); } } \ No newline at end of file diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminator.java similarity index 91% rename from src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherRequestTerminator.java rename to src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminator.java index 3fbc95c..1601fbc 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.single; +package com.github.prominence.openweathermap.api.request.weather; import com.github.prominence.openweathermap.api.enums.ResponseType; import com.github.prominence.openweathermap.api.model.weather.Weather; @@ -31,7 +31,7 @@ import com.github.prominence.openweathermap.api.utils.RequestUtils; /** * The type Single result current weather request terminator. */ -public class SingleResultCurrentWeatherRequestTerminator { +public class CurrentWeatherRequestTerminator { private final RequestSettings requestSettings; /** @@ -39,12 +39,12 @@ public class SingleResultCurrentWeatherRequestTerminator { * * @param requestSettings request settings object. */ - SingleResultCurrentWeatherRequestTerminator(RequestSettings requestSettings) { + CurrentWeatherRequestTerminator(RequestSettings requestSettings) { this.requestSettings = requestSettings; } public Weather asJava() { - return new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getSingle(asJSON()); + return new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).mapToWeather(asJSON()); } public String asJSON() { diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequester.java index c56babd..4a47fff 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -22,30 +22,64 @@ package com.github.prominence.openweathermap.api.request.weather; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; -import com.github.prominence.openweathermap.api.request.weather.multiple.MultipleLocationsCurrentWeatherRequester; -import com.github.prominence.openweathermap.api.request.weather.single.SingleLocationCurrentWeatherRequester; /** - * The type Current weather requester. + * The type Single location current weather requester. */ public class CurrentWeatherRequester { private final RequestSettings requestSettings; /** - * Instantiates a new Current weather requester. + * Instantiates a new Single location current weather requester. * * @param requestSettings request settings object. */ public CurrentWeatherRequester(RequestSettings requestSettings) { this.requestSettings = requestSettings; + this.requestSettings.appendToURL("data/2.5/weather"); } - public SingleLocationCurrentWeatherRequester single() { - return new SingleLocationCurrentWeatherRequester(requestSettings); + @Deprecated + public CurrentWeatherRequestCustomizer byCityName(String cityName) { + requestSettings.putRequestParameter("q", cityName); + return new CurrentWeatherRequestCustomizer(requestSettings); } - public MultipleLocationsCurrentWeatherRequester multiple() { - return new MultipleLocationsCurrentWeatherRequester(requestSettings); + @Deprecated + public CurrentWeatherRequestCustomizer byCityName(String cityName, String countryCode) { + requestSettings.putRequestParameter("q", cityName + "," + countryCode); + return new CurrentWeatherRequestCustomizer(requestSettings); + } + + @Deprecated + public CurrentWeatherRequestCustomizer byCityName(String cityName, String stateCode, String countryCode) { + requestSettings.putRequestParameter("q", cityName + "," + stateCode + "," + countryCode); + return new CurrentWeatherRequestCustomizer(requestSettings); + } + + @Deprecated + public CurrentWeatherRequestCustomizer byCityId(long cityId) { + requestSettings.putRequestParameter("id", String.valueOf(cityId)); + return new CurrentWeatherRequestCustomizer(requestSettings); + } + + public CurrentWeatherRequestCustomizer byCoordinates(Coordinates coordinates) { + requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + return new CurrentWeatherRequestCustomizer(requestSettings); + } + + @Deprecated + public CurrentWeatherRequestCustomizer byZipCodeAndCountry(String zipCode, String countryCode) { + requestSettings.putRequestParameter("zip", zipCode + "," + countryCode); + return new CurrentWeatherRequestCustomizer(requestSettings); + } + + @Deprecated + public CurrentWeatherRequestCustomizer byZipCodeInUSA(String zipCode) { + requestSettings.putRequestParameter("zip", zipCode); + return new CurrentWeatherRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleLocationsCurrentWeatherRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleLocationsCurrentWeatherRequester.java deleted file mode 100644 index 724ddbc..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleLocationsCurrentWeatherRequester.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2021 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 com.github.prominence.openweathermap.api.request.weather.multiple; - -import com.github.prominence.openweathermap.api.model.Coordinate; -import com.github.prominence.openweathermap.api.model.CoordinateRectangle; -import com.github.prominence.openweathermap.api.request.RequestSettings; - -/** - * The type Multiple locations current weather requester. - */ -public class MultipleLocationsCurrentWeatherRequester { - private final RequestSettings requestSettings; - - /** - * Instantiates a new Multiple locations current weather requester. - * - * @param requestSettings request settings object. - */ - public MultipleLocationsCurrentWeatherRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - } - - public MultipleResultCurrentWeatherRequestCustomizer byRectangle(CoordinateRectangle rectangle, int zoom) { - String coordinates = rectangle.getFormattedRequestString() + "," + zoom; - requestSettings.appendToURL("box/city"); - requestSettings.putRequestParameter("bbox", coordinates); - - return new MultipleResultCurrentWeatherRequestCustomizer(requestSettings); - } - - public MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer byCitiesInCycle(Coordinate point, int citiesCount) { - requestSettings.appendToURL("find"); - requestSettings.putRequestParameter("lat", Double.toString(point.getLatitude())); - requestSettings.putRequestParameter("lon", Double.toString(point.getLongitude())); - requestSettings.putRequestParameter("cnt", Integer.toString(citiesCount)); - - return new MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer(requestSettings); - } - - public MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer byCitiesInCycle(Coordinate point) { - requestSettings.appendToURL("find"); - requestSettings.putRequestParameter("lat", Double.toString(point.getLatitude())); - requestSettings.putRequestParameter("lon", Double.toString(point.getLongitude())); - - return new MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer(requestSettings); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleLocationCurrentWeatherRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleLocationCurrentWeatherRequester.java deleted file mode 100644 index 199a980..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleLocationCurrentWeatherRequester.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2021 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 com.github.prominence.openweathermap.api.request.weather.single; - -import com.github.prominence.openweathermap.api.model.Coordinate; -import com.github.prominence.openweathermap.api.request.RequestSettings; - -/** - * The type Single location current weather requester. - */ -public class SingleLocationCurrentWeatherRequester { - private final RequestSettings requestSettings; - - /** - * Instantiates a new Single location current weather requester. - * - * @param requestSettings request settings object. - */ - public SingleLocationCurrentWeatherRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - this.requestSettings.appendToURL("weather"); - } - - public SingleResultCurrentWeatherRequestCustomizer byCityName(String cityName) { - requestSettings.putRequestParameter("q", cityName); - return new SingleResultCurrentWeatherRequestCustomizer(requestSettings); - } - - public SingleResultCurrentWeatherRequestCustomizer byCityName(String cityName, String countryCode) { - requestSettings.putRequestParameter("q", cityName + "," + countryCode); - return new SingleResultCurrentWeatherRequestCustomizer(requestSettings); - } - - public SingleResultCurrentWeatherRequestCustomizer byCityName(String cityName, String stateCode, String countryCode) { - requestSettings.putRequestParameter("q", cityName + "," + stateCode + "," + countryCode); - return new SingleResultCurrentWeatherRequestCustomizer(requestSettings); - } - - public SingleResultCurrentWeatherRequestCustomizer byCityId(long cityId) { - requestSettings.putRequestParameter("id", String.valueOf(cityId)); - return new SingleResultCurrentWeatherRequestCustomizer(requestSettings); - } - - public SingleResultCurrentWeatherRequestCustomizer byCoordinate(Coordinate coordinate) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude())); - return new SingleResultCurrentWeatherRequestCustomizer(requestSettings); - } - - public SingleResultCurrentWeatherRequestCustomizer byZipCodeAndCountry(String zipCode, String countryCode) { - requestSettings.putRequestParameter("zip", zipCode + "," + countryCode); - return new SingleResultCurrentWeatherRequestCustomizer(requestSettings); - } - - public SingleResultCurrentWeatherRequestCustomizer byZipCodeInUSA(String zipCode) { - requestSettings.putRequestParameter("zip", zipCode); - return new SingleResultCurrentWeatherRequestCustomizer(requestSettings); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/utils/JsonDeserializationUtils.java b/src/main/java/com/github/prominence/openweathermap/api/utils/JsonDeserializationUtils.java new file mode 100644 index 0000000..519d862 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/utils/JsonDeserializationUtils.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.utils; + +import com.fasterxml.jackson.databind.JsonNode; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.TimeZone; + +public class JsonDeserializationUtils { + public static LocalDateTime parseDateTime(JsonNode dateTimeNode) { + return LocalDateTime.ofInstant(Instant.ofEpochSecond(dateTimeNode.asInt()), TimeZone.getDefault().toZoneId()); + } + + public static ZoneId parseZoneId(JsonNode zoneIdNode) { + return ZoneId.of(zoneIdNode.asText()); + } + + public static ZoneOffset parseZoneOffset(JsonNode zoneOffsetNode) { + return ZoneOffset.ofTotalSeconds(zoneOffsetNode.asInt()); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/utils/RequestUtils.java b/src/main/java/com/github/prominence/openweathermap/api/utils/RequestUtils.java index cbb39a7..ec7e95d 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/utils/RequestUtils.java +++ b/src/main/java/com/github/prominence/openweathermap/api/utils/RequestUtils.java @@ -44,7 +44,7 @@ import java.util.stream.Collectors; */ public final class RequestUtils { - private static final String OWM_URL_BASE = "https://api.openweathermap.org/data/2.5/"; + private static final String OWM_URL_BASE = "https://SUBDOMAIN.openweathermap.org/"; private static final Logger logger = LoggerFactory.getLogger(RequestUtils.class); @@ -52,7 +52,7 @@ public final class RequestUtils { } public static String getResponse(RequestSettings requestSettings) { - StringBuilder requestUrlBuilder = new StringBuilder(OWM_URL_BASE); + StringBuilder requestUrlBuilder = new StringBuilder(OWM_URL_BASE.replace("SUBDOMAIN", requestSettings.getSubdomain())); requestUrlBuilder.append(requestSettings.getUrlAppender()); requestUrlBuilder.append('?'); String parameters = requestSettings.getRequestParameters().entrySet().stream() diff --git a/src/test/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapperTest.java new file mode 100644 index 0000000..3bdc899 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapperTest.java @@ -0,0 +1,1254 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.mapper; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.weather.Weather; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class CurrentWeatherResponseMapperTest { + + @Test + public void mapToWeatherOfficialJsonExample() { + final String jsonString = """ + { + "coord": { + "lon": -122.08, + "lat": 37.39 + }, + "weather": [ + { + "id": 800, + "main": "Clear", + "description": "clear sky", + "icon": "01d" + } + ], + "base": "stations", + "main": { + "temp": 282.55, + "feels_like": 281.86, + "temp_min": 280.37, + "temp_max": 284.26, + "pressure": 1023, + "humidity": 100 + }, + "visibility": 10000, + "wind": { + "speed": 1.5, + "deg": 350 + }, + "clouds": { + "all": 1 + }, + "dt": 1560350645, + "sys": { + "type": 1, + "id": 5122, + "message": 0.0139, + "country": "US", + "sunrise": 1560343627, + "sunset": 1560396563 + }, + "timezone": -25200, + "id": 420006353, + "name": "Mountain View", + "cod": 200 + } + """; + + final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).mapToWeather(jsonString); + + assertNotNull(weather); + } + + @Test + public void mapToWeather() { + final String jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + + final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).mapToWeather(jsonString); + + assertNotNull(weather); + } + + @Test + public void mapToWeather_withDamagedJSON() { + final String jsonString = """ + { + "coord": "lon" + : + 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + assertThrows(RuntimeException.class, () -> new CurrentWeatherResponseMapper(null).mapToWeather(jsonString)); + } + + @Test + public void mapToWeather_withoutDt() { + final String jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + + final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).mapToWeather(jsonString); + + assertNotNull(weather); + assertNull(weather.getCalculationTime()); + } + + @Test + @Disabled + public void mapToWeather_withoutWeatherNode() { + final String jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + + final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).mapToWeather(jsonString); + + assertNotNull(weather); + assertNull(weather.getWeatherStates()); + } + + @Test + public void mapToWeather_withTemperatureVariations() { + String jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); + + Weather weather = mapper.mapToWeather(jsonString); + + assertNotNull(weather); + assertEquals(1.84, weather.getTemperature().getValue(), 0.00001); + assertEquals(-0.31, weather.getTemperature().getFeelsLike(), 0.00001); + assertEquals(1.67, weather.getTemperature().getMinTemperature(), 0.00001); + assertEquals(2, weather.getTemperature().getMaxTemperature(), 0.00001); + + // without feels like node + jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + weather = mapper.mapToWeather(jsonString); + + assertNotNull(weather); + assertNotNull(weather.getTemperature()); + assertNull(weather.getTemperature().getFeelsLike()); + assertNotNull(weather.getTemperature().getMinTemperature()); + assertNotNull(weather.getTemperature().getMaxTemperature()); + + // without min temperature node + jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + weather = mapper.mapToWeather(jsonString); + + assertNotNull(weather); + assertNotNull(weather.getTemperature()); + assertNotNull(weather.getTemperature().getFeelsLike()); + assertNull(weather.getTemperature().getMinTemperature()); + assertNotNull(weather.getTemperature().getMaxTemperature()); + + // without max temperature node + jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + weather = mapper.mapToWeather(jsonString); + + assertNotNull(weather); + assertNotNull(weather.getTemperature()); + assertNotNull(weather.getTemperature().getFeelsLike()); + assertNotNull(weather.getTemperature().getMinTemperature()); + assertNull(weather.getTemperature().getMaxTemperature()); + } + + @Test + public void mapToWeather_withWindVariations() { + String jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + + final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); + Weather weather = mapper.mapToWeather(jsonString); + + assertNotNull(weather); + assertEquals(2, weather.getWind().getSpeed(), 0.00001); + assertEquals(250, weather.getWind().getDegrees(), 0.00001); + assertNull(weather.getWind().getGust()); + + // without degrees + jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + weather = mapper.mapToWeather(jsonString); + + assertNotNull(weather); + assertNotNull(weather.getWind()); + assertNull(weather.getWind().getDegrees()); + + // with gust + jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250, + "gust": 2.44 + }, + "snow": { + "1h": 0.2 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + weather = mapper.mapToWeather(jsonString); + + assertNotNull(weather); + assertNotNull(weather.getWind()); + assertNotNull(weather.getWind().getDegrees()); + assertEquals(2.44, weather.getWind().getGust(), 0.00001); + } + + @Test + public void mapToWeather_withRainVariations() { + final String jsonWith1Hr = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "rain": { + "1h": 0.1 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + final String jsonWith3Hr = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "rain": { + "3h": 0.3 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + final String jsonWithBoth = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "rain": { + "1h": 0.1, + "3h": 0.3 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + + final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); + Weather weather = mapper.mapToWeather(jsonWith1Hr); + + // with 1h level only + assertNotNull(weather.getRain()); + assertEquals(0.1, weather.getRain().getOneHourLevel(), 0.00001); + assertNull(weather.getRain().getThreeHourLevel()); + + weather = mapper.mapToWeather(jsonWith3Hr); + + // with 3h level only + assertNotNull(weather.getRain()); + assertNull(weather.getRain().getOneHourLevel()); + assertEquals(0.3, weather.getRain().getThreeHourLevel(), 0.00001); + + weather = mapper.mapToWeather(jsonWithBoth); + + // with both levels + assertNotNull(weather.getRain()); + assertEquals(0.1, weather.getRain().getOneHourLevel(), 0.00001); + assertEquals(0.3, weather.getRain().getThreeHourLevel(), 0.00001); + } + + @Test + public void mapToWeather_withSnowVariations() { + final String jsonWith1Hr = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.1 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + final String jsonWith3Hr = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "3h": 0.3 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + final String jsonWithBoth = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.1, + "3h": 0.3 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + + final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); + Weather weather = mapper.mapToWeather(jsonWith1Hr); + + // with 1h level only + assertNotNull(weather.getSnow()); + assertEquals(0.1, weather.getSnow().getOneHourLevel(), 0.00001); + assertNull(weather.getSnow().getThreeHourLevel()); + + weather = mapper.mapToWeather(jsonWith3Hr); + + // with 3h level only + assertNotNull(weather.getSnow()); + assertNull(weather.getSnow().getOneHourLevel()); + assertEquals(0.3, weather.getSnow().getThreeHourLevel(), 0.00001); + + weather = mapper.mapToWeather(jsonWithBoth); + + // with both levels + assertNotNull(weather.getSnow()); + assertEquals(0.1, weather.getSnow().getOneHourLevel(), 0.00001); + assertEquals(0.3, weather.getSnow().getThreeHourLevel(), 0.00001); + } + + @Test + public void mapToWeather_withLocationVariations() { + String jsonString = """ + { + "coord": { + "lon": 27.5667, + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.1 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); + + Weather weather = mapper.mapToWeather(jsonString); + + assertNotNull(weather.getLocation().getCoordinate()); + assertNotNull(weather.getLocation().getCountryCode()); + + // without coordinates and country code + jsonString = """ + { + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.1 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + weather = mapper.mapToWeather(jsonString); + assertNull(weather.getLocation().getCoordinate()); + assertNull(weather.getLocation().getCountryCode()); + + // coordinates without latitude + jsonString = """ + { + "coord": { + "lon": 27.5667 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.1 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + weather = mapper.mapToWeather(jsonString); + assertNull(weather.getLocation().getCoordinate()); + assertNotNull(weather.getLocation().getCountryCode()); + + // coordinates without longitude + jsonString = """ + { + "coord": { + "lat": 53.9 + }, + "weather": [ + { + "id": 600, + "main": "Snow", + "description": "небольшой снег", + "icon": "13n" + } + ], + "base": "stations", + "main": { + "temp": 1.84, + "feels_like": -0.31, + "temp_min": 1.67, + "temp_max": 2, + "pressure": 1001, + "humidity": 69 + }, + "visibility": 10000, + "wind": { + "speed": 2, + "deg": 250 + }, + "snow": { + "1h": 0.1 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 + } + """; + weather = mapper.mapToWeather(jsonString); + assertNull(weather.getLocation().getCoordinate()); + assertNotNull(weather.getLocation().getCountryCode()); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapperTest.java new file mode 100644 index 0000000..cf4d1b0 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapperTest.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.mapper; + +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord; +import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingRecord; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class GeocodingResponseMapperTest { + + @Test + public void reverseGeocodingResponseMappingTest() { + String jsonResponse = """ + [ + { + "name": "City of London", + "local_names": { + "ar": "مدينة لندن", + "ascii": "City of London", + "bg": "Сити", + "ca": "La City", + "de": "London City", + "el": "Σίτι του Λονδίνου", + "en": "City of London", + "fa": "سیتی لندن", + "feature_name": "City of London", + "fi": "Lontoon City", + "fr": "Cité de Londres", + "gl": "Cidade de Londres", + "he": "הסיטי של לונדון", + "hi": "सिटी ऑफ़ लंदन", + "id": "Kota London", + "it": "Londra", + "ja": "シティ・オブ・ロンドン", + "la": "Civitas Londinium", + "lt": "Londono Sitis", + "pt": "Cidade de Londres", + "ru": "Сити", + "sr": "Сити", + "th": "นครลอนดอน", + "tr": "Londra Şehri", + "vi": "Thành phố Luân Đôn", + "zu": "Idolobha weLondon" + }, + "lat": 51.5128, + "lon": -0.0918, + "country": "GB" + }, + { + "name": "London", + "local_names": { + "af": "Londen", + "ar": "لندن", + "ascii": "London", + "az": "London", + "bg": "Лондон", + "ca": "Londres", + "da": "London", + "de": "London", + "el": "Λονδίνο", + "en": "London", + "eu": "Londres", + "fa": "لندن", + "feature_name": "London", + "fi": "Lontoo", + "fr": "Londres", + "gl": "Londres", + "he": "לונדון", + "hi": "लंदन", + "hr": "London", + "hu": "London", + "id": "London", + "it": "Londra", + "ja": "ロンドン", + "la": "Londinium", + "lt": "Londonas", + "mk": "Лондон", + "nl": "Londen", + "no": "London", + "pl": "Londyn", + "pt": "Londres", + "ro": "Londra", + "ru": "Лондон", + "sk": "Londýn", + "sl": "London", + "sr": "Лондон", + "th": "ลอนดอน", + "tr": "Londra", + "vi": "Luân Đôn", + "zu": "ILondon" + }, + "lat": 51.5085, + "lon": -0.1257, + "country": "GB" + }, + { + "name": "Islington", + "local_names": { + "ascii": "Islington", + "az": "İslinqton", + "fa": "ایزلینتن", + "feature_name": "Islington", + "fr": "District londonien d'Islington", + "he": "איזלינגטון", + "ja": "イズリントン", + "ru": "Ислингтон" + }, + "lat": 51.5362, + "lon": -0.103, + "country": "GB" + }, + { + "name": "Lewisham", + "local_names": { + "ascii": "Lewisham", + "de": "London Borough of Lewisham", + "en": "Lewisham", + "feature_name": "Lewisham", + "fi": "Lewisham", + "fr": "Lewisham", + "hu": "Lewisham kerület", + "nl": "Lewisham", + "no": "Lewisham", + "ro": "Lewisham" + }, + "lat": 51.4535, + "lon": -0.018, + "country": "GB" + }, + { + "name": "Islington", + "local_names": { + "ascii": "Islington", + "de": "London Borough of Islington", + "en": "Islington", + "feature_name": "Islington", + "fr": "Islington", + "nl": "Islington", + "no": "Islington", + "ro": "Islington" + }, + "lat": 51.547, + "lon": -0.1094, + "country": "GB" + } + ] + """; + + List geocodingRecords = new GeocodingResponseMapper().mapGeocodingResponse(jsonResponse); + + assertNotNull(geocodingRecords); + assertEquals(5, geocodingRecords.size()); + } + + public void zipGeocodingInfoResponseMappingTest() { + String jsonResponse = """ + { + "zip": "90210", + "name": "Beverly Hills", + "lat": 34.0901, + "lon": -118.4065, + "country": "US" + } + """; + + ZipCodeGeocodingRecord zipCodeGeocodingRecord = new GeocodingResponseMapper().mapZipCodeGeocodingResponse(jsonResponse); + + assertNotNull(zipCodeGeocodingRecord); + assertEquals("90210", zipCodeGeocodingRecord.getZip()); + assertEquals("Beverly Hills", zipCodeGeocodingRecord.getName()); + assertEquals("US", zipCodeGeocodingRecord.getCountryCode()); + assertEquals(Coordinates.of(34.0901, -118.4065), zipCodeGeocodingRecord.getCoordinates()); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapperTest.java new file mode 100644 index 0000000..4aeba61 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapperTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.mapper; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.*; +import com.github.prominence.openweathermap.api.model.forecast.hourly.*; +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.TimeZone; + +import static org.junit.jupiter.api.Assertions.*; + +class HourlyForecastResponseMapperTest { + + @Test + void forecastMappingTestWithOfficialExample() { + final String jsonResponse = """ + { + "cod": "200", + "message": 0.0179, + "cnt": 96, + "list": [ + { + "dt": 1596632400, + "main": { + "temp": 289.16, + "feels_like": 288.41, + "temp_min": 289.16, + "temp_max": 289.16, + "pressure": 1013, + "sea_level": 1013, + "grnd_level": 1010, + "humidity": 78, + "temp_kf": 0 + }, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "clouds": { + "all": 100 + }, + "wind": { + "speed": 2.03, + "deg": 252, + "gust": 5.46 + }, + "rain": { + "1h": 23.3 + }, + "snow": { + "1h": 27.945 + }, + "visibility": 10000, + "pop": 0.04, + "sys": { + "pod": "n" + }, + "dt_txt": "2020-08-05 13:00:00" + } + ], + "city": { + "id": 2643743, + "name": "London", + "coord": { + "lat": 51.5085, + "lon": -0.1258 + }, + "country": "GB", + "timezone": 0, + "sunrise": 1568958164, + "sunset": 1569002733 + } + } + """; + + final HourlyForecast hourlyForecast = new HourlyForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonResponse); + assertNotNull(hourlyForecast); + + final Location location = hourlyForecast.getLocation(); + assertEquals(2643743, location.getId()); + assertEquals("London", location.getName()); + assertEquals(Coordinates.of(51.5085, -0.1258), location.getCoordinate()); + assertEquals("GB", location.getCountryCode()); + assertEquals(ZoneOffset.ofTotalSeconds(0), location.getZoneOffset()); + assertEquals(LocalDateTime.ofInstant(Instant.ofEpochSecond(1568958164), TimeZone.getDefault().toZoneId()), location.getSunriseTime()); + assertEquals(LocalDateTime.ofInstant(Instant.ofEpochSecond(1569002733), TimeZone.getDefault().toZoneId()), location.getSunsetTime()); + + final WeatherForecast weatherForecast = hourlyForecast.getWeatherForecasts().get(0); + assertEquals(LocalDateTime.ofInstant(Instant.ofEpochSecond(1596632400), TimeZone.getDefault().toZoneId()), weatherForecast.getForecastTime()); + assertEquals("2020-08-05 13:00:00", weatherForecast.getForecastTimeISO()); + assertEquals(DayTime.NIGHT, weatherForecast.getDayTime()); + assertEquals(10000, weatherForecast.getAverageVisibilityInMetres()); + assertEquals(0.04, weatherForecast.getProbabilityOfPrecipitation()); + + final Temperature temperature = weatherForecast.getTemperature(); + assertEquals(289.16, temperature.getValue()); + assertEquals(288.41, temperature.getFeelsLike()); + assertEquals(289.16, temperature.getMinTemperature()); + assertEquals(289.16, temperature.getMaxTemperature()); + + final AtmosphericPressure pressure = weatherForecast.getAtmosphericPressure(); + assertEquals(1013, pressure.getValue()); + assertEquals(1013, pressure.getSeaLevelValue()); + assertEquals(1010, pressure.getGroundLevelValue()); + + final Humidity humidity = weatherForecast.getHumidity(); + assertEquals(78, humidity.getValue()); + + final WeatherState weatherState = weatherForecast.getWeatherStates().get(0); + assertEquals(804, weatherState.getId()); + assertEquals("Clouds", weatherState.getName()); + assertEquals("overcast clouds", weatherState.getDescription()); + assertEquals("04n", weatherState.getIconId()); + + final Clouds clouds = weatherForecast.getClouds(); + assertEquals(100, clouds.getValue()); + + final Wind wind = weatherForecast.getWind(); + assertEquals(2.03, wind.getSpeed()); + assertEquals(252, wind.getDegrees()); + assertEquals(5.46, wind.getGust()); + + final Rain rain = weatherForecast.getRain(); + assertEquals(23.3, rain.getOneHourLevel()); + + final Snow snow = weatherForecast.getSnow(); + assertEquals(27.945, snow.getOneHourLevel()); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapperTest.java new file mode 100644 index 0000000..f55d17f --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapperTest.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2022 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 com.github.prominence.openweathermap.api.mapper; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.onecall.current.CurrentWeatherData; +import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeatherData; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class OneCallWeatherResponseMapperTest { + + @Test + void mapToCurrent() { + final String jsonResponse = """ + { + "lat": 33.44, + "lon": -94.04, + "timezone": "America/Chicago", + "timezone_offset": -21600, + "current": { + "dt": 1618317040, + "sunrise": 1618282134, + "sunset": 1618333901, + "temp": 284.07, + "feels_like": 282.84, + "pressure": 1019, + "humidity": 62, + "dew_point": 277.08, + "uvi": 0.89, + "clouds": 0, + "visibility": 10000, + "wind_speed": 6, + "wind_deg": 300, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "rain": { + "1h": 0.21 + } + }, + "minutely": [ + { + "dt": 1618317060, + "precipitation": 0.205 + } + ], + "hourly": [ + { + "dt": 1618315200, + "temp": 282.58, + "feels_like": 280.4, + "pressure": 1019, + "humidity": 68, + "dew_point": 276.98, + "uvi": 1.4, + "clouds": 19, + "visibility": 306, + "wind_speed": 4.12, + "wind_deg": 296, + "wind_gust": 7.33, + "weather": [ + { + "id": 801, + "main": "Clouds", + "description": "few clouds", + "icon": "02d" + } + ], + "pop": 0 + } + ], + "daily": [ + { + "dt": 1618308000, + "sunrise": 1618282134, + "sunset": 1618333901, + "moonrise": 1618284960, + "moonset": 1618339740, + "moon_phase": 0.04, + "temp": { + "day": 279.79, + "min": 275.09, + "max": 284.07, + "night": 275.09, + "eve": 279.21, + "morn": 278.49 + }, + "feels_like": { + "day": 277.59, + "night": 276.27, + "eve": 276.49, + "morn": 276.27 + }, + "pressure": 1020, + "humidity": 81, + "dew_point": 276.77, + "wind_speed": 3.06, + "wind_deg": 294, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "clouds": 56, + "pop": 0.2, + "rain": 0.62, + "uvi": 1.93 + } + ], + "alerts": [ + { + "sender_name": "NWS Tulsa", + "event": "Heat Advisory", + "start": 1597341600, + "end": 1597366800, + "description": "...HEAT ADVISORY REMAINS IN EFFECT FROM 1 PM THIS AFTERNOON TO\\n8 PM CDT THIS EVENING...\\n* WHAT...Heat index values of 105 to 109 degrees expected.\\n* WHERE...Creek, Okfuskee, Okmulgee, McIntosh, Pittsburg,\\nLatimer, Pushmataha, and Choctaw Counties.\\n* WHEN...From 1 PM to 8 PM CDT Thursday.\\n* IMPACTS...The combination of hot temperatures and high\\nhumidity will combine to create a dangerous situation in which\\nheat illnesses are possible.", + "tags": [ + "Extreme temperature value" + ] + } + ] + } + """; + + final CurrentWeatherData weatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToCurrent(jsonResponse); + + assertNotNull(weatherData); + assertNotEquals(0, weatherData.getDailyList().size()); + assertEquals(1, weatherData.getAlerts().get(0).getTags().size()); + } + + @Test + void mapToHistorical() { + final String jsonResponse = """ + { + "lat": 60.99, + "lon": 30.9, + "timezone": "Europe/Moscow", + "timezone_offset": 10800, + "current": { + "dt": 1586468027, + "sunrise": 1586487424, + "sunset": 1586538297, + "temp": 274.31, + "feels_like": 269.79, + "pressure": 1006, + "humidity": 72, + "dew_point": 270.21, + "clouds": 0, + "visibility": 10000, + "wind_speed": 3, + "wind_deg": 260, + "weather": [ + { + "id": 800, + "main": "Clear", + "description": "clear sky", + "icon": "01n" + } + ] + }, + "hourly": [ + { + "dt": 1586390400, + "temp": 278.41, + "feels_like": 269.43, + "pressure": 1006, + "humidity": 65, + "dew_point": 272.46, + "clouds": 0, + "wind_speed": 9.83, + "wind_deg": 60, + "wind_gust": 15.65, + "weather": [ + { + "id": 800, + "main": "Clear", + "description": "clear sky", + "icon": "01n" + } + ] + } + ] + } + """; + + final HistoricalWeatherData weatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToHistorical(jsonResponse); + + assertNotNull(weatherData); + assertNotNull(weatherData.getHistoricalWeather()); + assertNotEquals(0, weatherData.getHourlyList().size()); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/CoordinateRectangleUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangleUnitTest.java similarity index 77% rename from src/test/java/com/github/prominence/openweathermap/api/model/CoordinateRectangleUnitTest.java rename to src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangleUnitTest.java index 8e05dc8..8c454e2 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/CoordinateRectangleUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangleUnitTest.java @@ -26,116 +26,116 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; -public class CoordinateRectangleUnitTest { +public class CoordinatesRectangleUnitTest { @Test public void whenCreateObjectWithValidArgs_thenObjectIsCreated() { - CoordinateRectangle.withValues(44.5, 22.4, 54.4, 22.2); + CoordinatesRectangle.withValues(44.5, 22.4, 54.4, 22.2); } @Test public void whenCreateObjectWithLatitudeBottomBelowMinus90_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> CoordinateRectangle.withValues(44.5, -91.2, 54.4, 22.2)); + assertThrows(IllegalArgumentException.class, () -> CoordinatesRectangle.withValues(44.5, -91.2, 54.4, 22.2)); } @Test public void whenCreateObjectWithLatitudeBottomAbove90_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> CoordinateRectangle.withValues(44.5, 91.2, 54.4, 22.2)); + assertThrows(IllegalArgumentException.class, () -> CoordinatesRectangle.withValues(44.5, 91.2, 54.4, 22.2)); } @Test public void whenCreateObjectWithLatitudeTopBelowMinus90_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> CoordinateRectangle.withValues(44.5, 22.4, 54.4, -92.3)); + assertThrows(IllegalArgumentException.class, () -> CoordinatesRectangle.withValues(44.5, 22.4, 54.4, -92.3)); } @Test public void whenCreateObjectWithLatitudeTopAbove90_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> CoordinateRectangle.withValues(44.5, 22.5, 54.4, 94.887)); + assertThrows(IllegalArgumentException.class, () -> CoordinatesRectangle.withValues(44.5, 22.5, 54.4, 94.887)); } @Test public void whenCreateObjectWithLongitudeLeftBelowMinus180_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> CoordinateRectangle.withValues(-944.5, 22.4, 54.4, 22.2)); + assertThrows(IllegalArgumentException.class, () -> CoordinatesRectangle.withValues(-944.5, 22.4, 54.4, 22.2)); } @Test public void whenCreateObjectWithLongitudeLeftAbove180_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> CoordinateRectangle.withValues(544.5, 22.4, 54.4, 22.2)); + assertThrows(IllegalArgumentException.class, () -> CoordinatesRectangle.withValues(544.5, 22.4, 54.4, 22.2)); } @Test public void whenCreateObjectWithLongitudeRightBelowMinus180_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> CoordinateRectangle.withValues(44.5, 22.4, -254.4, 22.2)); + assertThrows(IllegalArgumentException.class, () -> CoordinatesRectangle.withValues(44.5, 22.4, -254.4, 22.2)); } @Test public void whenCreateObjectWithLongitudeRightAbove180_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> CoordinateRectangle.withValues(44.5, 22.4, 354.4, 22.2)); + assertThrows(IllegalArgumentException.class, () -> CoordinatesRectangle.withValues(44.5, 22.4, 354.4, 22.2)); } @Test public void whenCreateObjectUsingBuilderWithInvalidLatitudeBottom_thenFail() { - assertThrows(IllegalArgumentException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalArgumentException.class, () -> new CoordinatesRectangle.Builder() .setLatitudeBottom(-1000)); } @Test public void whenCreateObjectUsingBuilderWithInvalidLatitudeBottom2_thenFail() { - assertThrows(IllegalArgumentException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalArgumentException.class, () -> new CoordinatesRectangle.Builder() .setLatitudeBottom(1000)); } @Test public void whenCreateObjectUsingBuilderWithInvalidLatitudeTop_thenFail() { - assertThrows(IllegalArgumentException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalArgumentException.class, () -> new CoordinatesRectangle.Builder() .setLatitudeTop(-1000)); } @Test public void whenCreateObjectUsingBuilderWithInvalidLatitudeTop2_thenFail() { - assertThrows(IllegalArgumentException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalArgumentException.class, () -> new CoordinatesRectangle.Builder() .setLatitudeTop(1000)); } @Test public void whenCreateObjectUsingBuilderWithInvalidLongitudeLeft_thenFail() { - assertThrows(IllegalArgumentException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalArgumentException.class, () -> new CoordinatesRectangle.Builder() .setLongitudeLeft(-1000)); } @Test public void whenCreateObjectUsingBuilderWithInvalidLongitudeLeft2_thenFail() { - assertThrows(IllegalArgumentException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalArgumentException.class, () -> new CoordinatesRectangle.Builder() .setLongitudeLeft(1000)); } @Test public void whenCreateObjectUsingBuilderWithInvalidLongitudeRight_thenFail() { - assertThrows(IllegalArgumentException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalArgumentException.class, () -> new CoordinatesRectangle.Builder() .setLongitudeRight(-1000)); } @Test public void whenCreateObjectUsingBuilderWithInvalidLongitudeRight2_thenFail() { - assertThrows(IllegalArgumentException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalArgumentException.class, () -> new CoordinatesRectangle.Builder() .setLongitudeRight(1000)); } @Test public void whenCreateObjectUsingBuilderWithoutAllPropertiesSet_thenFail() { - assertThrows(IllegalStateException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalStateException.class, () -> new CoordinatesRectangle.Builder() .build()); } @Test public void whenCreateObjectUsingBuilderWithoutAllPropertiesSet1_thenFail() { - assertThrows(IllegalStateException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalStateException.class, () -> new CoordinatesRectangle.Builder() .setLongitudeLeft(10) .build()); } @Test public void whenCreateObjectUsingBuilderWithoutAllPropertiesSet2_thenFail() { - assertThrows(IllegalStateException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalStateException.class, () -> new CoordinatesRectangle.Builder() .setLongitudeRight(10) .setLatitudeBottom(10) .build()); @@ -143,7 +143,7 @@ public class CoordinateRectangleUnitTest { @Test public void whenCreateObjectUsingBuilderWithoutAllPropertiesSet3_thenFail() { - assertThrows(IllegalStateException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalStateException.class, () -> new CoordinatesRectangle.Builder() .setLongitudeLeft(10) .setLatitudeBottom(10) .setLongitudeRight(10) @@ -152,7 +152,7 @@ public class CoordinateRectangleUnitTest { @Test public void whenCreateObjectUsingBuilderWithoutAllPropertiesSet4_thenFail() { - assertThrows(IllegalStateException.class, () -> new CoordinateRectangle.Builder() + assertThrows(IllegalStateException.class, () -> new CoordinatesRectangle.Builder() .setLongitudeLeft(10) .setLatitudeTop(10) .setLatitudeBottom(10) @@ -161,7 +161,7 @@ public class CoordinateRectangleUnitTest { @Test public void whenCreateObjectUsingBuilderWithCorrectUsage_thenOk() { - final CoordinateRectangle rectangle = new CoordinateRectangle.Builder() + final CoordinatesRectangle rectangle = new CoordinatesRectangle.Builder() .setLongitudeRight(10) .setLongitudeLeft(10) .setLatitudeTop(10) @@ -173,7 +173,7 @@ public class CoordinateRectangleUnitTest { @Test public void whenGetAllParameters_thenAllIsFine() { - final CoordinateRectangle rectangle = CoordinateRectangle.withValues(44.5, 22.4, 54.4, 22.2); + final CoordinatesRectangle rectangle = CoordinatesRectangle.withValues(44.5, 22.4, 54.4, 22.2); assertEquals(44.5, rectangle.getLongitudeLeft(), 0.00001); assertEquals(22.4, rectangle.getLatitudeBottom(), 0.00001); assertEquals(54.4, rectangle.getLongitudeRight(), 0.00001); @@ -182,7 +182,7 @@ public class CoordinateRectangleUnitTest { @Test public void whenCallToString_thenAllIsFine() { - final CoordinateRectangle rectangle = CoordinateRectangle.withValues(44.5, 22.4, 54.4, 22.2); + final CoordinatesRectangle rectangle = CoordinatesRectangle.withValues(44.5, 22.4, 54.4, 22.2); assertNotNull(rectangle.toString()); assertNotEquals("", rectangle.toString()); @@ -190,12 +190,12 @@ public class CoordinateRectangleUnitTest { @Test public void whenCallHashCode_thenAllIsFine() { - final CoordinateRectangle first = CoordinateRectangle.withValues(44.5, 22.4, 54.4, 22.2); - final CoordinateRectangle second = CoordinateRectangle.withValues(44.5, 22.4, 54.4, 22.2); + final CoordinatesRectangle first = CoordinatesRectangle.withValues(44.5, 22.4, 54.4, 22.2); + final CoordinatesRectangle second = CoordinatesRectangle.withValues(44.5, 22.4, 54.4, 22.2); assertEquals(first.hashCode(), second.hashCode()); - final CoordinateRectangle third = CoordinateRectangle.withValues(44.5, 22.4, 54.4, 23.566); + final CoordinatesRectangle third = CoordinatesRectangle.withValues(44.5, 22.4, 54.4, 23.566); assertNotEquals(first.hashCode(), third.hashCode()); assertNotEquals(second.hashCode(), third.hashCode()); @@ -203,26 +203,26 @@ public class CoordinateRectangleUnitTest { @Test public void whenCheckEquality_thenAllIsFine() { - CoordinateRectangle first = CoordinateRectangle.withValues(44.5, 22.4, 54.4, 22.2); - CoordinateRectangle second = CoordinateRectangle.withValues(44.5, 22.4, 54.4, 22.2); + CoordinatesRectangle first = CoordinatesRectangle.withValues(44.5, 22.4, 54.4, 22.2); + CoordinatesRectangle second = CoordinatesRectangle.withValues(44.5, 22.4, 54.4, 22.2); assertEquals(first, second); assertEquals(first, first); assertNotEquals(first, new Object()); - first = CoordinateRectangle.withValues(49.5, 22.4, 54.4, 22.2); + first = CoordinatesRectangle.withValues(49.5, 22.4, 54.4, 22.2); assertNotEquals(first, second); - first = CoordinateRectangle.withValues(44.5, 29.4, 54.4, 22.2); + first = CoordinatesRectangle.withValues(44.5, 29.4, 54.4, 22.2); assertNotEquals(first, second); - first = CoordinateRectangle.withValues(44.5, 22.4, 24.4, 22.2); + first = CoordinatesRectangle.withValues(44.5, 22.4, 24.4, 22.2); assertNotEquals(first, second); - first = CoordinateRectangle.withValues(44.5, 22.4, 54.4, -2.2); + first = CoordinatesRectangle.withValues(44.5, 22.4, 54.4, -2.2); assertNotEquals(first, second); } diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/CoordinateUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesUnitTest.java similarity index 65% rename from src/test/java/com/github/prominence/openweathermap/api/model/CoordinateUnitTest.java rename to src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesUnitTest.java index 8b358b3..3c0a535 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/CoordinateUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesUnitTest.java @@ -26,107 +26,107 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; -public class CoordinateUnitTest { +public class CoordinatesUnitTest { @Test public void whenCreateCoordinateWithValidValues_thenObjectCreated() { - Coordinate.of(44, 53); + Coordinates.of(44, 53); } @Test public void whenCreateCoordinateWithInvalidLatitudeBelowMinus90_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Coordinate.of(-333, 44)); + assertThrows(IllegalArgumentException.class, () -> Coordinates.of(-333, 44)); } @Test public void whenCreateCoordinateWithInvalidLatitudeAbove90_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Coordinate.of(223, 44)); + assertThrows(IllegalArgumentException.class, () -> Coordinates.of(223, 44)); } @Test public void whenCreateCoordinateWithInvalidLongitudeBelowMinus180_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Coordinate.of(33, -999)); + assertThrows(IllegalArgumentException.class, () -> Coordinates.of(33, -999)); } @Test public void whenCreateCoordinateWithInvalidLongitudeAbove180_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Coordinate.of(33, 999)); + assertThrows(IllegalArgumentException.class, () -> Coordinates.of(33, 999)); } @Test public void whenSetValidCoordinates_thenAllIsFine() { - final Coordinate coordinate = Coordinate.of(0, 0); + final Coordinates coordinates = Coordinates.of(0, 0); - coordinate.setLatitude(-90); - assertEquals(-90, coordinate.getLatitude(), 0.00001); - coordinate.setLatitude(90); - assertEquals(90, coordinate.getLatitude(), 0.00001); - coordinate.setLatitude(44); - assertEquals(44, coordinate.getLatitude(), 0.00001); + coordinates.setLatitude(-90); + assertEquals(-90, coordinates.getLatitude(), 0.00001); + coordinates.setLatitude(90); + assertEquals(90, coordinates.getLatitude(), 0.00001); + coordinates.setLatitude(44); + assertEquals(44, coordinates.getLatitude(), 0.00001); - coordinate.setLongitude(-180); - assertEquals(-180, coordinate.getLongitude(), 0.00001); - coordinate.setLongitude(180); - assertEquals(180, coordinate.getLongitude(), 0.00001); - coordinate.setLongitude(130); - assertEquals(130, coordinate.getLongitude(), 0.00001); + coordinates.setLongitude(-180); + assertEquals(-180, coordinates.getLongitude(), 0.00001); + coordinates.setLongitude(180); + assertEquals(180, coordinates.getLongitude(), 0.00001); + coordinates.setLongitude(130); + assertEquals(130, coordinates.getLongitude(), 0.00001); } @Test public void whenSetInvalidLatitudeBelowMinus90_thenThrowAnException() { - final Coordinate coordinate = Coordinate.of(0, 0); - assertThrows(IllegalArgumentException.class, () -> coordinate.setLatitude(-91)); + final Coordinates coordinates = Coordinates.of(0, 0); + assertThrows(IllegalArgumentException.class, () -> coordinates.setLatitude(-91)); } @Test public void whenSetInvalidLatitudeAbove90_thenThrowAnException() { - final Coordinate coordinate = Coordinate.of(0, 0); - assertThrows(IllegalArgumentException.class, () -> coordinate.setLatitude(92)); + final Coordinates coordinates = Coordinates.of(0, 0); + assertThrows(IllegalArgumentException.class, () -> coordinates.setLatitude(92)); } @Test public void whenSetInvalidLongitudeBelowMinus180_thenThrowAnException() { - final Coordinate coordinate = Coordinate.of(0, 0); - assertThrows(IllegalArgumentException.class, () -> coordinate.setLongitude(-194)); + final Coordinates coordinates = Coordinates.of(0, 0); + assertThrows(IllegalArgumentException.class, () -> coordinates.setLongitude(-194)); } @Test public void whenSetInvalidLongitudeAbove180_thenThrowAnException() { - final Coordinate coordinate = Coordinate.of(0, 0); - assertThrows(IllegalArgumentException.class, () -> coordinate.setLongitude(444)); + final Coordinates coordinates = Coordinates.of(0, 0); + assertThrows(IllegalArgumentException.class, () -> coordinates.setLongitude(444)); } @Test public void whenGetLatitude_thenAllIsFine() { - final Coordinate coordinate = Coordinate.of(0, 0); - assertEquals(0, coordinate.getLatitude(), 0.00001); + final Coordinates coordinates = Coordinates.of(0, 0); + assertEquals(0, coordinates.getLatitude(), 0.00001); - coordinate.setLatitude(45); + coordinates.setLatitude(45); - assertEquals(45, coordinate.getLatitude(), 0.00001); + assertEquals(45, coordinates.getLatitude(), 0.00001); } @Test public void whenGetLongitude_thenAllIsFine() { - final Coordinate coordinate = Coordinate.of(0, 0); - assertEquals(0, coordinate.getLongitude(), 0.00001); + final Coordinates coordinates = Coordinates.of(0, 0); + assertEquals(0, coordinates.getLongitude(), 0.00001); - coordinate.setLongitude(33); + coordinates.setLongitude(33); - assertEquals(33, coordinate.getLongitude(), 0.00001); + assertEquals(33, coordinates.getLongitude(), 0.00001); } @Test public void whenCallToString_thenAllIsFine() { - final Coordinate coordinate = Coordinate.of(0, 0); - assertNotNull(coordinate.toString()); - assertNotEquals("", coordinate.toString()); + final Coordinates coordinates = Coordinates.of(0, 0); + assertNotNull(coordinates.toString()); + assertNotEquals("", coordinates.toString()); } @Test public void whenCallHashCode_thenAllIsFine() { - final Coordinate first = Coordinate.of(22, 66); - final Coordinate second = Coordinate.of(22, 44); + final Coordinates first = Coordinates.of(22, 66); + final Coordinates second = Coordinates.of(22, 44); assertNotEquals(first.hashCode(), second.hashCode()); @@ -145,8 +145,8 @@ public class CoordinateUnitTest { @Test public void whenCheckEquality_thenAllIsFine() { - final Coordinate first = Coordinate.of(11, 99); - final Coordinate second = Coordinate.of(11, 99); + final Coordinates first = Coordinates.of(11, 99); + final Coordinates second = Coordinates.of(11, 99); assertEquals(first, second); assertEquals(first, first); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsUnitTest.java index a274a8e..d6ac6fe 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsUnitTest.java @@ -24,7 +24,7 @@ package com.github.prominence.openweathermap.api.model.air.pollution; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -36,10 +36,10 @@ public class AirPollutionDetailsUnitTest { @Test public void getCoordinate() { final AirPollutionDetails airPollutionDetails = new AirPollutionDetails(); - final Coordinate coordinate = Coordinate.of(22.3, 44.2); - airPollutionDetails.setCoordinate(coordinate); + final Coordinates coordinates = Coordinates.of(22.3, 44.2); + airPollutionDetails.setCoordinate(coordinates); - assertEquals(coordinate, airPollutionDetails.getCoordinate()); + assertEquals(coordinates, airPollutionDetails.getCoordinate()); } @Test @@ -55,7 +55,7 @@ public class AirPollutionDetailsUnitTest { public void testEquals() { final AirPollutionDetails first = new AirPollutionDetails(); final AirPollutionDetails second = new AirPollutionDetails(); - final Coordinate coordinate = Coordinate.of(22.3, 44.2); + final Coordinates coordinates = Coordinates.of(22.3, 44.2); final List airPollutionRecords = new ArrayList<>(); assertEquals(first, first); @@ -65,11 +65,11 @@ public class AirPollutionDetailsUnitTest { assertEquals(first, second); - first.setCoordinate(coordinate); + first.setCoordinate(coordinates); assertNotEquals(first, second); - second.setCoordinate(coordinate); + second.setCoordinate(coordinates); assertEquals(first, second); @@ -86,11 +86,11 @@ public class AirPollutionDetailsUnitTest { public void testHashCode() { final AirPollutionDetails first = new AirPollutionDetails(); final AirPollutionDetails second = new AirPollutionDetails(); - final Coordinate coordinate = Coordinate.of(22.3, 44.2); + final Coordinates coordinates = Coordinates.of(22.3, 44.2); assertEquals(first.hashCode(), second.hashCode()); - first.setCoordinate(coordinate); + first.setCoordinate(coordinates); assertNotEquals(first.hashCode(), second.hashCode()); } diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/ForecastUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/ForecastUnitTest.java similarity index 95% rename from src/test/java/com/github/prominence/openweathermap/api/model/forecast/ForecastUnitTest.java rename to src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/ForecastUnitTest.java index 164d935..42d3968 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/ForecastUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/ForecastUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/LocationUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationUnitTest.java similarity index 92% rename from src/test/java/com/github/prominence/openweathermap/api/model/forecast/LocationUnitTest.java rename to src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationUnitTest.java index 303c464..103a5dc 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/LocationUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,9 +20,9 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; @@ -95,10 +95,10 @@ public class LocationUnitTest { @Test public void whenSetCoordinate_thenValueIsSet() { final Location location = Location.withValues(33, "test"); - final Coordinate coordinate = Coordinate.of(33.2, 64.2); - location.setCoordinate(coordinate); + final Coordinates coordinates = Coordinates.of(33.2, 64.2); + location.setCoordinate(coordinates); - assertEquals(coordinate, location.getCoordinate()); + assertEquals(coordinates, location.getCoordinate()); } @Test @@ -115,7 +115,7 @@ public class LocationUnitTest { assertNotEquals("", location.toString()); - location.setCoordinate(Coordinate.of(33.2, 56.3)); + location.setCoordinate(Coordinates.of(33.2, 56.3)); assertNotEquals("", location.toString()); @@ -201,13 +201,13 @@ public class LocationUnitTest { assertEquals(one, two); - final Coordinate coordinate = Coordinate.of(33.5, -22.4); + final Coordinates coordinates = Coordinates.of(33.5, -22.4); - one.setCoordinate(coordinate); + one.setCoordinate(coordinates); assertNotEquals(one, two); - two.setCoordinate(coordinate); + two.setCoordinate(coordinates); assertEquals(one, two); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/RainUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/RainUnitTest.java similarity index 96% rename from src/test/java/com/github/prominence/openweathermap/api/model/forecast/RainUnitTest.java rename to src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/RainUnitTest.java index ffc6c98..2b1807e 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/RainUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/RainUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/SnowUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/SnowUnitTest.java similarity index 96% rename from src/test/java/com/github/prominence/openweathermap/api/model/forecast/SnowUnitTest.java rename to src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/SnowUnitTest.java index a7037a4..b4b65fa 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/SnowUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/SnowUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; import org.junit.jupiter.api.Test; @@ -32,6 +32,7 @@ public class SnowUnitTest { Snow.withThreeHourLevelValue(2222.3); Snow.withThreeHourLevelValue(0); } + @Test public void whenCreateWithInvalidData_thenFail() { assertThrows(IllegalArgumentException.class, () -> Snow.withThreeHourLevelValue(-20)); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/WeatherForecastUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecastUnitTest.java similarity index 98% rename from src/test/java/com/github/prominence/openweathermap/api/model/forecast/WeatherForecastUnitTest.java rename to src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecastUnitTest.java index aee9951..7e32251 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/WeatherForecastUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecastUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,7 +20,7 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; import com.github.prominence.openweathermap.api.model.*; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/WindUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WindUnitTest.java similarity index 96% rename from src/test/java/com/github/prominence/openweathermap/api/model/forecast/WindUnitTest.java rename to src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WindUnitTest.java index 5c58871..347732c 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/WindUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WindUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,8 +20,9 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model.forecast; +package com.github.prominence.openweathermap.api.model.forecast.free; +import com.github.prominence.openweathermap.api.model.Wind; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/CurrentUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/CurrentUnitTest.java index 196af22..3adeef4 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/CurrentUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/CurrentUnitTest.java @@ -25,9 +25,11 @@ package com.github.prominence.openweathermap.api.model.onecall; import com.github.prominence.openweathermap.api.model.Clouds; import com.github.prominence.openweathermap.api.model.Humidity; import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.Wind; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -63,9 +65,9 @@ public class CurrentUnitTest { public void getWeatherState() { final Current current = new Current(); final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - current.setWeatherState(weatherState); + current.setWeatherStates(List.of(weatherState)); - assertEquals(weatherState, current.getWeatherState()); + assertEquals(weatherState, current.getWeatherStates().get(0)); } @Test @@ -211,11 +213,11 @@ public class CurrentUnitTest { final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - first.setWeatherState(weatherState); + first.setWeatherStates(List.of(weatherState)); assertNotEquals(first, second); - second.setWeatherState(weatherState); + second.setWeatherStates(List.of(weatherState)); assertEquals(first, second); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/WindUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/WindUnitTest.java index 61c0acc..d357510 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/WindUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/WindUnitTest.java @@ -23,6 +23,7 @@ package com.github.prominence.openweathermap.api.model.onecall; import org.junit.jupiter.api.Test; +import com.github.prominence.openweathermap.api.model.Wind; import static org.junit.jupiter.api.Assertions.*; diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/AlertUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/AlertUnitTest.java index bcbd3d0..4420e42 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/AlertUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/AlertUnitTest.java @@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; +import java.util.Collections; import static org.junit.jupiter.api.Assertions.*; @@ -131,8 +132,8 @@ public class AlertUnitTest { @Test public void getHashCode() { - final Alert event1 = new Alert("Sender", "Event1", LocalDateTime.now(), LocalDateTime.now().plus(2, ChronoUnit.HOURS), "Description1"); - final Alert event2 = new Alert("Sender", "Event2", LocalDateTime.now(), LocalDateTime.now().plus(2, ChronoUnit.HOURS), "Description2"); + final Alert event1 = new Alert("Sender", "Event1", LocalDateTime.now(), LocalDateTime.now().plus(2, ChronoUnit.HOURS), "Description1", Collections.emptyList()); + final Alert event2 = new Alert("Sender", "Event2", LocalDateTime.now(), LocalDateTime.now().plus(2, ChronoUnit.HOURS), "Description2", Collections.emptyList()); assertEquals(event1.hashCode(), event1.hashCode()); assertNotEquals(event1.hashCode(), event2.hashCode()); @@ -140,7 +141,7 @@ public class AlertUnitTest { @Test public void getToString() { - final Alert alert = new Alert("Sender", "Event", LocalDateTime.now(), LocalDateTime.now().plus(2, ChronoUnit.HOURS), "Description"); + final Alert alert = new Alert("Sender", "Event", LocalDateTime.now(), LocalDateTime.now().plus(2, ChronoUnit.HOURS), "Description", Collections.emptyList()); assertNotNull(alert.toString()); assertNotEquals("", alert.toString()); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherDataUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherDataUnitTest.java index 811fca6..749c26c 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherDataUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherDataUnitTest.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.model.onecall.current; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.model.onecall.Current; import org.junit.jupiter.api.Test; @@ -37,10 +37,10 @@ public class CurrentWeatherDataUnitTest { @Test public void getCoordinate() { final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); - final Coordinate coordinate = Coordinate.of(11.2, 43.2); - currentWeatherData.setCoordinate(coordinate); + final Coordinates coordinates = Coordinates.of(11.2, 43.2); + currentWeatherData.setCoordinate(coordinates); - assertEquals(coordinate, currentWeatherData.getCoordinate()); + assertEquals(coordinates, currentWeatherData.getCoordinate()); } @Test @@ -115,7 +115,7 @@ public class CurrentWeatherDataUnitTest { assertNotEquals(first, null); assertNotEquals(first, new Object()); - final Coordinate coordinate = Coordinate.of(11, 12); + final Coordinates coordinates = Coordinates.of(11, 12); final ZoneId timeZone = ZoneId.of("GMT"); final ZoneOffset offset = ZoneOffset.UTC; final Current current = new Current(); @@ -126,11 +126,11 @@ public class CurrentWeatherDataUnitTest { assertEquals(first, second); - first.setCoordinate(coordinate); + first.setCoordinate(coordinates); assertNotEquals(first, second); - second.setCoordinate(coordinate); + second.setCoordinate(coordinates); assertEquals(first, second); @@ -198,7 +198,7 @@ public class CurrentWeatherDataUnitTest { assertEquals(first.hashCode(), second.hashCode()); - first.setCoordinate(Coordinate.of(11, 42)); + first.setCoordinate(Coordinates.of(11, 42)); assertNotEquals(first.hashCode(), second.hashCode()); } @@ -206,7 +206,7 @@ public class CurrentWeatherDataUnitTest { @Test public void getToString() { final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); - currentWeatherData.setCoordinate(Coordinate.of(32, 22)); + currentWeatherData.setCoordinate(Coordinates.of(32, 22)); assertNotNull(currentWeatherData.toString()); assertNotEquals("", currentWeatherData.toString()); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyUnitTest.java index 5fc2200..8a1f676 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyUnitTest.java @@ -26,10 +26,11 @@ import com.github.prominence.openweathermap.api.model.Clouds; import com.github.prominence.openweathermap.api.model.Humidity; import com.github.prominence.openweathermap.api.model.WeatherState; import com.github.prominence.openweathermap.api.model.onecall.AtmosphericPressure; -import com.github.prominence.openweathermap.api.model.onecall.Wind; +import com.github.prominence.openweathermap.api.model.Wind; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -65,9 +66,9 @@ public class DailyUnitTest { public void getWeatherState() { final Daily daily = new Daily(); final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - daily.setWeatherState(weatherState); + daily.setWeatherStates(List.of(weatherState)); - assertEquals(weatherState, daily.getWeatherState()); + assertEquals(weatherState, daily.getWeatherStates().get(0)); } @Test @@ -224,11 +225,11 @@ public class DailyUnitTest { final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - first.setWeatherState(weatherState); + first.setWeatherStates(List.of(weatherState)); assertNotEquals(first, second); - second.setWeatherState(weatherState); + second.setWeatherStates(List.of(weatherState)); assertEquals(first, second); @@ -347,7 +348,7 @@ public class DailyUnitTest { final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - daily.setWeatherState(weatherState); + daily.setWeatherStates(List.of(weatherState)); assertNotNull(daily.toString()); assertNotEquals("", daily.toString()); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/HourlyUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/HourlyUnitTest.java index 81c17b7..938ef9c 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/HourlyUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/HourlyUnitTest.java @@ -25,10 +25,12 @@ package com.github.prominence.openweathermap.api.model.onecall.current; import com.github.prominence.openweathermap.api.model.Clouds; import com.github.prominence.openweathermap.api.model.Humidity; import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.Wind; import com.github.prominence.openweathermap.api.model.onecall.*; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -46,9 +48,9 @@ public class HourlyUnitTest { public void getWeatherState() { final Hourly hourly = new Hourly(); final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - hourly.setWeatherState(weatherState); + hourly.setWeatherStates(List.of(weatherState)); - assertEquals(weatherState, hourly.getWeatherState()); + assertEquals(weatherState, hourly.getWeatherStates().get(0)); } @Test @@ -193,11 +195,11 @@ public class HourlyUnitTest { assertEquals(first, second); - first.setWeatherState(weatherState); + first.setWeatherStates(List.of(weatherState)); assertNotEquals(first, second); - second.setWeatherState(weatherState); + second.setWeatherStates(List.of(weatherState)); assertEquals(first, second); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherDataUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherDataUnitTest.java index 42a28a9..7f51b3d 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherDataUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherDataUnitTest.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.model.onecall.historical; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import org.junit.jupiter.api.Test; import java.time.ZoneId; @@ -36,10 +36,10 @@ public class HistoricalWeatherDataUnitTest { @Test public void getCoordinate() { final HistoricalWeatherData historicalWeatherData = new HistoricalWeatherData(); - final Coordinate coordinate = Coordinate.of(11.2, 43.2); - historicalWeatherData.setCoordinate(coordinate); + final Coordinates coordinates = Coordinates.of(11.2, 43.2); + historicalWeatherData.setCoordinate(coordinates); - assertEquals(coordinate, historicalWeatherData.getCoordinate()); + assertEquals(coordinates, historicalWeatherData.getCoordinate()); } @Test @@ -87,7 +87,7 @@ public class HistoricalWeatherDataUnitTest { assertNotEquals(first, null); assertNotEquals(first, new Object()); - final Coordinate coordinate = Coordinate.of(11, 12); + final Coordinates coordinates = Coordinates.of(11, 12); final ZoneId timeZone = ZoneId.of("GMT"); final ZoneOffset offset = ZoneOffset.UTC; final HistoricalWeather historicalWeather = new HistoricalWeather(); @@ -95,11 +95,11 @@ public class HistoricalWeatherDataUnitTest { assertEquals(first, second); - first.setCoordinate(coordinate); + first.setCoordinate(coordinates); assertNotEquals(first, second); - second.setCoordinate(coordinate); + second.setCoordinate(coordinates); assertEquals(first, second); @@ -143,7 +143,7 @@ public class HistoricalWeatherDataUnitTest { assertEquals(first.hashCode(), second.hashCode()); - first.setCoordinate(Coordinate.of(11, 42)); + first.setCoordinate(Coordinates.of(11, 42)); assertNotEquals(first.hashCode(), second.hashCode()); } @@ -151,7 +151,7 @@ public class HistoricalWeatherDataUnitTest { @Test public void getToString() { final HistoricalWeatherData historicalWeatherData = new HistoricalWeatherData(); - historicalWeatherData.setCoordinate(Coordinate.of(32, 22)); + historicalWeatherData.setCoordinate(Coordinates.of(32, 22)); assertNotNull(historicalWeatherData.toString()); assertNotEquals("", historicalWeatherData.toString()); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherUnitTest.java index 620747e..afbb747 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherUnitTest.java @@ -25,10 +25,12 @@ package com.github.prominence.openweathermap.api.model.onecall.historical; import com.github.prominence.openweathermap.api.model.Clouds; import com.github.prominence.openweathermap.api.model.Humidity; import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.Wind; import com.github.prominence.openweathermap.api.model.onecall.*; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -64,9 +66,9 @@ public class HistoricalWeatherUnitTest { public void getWeatherState() { final HistoricalWeather historicalWeather = new HistoricalWeather(); final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - historicalWeather.setWeatherState(weatherState); + historicalWeather.setWeatherStates(List.of(weatherState)); - assertEquals(weatherState, historicalWeather.getWeatherState()); + assertEquals(weatherState, historicalWeather.getWeatherStates().get(0)); } @Test @@ -212,11 +214,11 @@ public class HistoricalWeatherUnitTest { final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - first.setWeatherState(weatherState); + first.setWeatherStates(List.of(weatherState)); assertNotEquals(first, second); - second.setWeatherState(weatherState); + second.setWeatherStates(List.of(weatherState)); assertEquals(first, second); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistoricalUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistoricalUnitTest.java index 0b04fa3..bf8832b 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistoricalUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistoricalUnitTest.java @@ -25,10 +25,12 @@ package com.github.prominence.openweathermap.api.model.onecall.historical; import com.github.prominence.openweathermap.api.model.Clouds; import com.github.prominence.openweathermap.api.model.Humidity; import com.github.prominence.openweathermap.api.model.WeatherState; +import com.github.prominence.openweathermap.api.model.Wind; import com.github.prominence.openweathermap.api.model.onecall.*; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -46,9 +48,9 @@ public class HourlyHistoricalUnitTest { public void getWeatherState() { final HourlyHistorical hourlyHistorical = new HourlyHistorical(); final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - hourlyHistorical.setWeatherState(weatherState); + hourlyHistorical.setWeatherStates(List.of(weatherState)); - assertEquals(weatherState, hourlyHistorical.getWeatherState()); + assertEquals(weatherState, hourlyHistorical.getWeatherStates().get(0)); } @Test @@ -153,11 +155,11 @@ public class HourlyHistoricalUnitTest { assertEquals(first, second); - first.setWeatherState(weatherState); + first.setWeatherStates(List.of(weatherState)); assertNotEquals(first, second); - second.setWeatherState(weatherState); + second.setWeatherStates(List.of(weatherState)); assertEquals(first, second); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/weather/LocationUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/weather/LocationUnitTest.java index dfcd359..4bccf86 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/weather/LocationUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/weather/LocationUnitTest.java @@ -22,7 +22,7 @@ package com.github.prominence.openweathermap.api.model.weather; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; @@ -95,10 +95,10 @@ public class LocationUnitTest { @Test public void whenSetCoordinate_thenValueIsSet() { final Location location = Location.withValues(33, "test"); - final Coordinate coordinate = Coordinate.of(33.2, 64.2); - location.setCoordinate(coordinate); + final Coordinates coordinates = Coordinates.of(33.2, 64.2); + location.setCoordinate(coordinates); - assertEquals(coordinate, location.getCoordinate()); + assertEquals(coordinates, location.getCoordinate()); } @Test @@ -107,7 +107,7 @@ public class LocationUnitTest { assertNotEquals("", location.toString()); - location.setCoordinate(Coordinate.of(33.2, 56.3)); + location.setCoordinate(Coordinates.of(33.2, 56.3)); assertNotEquals("", location.toString()); @@ -189,13 +189,13 @@ public class LocationUnitTest { assertEquals(one, two); - final Coordinate coordinate = Coordinate.of(33.5, -22.4); + final Coordinates coordinates = Coordinates.of(33.5, -22.4); - one.setCoordinate(coordinate); + one.setCoordinate(coordinates); assertNotEquals(one, two); - two.setCoordinate(coordinate); + two.setCoordinate(coordinates); assertEquals(one, two); } diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/weather/WeatherUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/weather/WeatherUnitTest.java index b92e446..e2df79f 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/weather/WeatherUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/weather/WeatherUnitTest.java @@ -26,6 +26,8 @@ import com.github.prominence.openweathermap.api.model.*; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -201,11 +203,11 @@ public class WeatherUnitTest { assertEquals(one, two); final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - one.setWeatherState(weatherState); + one.setWeatherStates(Collections.singletonList(weatherState)); assertNotEquals(one, two); - two.setWeatherState(weatherState); + two.setWeatherStates(Collections.singletonList(weatherState)); assertEquals(one, two); diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/weather/WindUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/weather/WindUnitTest.java index 2da62a5..45f54ba 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/weather/WindUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/weather/WindUnitTest.java @@ -22,6 +22,7 @@ package com.github.prominence.openweathermap.api.model.weather; +import com.github.prominence.openweathermap.api.model.Wind; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionIntegrationTest.java index 657cd15..715baba 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionIntegrationTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionIntegrationTest.java @@ -25,7 +25,7 @@ package com.github.prominence.openweathermap.api.request.air.pollution; import com.github.prominence.openweathermap.api.ApiTest; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails; import org.junit.jupiter.api.Test; @@ -40,7 +40,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final AirPollutionDetails airPollutionDetails = getClient() .airPollution() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .retrieve() .asJava(); @@ -56,7 +56,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final String jsonString = getClient() .airPollution() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .retrieve() .asJSON(); @@ -69,7 +69,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final CompletableFuture pollutionDetailsFuture = getClient() .airPollution() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .retrieveAsync() .asJava(); @@ -82,7 +82,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final CompletableFuture jsonStringFuture = getClient() .airPollution() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .retrieveAsync() .asJSON(); @@ -97,7 +97,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final AirPollutionDetails airPollutionDetails = getClient() .airPollution() .forecast() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .retrieve() .asJava(); @@ -113,7 +113,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final String jsonString = getClient() .airPollution() .forecast() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .retrieve() .asJSON(); @@ -126,7 +126,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final CompletableFuture pollutionDetailsFuture = getClient() .airPollution() .forecast() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .retrieveAsync() .asJava(); @@ -139,7 +139,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final CompletableFuture jsonStringFuture = getClient() .airPollution() .forecast() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .retrieveAsync() .asJSON(); @@ -154,7 +154,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final AirPollutionDetails airPollutionDetails = getClient() .airPollution() .historical() - .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999) + .byCoordinateAndPeriod(Coordinates.of(53.54, 27.34), 1606223802, 1606482999) .retrieve() .asJava(); @@ -170,7 +170,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final String jsonString = getClient() .airPollution() .historical() - .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999) + .byCoordinateAndPeriod(Coordinates.of(53.54, 27.34), 1606223802, 1606482999) .retrieve() .asJSON(); @@ -183,7 +183,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final CompletableFuture pollutionDetailsFuture = getClient() .airPollution() .historical() - .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999) + .byCoordinateAndPeriod(Coordinates.of(53.54, 27.34), 1606223802, 1606482999) .retrieveAsync() .asJava(); @@ -196,7 +196,7 @@ public class AirPollutionIntegrationTest extends ApiTest { final CompletableFuture jsonStringFuture = getClient() .airPollution() .historical() - .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999) + .byCoordinateAndPeriod(Coordinates.of(53.54, 27.34), 1606223802, 1606482999) .retrieveAsync() .asJSON(); diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastIntegrationTest.java index d9306c1..51887ae 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastIntegrationTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastIntegrationTest.java @@ -28,9 +28,9 @@ import com.github.prominence.openweathermap.api.enums.Language; import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.exception.InvalidAuthTokenException; import com.github.prominence.openweathermap.api.exception.NoDataFoundException; -import com.github.prominence.openweathermap.api.model.Coordinate; -import com.github.prominence.openweathermap.api.model.forecast.Forecast; -import com.github.prominence.openweathermap.api.model.forecast.WeatherForecast; +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.forecast.free.Forecast; +import com.github.prominence.openweathermap.api.model.forecast.free.WeatherForecast; import org.junit.jupiter.api.Test; import java.util.concurrent.CompletableFuture; @@ -249,7 +249,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { public void whenGetForecastByCoordinatesRequestAsJava_thenReturnNotNull() { final Forecast forecast = getClient() .forecast5Day3HourStep() - .byCoordinate(Coordinate.of(5, 5)) + .byCoordinates(Coordinates.of(5, 5)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .count(15) @@ -273,7 +273,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { public void whenGetForecastByCoordinatesRequestAsJSON_thenReturnNotNull() { final String forecastJson = getClient() .forecast5Day3HourStep() - .byCoordinate(Coordinate.of(5, 5)) + .byCoordinates(Coordinates.of(5, 5)) .language(Language.SPANISH) .unitSystem(UnitSystem.IMPERIAL) .count(15) @@ -287,7 +287,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { public void whenGetForecastByCoordinatesRequestAsXML_thenReturnNotNull() { final String forecastXml = getClient() .forecast5Day3HourStep() - .byCoordinate(Coordinate.of(5, 5)) + .byCoordinates(Coordinates.of(5, 5)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieve() diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastResponseMapperUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastResponseMapperUnitTest.java index d8a6ce2..abed39b 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastResponseMapperUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastResponseMapperUnitTest.java @@ -24,7 +24,7 @@ package com.github.prominence.openweathermap.api.request.forecast.free; import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.mapper.FiveDayThreeHourStepForecastResponseMapper; -import com.github.prominence.openweathermap.api.model.forecast.Forecast; +import com.github.prominence.openweathermap.api.model.forecast.free.Forecast; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherResponseMapperUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherResponseMapperUnitTest.java index d34b4ac..268b577 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherResponseMapperUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherResponseMapperUnitTest.java @@ -101,7 +101,520 @@ public class OneCallWeatherResponseMapperUnitTest { assertNotNull(historicalWeatherData); assertNull(historicalWeatherData.getHistoricalWeather()); - jsonString = "{\"lat\":60.99,\"lon\":30.9,\"timezone\":\"Europe/Moscow\",\"timezone_offset\":10800,\"current\":{\"dt\":1617739371,\"sunrise\":1617678248,\"sunset\":1617727984,\"temp\":0,\"feels_like\":-10.26,\"pressure\":986,\"humidity\":73,\"dew_point\":-3.77,\"uvi\":1.69,\"visibility\":20000,\"clouds\":33,\"wind_speed\":11.04,\"wind_deg\":196,\"wind_gust\":15.97,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}]},\"hourly\":[{\"dt\":1617667200,\"temp\":0.22,\"feels_like\":-7.76,\"pressure\":988,\"humidity\":80,\"dew_point\":-2.49,\"clouds\":100,\"wind_speed\":8.02,\"wind_deg\":199,\"wind_gust\":10.5,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}]},{\"dt\":1617670800,\"temp\":0.22,\"feels_like\":-7.76,\"pressure\":988,\"humidity\":80,\"dew_point\":-2.49,\"clouds\":100,\"wind_speed\":8.02,\"wind_deg\":199,\"wind_gust\":10.5,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}]},{\"dt\":1617674400,\"temp\":0.22,\"feels_like\":-7.76,\"pressure\":988,\"humidity\":80,\"dew_point\":-2.49,\"clouds\":100,\"wind_speed\":8.02,\"wind_deg\":199,\"wind_gust\":10.5,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}]},{\"dt\":1617678000,\"temp\":0.22,\"feels_like\":-7.76,\"pressure\":988,\"humidity\":80,\"dew_point\":-2.49,\"clouds\":100,\"wind_speed\":8.02,\"wind_deg\":199,\"wind_gust\":10.5,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}]},{\"dt\":1617681600,\"temp\":0.22,\"feels_like\":-7.76,\"pressure\":988,\"humidity\":80,\"dew_point\":-2.49,\"clouds\":100,\"wind_speed\":8.02,\"wind_deg\":199,\"wind_gust\":10.5,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}]},{\"dt\":1617685200,\"temp\":0.22,\"feels_like\":-7.76,\"pressure\":988,\"humidity\":80,\"dew_point\":-2.49,\"clouds\":100,\"wind_speed\":8.02,\"wind_deg\":199,\"wind_gust\":10.5,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}]},{\"dt\":1617688800,\"temp\":0.22,\"feels_like\":-7.76,\"pressure\":988,\"humidity\":80,\"dew_point\":-2.49,\"clouds\":100,\"wind_speed\":8.02,\"wind_deg\":199,\"wind_gust\":10.5,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}]},{\"dt\":1617692400,\"temp\":0.49,\"feels_like\":-7.81,\"pressure\":988,\"humidity\":76,\"dew_point\":-2.87,\"clouds\":100,\"wind_speed\":8.41,\"wind_deg\":196,\"wind_gust\":10.8,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}]},{\"dt\":1617696000,\"temp\":0.74,\"feels_like\":-7.87,\"pressure\":988,\"humidity\":74,\"dew_point\":-2.97,\"clouds\":100,\"wind_speed\":8.83,\"wind_deg\":196,\"wind_gust\":11.38,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}]},{\"dt\":1617699600,\"temp\":0.98,\"feels_like\":-7.65,\"pressure\":989,\"humidity\":69,\"dew_point\":-3.59,\"clouds\":99,\"wind_speed\":8.75,\"wind_deg\":203,\"wind_gust\":11.54,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}]},{\"dt\":1617703200,\"temp\":1.18,\"feels_like\":-7.24,\"pressure\":989,\"humidity\":67,\"dew_point\":-3.77,\"clouds\":86,\"wind_speed\":8.41,\"wind_deg\":205,\"wind_gust\":11.41,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}]},{\"dt\":1617706800,\"temp\":1.39,\"feels_like\":-6.84,\"pressure\":990,\"humidity\":66,\"dew_point\":-3.77,\"clouds\":77,\"wind_speed\":8.15,\"wind_deg\":199,\"wind_gust\":10.92,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}]},{\"dt\":1617710400,\"temp\":1.53,\"feels_like\":-6.93,\"pressure\":990,\"humidity\":66,\"dew_point\":-3.65,\"clouds\":42,\"wind_speed\":8.49,\"wind_deg\":191,\"wind_gust\":11.93,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}]},{\"dt\":1617714000,\"temp\":1.76,\"feels_like\":-7.16,\"pressure\":991,\"humidity\":66,\"dew_point\":-3.46,\"clouds\":47,\"wind_speed\":9.19,\"wind_deg\":199,\"wind_gust\":13.07,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}]},{\"dt\":1617717600,\"temp\":1.64,\"feels_like\":-7.85,\"pressure\":991,\"humidity\":72,\"dew_point\":-2.53,\"clouds\":67,\"wind_speed\":10.18,\"wind_deg\":205,\"wind_gust\":13.98,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}]},{\"dt\":1617721200,\"temp\":1.49,\"feels_like\":-7.59,\"pressure\":991,\"humidity\":76,\"dew_point\":-2.01,\"clouds\":52,\"wind_speed\":9.7,\"wind_deg\":197,\"wind_gust\":13.49,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}]},{\"dt\":1617724800,\"temp\":1.68,\"feels_like\":-7.57,\"pressure\":992,\"humidity\":76,\"dew_point\":-1.85,\"clouds\":42,\"wind_speed\":9.97,\"wind_deg\":193,\"wind_gust\":14.21,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}]},{\"dt\":1617728400,\"temp\":1.67,\"feels_like\":-7.65,\"pressure\":984,\"humidity\":75,\"dew_point\":-2.01,\"clouds\":38,\"wind_speed\":10.04,\"wind_deg\":190,\"wind_gust\":14.59,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}]},{\"dt\":1617732000,\"temp\":1.67,\"feels_like\":-8.41,\"pressure\":984,\"humidity\":73,\"dew_point\":-2.34,\"clouds\":37,\"wind_speed\":11.06,\"wind_deg\":191,\"wind_gust\":16.02,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}]},{\"dt\":1617735600,\"temp\":1.11,\"feels_like\":-9.22,\"pressure\":985,\"humidity\":73,\"dew_point\":-2.82,\"clouds\":56,\"wind_speed\":11.32,\"wind_deg\":195,\"wind_gust\":16.33,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}]},{\"dt\":1617739200,\"temp\":0,\"feels_like\":-10.26,\"pressure\":986,\"humidity\":73,\"dew_point\":-3.77,\"clouds\":33,\"wind_speed\":11.04,\"wind_deg\":196,\"wind_gust\":15.97,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}]},{\"dt\":1617742800,\"temp\":0.56,\"feels_like\":-9.73,\"pressure\":986,\"humidity\":72,\"dew_point\":-3.45,\"clouds\":26,\"wind_deg\":202,\"wind_gust\":16.22,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}]},{\"dt\":1617746400,\"temp\":0.56,\"feels_like\":-9.57,\"pressure\":986,\"humidity\":72,\"dew_point\":-3.45,\"clouds\":21,\"wind_speed\":10.92,\"wind_deg\":206,\"wind_gust\":16.09,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}]},{\"dt\":1617750000,\"temp\":0,\"feels_like\":-9.73,\"pressure\":987,\"humidity\":74,\"dew_point\":-3.61,\"clouds\":19,\"wind_speed\":10.31,\"wind_deg\":207,\"wind_gust\":15.05,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}]}]}"; + jsonString = """ + { + "lat": 60.99, + "lon": 30.9, + "timezone": "Europe/Moscow", + "timezone_offset": 10800, + "current": { + "dt": 1617739371, + "sunrise": 1617678248, + "sunset": 1617727984, + "temp": 0, + "feels_like": -10.26, + "pressure": 986, + "humidity": 73, + "dew_point": -3.77, + "uvi": 1.69, + "visibility": 20000, + "clouds": 33, + "wind_speed": 11.04, + "wind_deg": 196, + "wind_gust": 15.97, + "weather": [ + { + "id": 802, + "main": "Clouds", + "description": "scattered clouds", + "icon": "03n" + } + ] + }, + "hourly": [ + { + "dt": 1617667200, + "temp": 0.22, + "feels_like": -7.76, + "pressure": 988, + "humidity": 80, + "dew_point": -2.49, + "clouds": 100, + "wind_speed": 8.02, + "wind_deg": 199, + "wind_gust": 10.5, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ] + }, + { + "dt": 1617670800, + "temp": 0.22, + "feels_like": -7.76, + "pressure": 988, + "humidity": 80, + "dew_point": -2.49, + "clouds": 100, + "wind_speed": 8.02, + "wind_deg": 199, + "wind_gust": 10.5, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ] + }, + { + "dt": 1617674400, + "temp": 0.22, + "feels_like": -7.76, + "pressure": 988, + "humidity": 80, + "dew_point": -2.49, + "clouds": 100, + "wind_speed": 8.02, + "wind_deg": 199, + "wind_gust": 10.5, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ] + }, + { + "dt": 1617678000, + "temp": 0.22, + "feels_like": -7.76, + "pressure": 988, + "humidity": 80, + "dew_point": -2.49, + "clouds": 100, + "wind_speed": 8.02, + "wind_deg": 199, + "wind_gust": 10.5, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ] + }, + { + "dt": 1617681600, + "temp": 0.22, + "feels_like": -7.76, + "pressure": 988, + "humidity": 80, + "dew_point": -2.49, + "clouds": 100, + "wind_speed": 8.02, + "wind_deg": 199, + "wind_gust": 10.5, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617685200, + "temp": 0.22, + "feels_like": -7.76, + "pressure": 988, + "humidity": 80, + "dew_point": -2.49, + "clouds": 100, + "wind_speed": 8.02, + "wind_deg": 199, + "wind_gust": 10.5, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617688800, + "temp": 0.22, + "feels_like": -7.76, + "pressure": 988, + "humidity": 80, + "dew_point": -2.49, + "clouds": 100, + "wind_speed": 8.02, + "wind_deg": 199, + "wind_gust": 10.5, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617692400, + "temp": 0.49, + "feels_like": -7.81, + "pressure": 988, + "humidity": 76, + "dew_point": -2.87, + "clouds": 100, + "wind_speed": 8.41, + "wind_deg": 196, + "wind_gust": 10.8, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617696000, + "temp": 0.74, + "feels_like": -7.87, + "pressure": 988, + "humidity": 74, + "dew_point": -2.97, + "clouds": 100, + "wind_speed": 8.83, + "wind_deg": 196, + "wind_gust": 11.38, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617699600, + "temp": 0.98, + "feels_like": -7.65, + "pressure": 989, + "humidity": 69, + "dew_point": -3.59, + "clouds": 99, + "wind_speed": 8.75, + "wind_deg": 203, + "wind_gust": 11.54, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617703200, + "temp": 1.18, + "feels_like": -7.24, + "pressure": 989, + "humidity": 67, + "dew_point": -3.77, + "clouds": 86, + "wind_speed": 8.41, + "wind_deg": 205, + "wind_gust": 11.41, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617706800, + "temp": 1.39, + "feels_like": -6.84, + "pressure": 990, + "humidity": 66, + "dew_point": -3.77, + "clouds": 77, + "wind_speed": 8.15, + "wind_deg": 199, + "wind_gust": 10.92, + "weather": [ + { + "id": 803, + "main": "Clouds", + "description": "broken clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617710400, + "temp": 1.53, + "feels_like": -6.93, + "pressure": 990, + "humidity": 66, + "dew_point": -3.65, + "clouds": 42, + "wind_speed": 8.49, + "wind_deg": 191, + "wind_gust": 11.93, + "weather": [ + { + "id": 802, + "main": "Clouds", + "description": "scattered clouds", + "icon": "03d" + } + ] + }, + { + "dt": 1617714000, + "temp": 1.76, + "feels_like": -7.16, + "pressure": 991, + "humidity": 66, + "dew_point": -3.46, + "clouds": 47, + "wind_speed": 9.19, + "wind_deg": 199, + "wind_gust": 13.07, + "weather": [ + { + "id": 802, + "main": "Clouds", + "description": "scattered clouds", + "icon": "03d" + } + ] + }, + { + "dt": 1617717600, + "temp": 1.64, + "feels_like": -7.85, + "pressure": 991, + "humidity": 72, + "dew_point": -2.53, + "clouds": 67, + "wind_speed": 10.18, + "wind_deg": 205, + "wind_gust": 13.98, + "weather": [ + { + "id": 803, + "main": "Clouds", + "description": "broken clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617721200, + "temp": 1.49, + "feels_like": -7.59, + "pressure": 991, + "humidity": 76, + "dew_point": -2.01, + "clouds": 52, + "wind_speed": 9.7, + "wind_deg": 197, + "wind_gust": 13.49, + "weather": [ + { + "id": 803, + "main": "Clouds", + "description": "broken clouds", + "icon": "04d" + } + ] + }, + { + "dt": 1617724800, + "temp": 1.68, + "feels_like": -7.57, + "pressure": 992, + "humidity": 76, + "dew_point": -1.85, + "clouds": 42, + "wind_speed": 9.97, + "wind_deg": 193, + "wind_gust": 14.21, + "weather": [ + { + "id": 802, + "main": "Clouds", + "description": "scattered clouds", + "icon": "03d" + } + ] + }, + { + "dt": 1617728400, + "temp": 1.67, + "feels_like": -7.65, + "pressure": 984, + "humidity": 75, + "dew_point": -2.01, + "clouds": 38, + "wind_speed": 10.04, + "wind_deg": 190, + "wind_gust": 14.59, + "weather": [ + { + "id": 802, + "main": "Clouds", + "description": "scattered clouds", + "icon": "03n" + } + ] + }, + { + "dt": 1617732000, + "temp": 1.67, + "feels_like": -8.41, + "pressure": 984, + "humidity": 73, + "dew_point": -2.34, + "clouds": 37, + "wind_speed": 11.06, + "wind_deg": 191, + "wind_gust": 16.02, + "weather": [ + { + "id": 802, + "main": "Clouds", + "description": "scattered clouds", + "icon": "03n" + } + ] + }, + { + "dt": 1617735600, + "temp": 1.11, + "feels_like": -9.22, + "pressure": 985, + "humidity": 73, + "dew_point": -2.82, + "clouds": 56, + "wind_speed": 11.32, + "wind_deg": 195, + "wind_gust": 16.33, + "weather": [ + { + "id": 803, + "main": "Clouds", + "description": "broken clouds", + "icon": "04n" + } + ] + }, + { + "dt": 1617739200, + "temp": 0, + "feels_like": -10.26, + "pressure": 986, + "humidity": 73, + "dew_point": -3.77, + "clouds": 33, + "wind_speed": 11.04, + "wind_deg": 196, + "wind_gust": 15.97, + "weather": [ + { + "id": 802, + "main": "Clouds", + "description": "scattered clouds", + "icon": "03n" + } + ] + }, + { + "dt": 1617742800, + "temp": 0.56, + "feels_like": -9.73, + "pressure": 986, + "humidity": 72, + "dew_point": -3.45, + "clouds": 26, + "wind_speed": 10.92, + "wind_deg": 202, + "wind_gust": 16.22, + "weather": [ + { + "id": 802, + "main": "Clouds", + "description": "scattered clouds", + "icon": "03n" + } + ] + }, + { + "dt": 1617746400, + "temp": 0.56, + "feels_like": -9.57, + "pressure": 986, + "humidity": 72, + "dew_point": -3.45, + "clouds": 21, + "wind_speed": 10.92, + "wind_deg": 206, + "wind_gust": 16.09, + "weather": [ + { + "id": 801, + "main": "Clouds", + "description": "few clouds", + "icon": "02n" + } + ] + }, + { + "dt": 1617750000, + "temp": 0, + "feels_like": -9.73, + "pressure": 987, + "humidity": 74, + "dew_point": -3.61, + "clouds": 19, + "wind_speed": 10.31, + "wind_deg": 207, + "wind_gust": 15.05, + "weather": [ + { + "id": 801, + "main": "Clouds", + "description": "few clouds", + "icon": "02n" + } + ] + } + ] + } + """; historicalWeatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToHistorical(jsonString); assertNotNull(historicalWeatherData); diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/CurrentWeatherOneCallIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/CurrentWeatherOneCallIntegrationTest.java index 2ed6d27..179157d 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/CurrentWeatherOneCallIntegrationTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/CurrentWeatherOneCallIntegrationTest.java @@ -28,8 +28,7 @@ import com.github.prominence.openweathermap.api.enums.Language; import com.github.prominence.openweathermap.api.enums.OneCallResultOptions; import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.exception.InvalidAuthTokenException; -import com.github.prominence.openweathermap.api.exception.NoDataFoundException; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.model.onecall.current.CurrentWeatherData; import org.junit.jupiter.api.Test; @@ -44,7 +43,7 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { final CurrentWeatherData currentWeatherData = getClient() .oneCall() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieve() @@ -58,7 +57,7 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { final String responseJson = getClient() .oneCall() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieve() @@ -74,7 +73,7 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { final CurrentWeatherData currentWeatherData = getClient() .oneCall() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .exclude(OneCallResultOptions.CURRENT, OneCallResultOptions.MINUTELY) @@ -91,7 +90,7 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { final CompletableFuture currentWeatherDataFuture = getClient() .oneCall() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieveAsync() @@ -106,7 +105,7 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { final CompletableFuture responseJsonFuture = getClient() .oneCall() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieveAsync() @@ -125,7 +124,7 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { client .oneCall() .current() - .byCoordinate(Coordinate.of(53.54, 27.34)) + .byCoordinates(Coordinates.of(53.54, 27.34)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieve() diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/HistoricalWeatherOneCallIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/HistoricalWeatherOneCallIntegrationTest.java index d7d2ecf..038148f 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/HistoricalWeatherOneCallIntegrationTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/HistoricalWeatherOneCallIntegrationTest.java @@ -27,8 +27,7 @@ import com.github.prominence.openweathermap.api.OpenWeatherMapClient; import com.github.prominence.openweathermap.api.enums.Language; import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.exception.InvalidAuthTokenException; -import com.github.prominence.openweathermap.api.exception.NoDataFoundException; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeatherData; import org.junit.jupiter.api.Test; @@ -45,7 +44,7 @@ public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { final HistoricalWeatherData historicalWeatherData = getClient() .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinate.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(Coordinates.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieve() @@ -59,7 +58,7 @@ public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { final String responseJson = getClient() .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinate.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(Coordinates.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieve() @@ -75,7 +74,7 @@ public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { final CompletableFuture historicalWeatherDataFuture = getClient() .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinate.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(Coordinates.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieveAsync() @@ -90,7 +89,7 @@ public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { final CompletableFuture responseJsonFuture = getClient() .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinate.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(Coordinates.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieveAsync() @@ -109,7 +108,7 @@ public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { client .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinate.of(53.54, 27.34), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(Coordinates.of(53.54, 27.34), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) .retrieve() diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherIntegrationTest.java similarity index 86% rename from src/test/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherIntegrationTest.java rename to src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherIntegrationTest.java index e78faef..96ecf08 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/weather/single/SingleResultCurrentWeatherIntegrationTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherIntegrationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2022 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 @@ -20,288 +20,34 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.weather.single; +package com.github.prominence.openweathermap.api.request.weather; import com.github.prominence.openweathermap.api.ApiTest; import com.github.prominence.openweathermap.api.enums.Language; import com.github.prominence.openweathermap.api.enums.UnitSystem; -import com.github.prominence.openweathermap.api.exception.InvalidAuthTokenException; -import com.github.prominence.openweathermap.api.exception.NoDataFoundException; -import com.github.prominence.openweathermap.api.model.Coordinate; +import com.github.prominence.openweathermap.api.model.Coordinates; import com.github.prominence.openweathermap.api.model.weather.Weather; -import com.github.prominence.openweathermap.api.OpenWeatherMapClient; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import static org.junit.jupiter.api.Assertions.*; - -public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { - @Test - public void whenGetSingleCurrentWeatherByCityNameRequestAsJava_thenReturnNotNull() { - final Weather weather = getClient() - .currentWeather() - .single() - .byCityName("Minsk") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asJava(); - - assertNotNull(weather); - assertNotNull(weather.getWeatherState()); - assertNotNull(weather.getCalculationTime()); - assertNotNull(weather.getTemperature()); - assertNotNull(weather.getLocation()); - assertNotNull(weather.getAtmosphericPressure()); - assertNotNull(weather.getHumidity()); - assertNotNull(weather.getWind()); - System.out.println(weather); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameRequestAsJSON_thenReturnNotNull() { - final String weatherJson = getClient() - .currentWeather() - .single() - .byCityName("Minsk") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieve() - .asJSON(); - - assertTrue(weatherJson.startsWith("{")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameRequestAsXML_thenReturnNotNull() { - final String weatherXml = getClient() - .currentWeather() - .single() - .byCityName("Minsk") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.STANDARD) - .retrieve() - .asXML(); - - assertTrue(weatherXml.startsWith("<")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameRequestAsHTML_thenReturnNotNull() { - final String weatherHtml = getClient() - .currentWeather() - .single() - .byCityName("Minsk") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asHTML(); - - assertTrue(weatherHtml.startsWith("<")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameAndCountryCodeRequestAsJava_thenReturnNotNull() { - final Weather weather = getClient() - .currentWeather() - .single() - .byCityName("Minsk", "BY") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asJava(); - - assertNotNull(weather); - assertNotNull(weather.getWeatherState()); - assertNotNull(weather.getCalculationTime()); - assertNotNull(weather.getTemperature()); - assertNotNull(weather.getLocation()); - assertNotNull(weather.getAtmosphericPressure()); - assertNotNull(weather.getHumidity()); - assertNotNull(weather.getWind()); - System.out.println(weather); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameAndCountryCodeRequestAsJSON_thenReturnNotNull() { - final String weatherJson = getClient() - .currentWeather() - .single() - .byCityName("Minsk", "by") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asJSON(); - - assertTrue(weatherJson.startsWith("{")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameAndCountryCodeRequestAsXML_thenReturnNotNull() { - final String weatherXml = getClient() - .currentWeather() - .single() - .byCityName("Minsk", "by") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asXML(); - - assertTrue(weatherXml.startsWith("<")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameAndCountryCodeRequestAsHTML_thenReturnNotNull() { - final String weatherHtml = getClient() - .currentWeather() - .single() - .byCityName("Minsk", "by") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.STANDARD) - .retrieve() - .asHTML(); - - assertTrue(weatherHtml.startsWith("<")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameAndStateCodeAndCountryCodeRequestAsJava_thenReturnNotNull() { - final Weather weather = getClient() - .currentWeather() - .single() - .byCityName("New York", "ny", "us") - .language(Language.SLOVAK) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asJava(); - - assertNotNull(weather); - assertNotNull(weather.getWeatherState()); - assertNotNull(weather.getCalculationTime()); - assertNotNull(weather.getTemperature()); - assertNotNull(weather.getLocation()); - assertNotNull(weather.getAtmosphericPressure()); - assertNotNull(weather.getHumidity()); - assertNotNull(weather.getWind()); - System.out.println(weather); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameAndStateCodeAndCountryCodeRequestAsJSON_thenReturnNotNull() { - final String weatherJson = getClient() - .currentWeather() - .single() - .byCityName("New York", "ny", "us") - .language(Language.HUNGARIAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieve() - .asJSON(); - - assertTrue(weatherJson.startsWith("{")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameAndStateCodeAndCountryCodeRequestAsXML_thenReturnNotNull() { - final String weatherXml = getClient() - .currentWeather() - .single() - .byCityName("New York", "ny", "us") - .language(Language.ROMANIAN) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asXML(); - - assertTrue(weatherXml.startsWith("<")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityNameAndStateCodeAndCountryCodeRequestAsHTML_thenReturnNotNull() { - final String weatherHtml = getClient() - .currentWeather() - .single() - .byCityName("New York", "ny", "us") - .language(Language.ARABIC) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asHTML(); - - assertTrue(weatherHtml.startsWith("<")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityIdRequestAsJava_thenReturnNotNull() { - final Weather weather = getClient() - .currentWeather() - .single() - .byCityId(350001514) - .language(Language.GERMAN) - .retrieve() - .asJava(); - - assertNotNull(weather); - assertNotNull(weather.getWeatherState()); - assertNotNull(weather.getCalculationTime()); - assertNotNull(weather.getTemperature()); - assertNotNull(weather.getLocation()); - assertNotNull(weather.getAtmosphericPressure()); - assertNotNull(weather.getHumidity()); - assertNotNull(weather.getWind()); - System.out.println(weather); - } - - @Test - public void whenGetSingleCurrentWeatherByCityIdRequestAsJSON_thenReturnNotNull() { - final String weatherJson = getClient() - .currentWeather() - .single() - .byCityId(350001514) - .language(Language.GERMAN) - .retrieve() - .asJSON(); - - assertTrue(weatherJson.startsWith("{")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityIdRequestAsXML_thenReturnNotNull() { - final String weatherXml = getClient() - .currentWeather() - .single() - .byCityId(350001514) - .language(Language.GERMAN) - .retrieve() - .asXML(); - - assertTrue(weatherXml.startsWith("<")); - } - - @Test - public void whenGetSingleCurrentWeatherByCityIdRequestAsHTML_thenReturnNotNull() { - final String weatherHtml = getClient() - .currentWeather() - .single() - .byCityId(350001514) - .language(Language.GERMAN) - .retrieve() - .asXML(); - - assertTrue(weatherHtml.startsWith("<")); - } +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +public class CurrentWeatherIntegrationTest extends ApiTest { @Test public void whenGetSingleCurrentWeatherByCoordinateRequestAsJava_thenReturnNotNull() { final Weather weather = getClient() .currentWeather() - .single() - .byCoordinate(Coordinate.of(5, 5)) + .byCoordinates(Coordinates.of(5, 5)) .unitSystem(UnitSystem.METRIC) .retrieve() .asJava(); assertNotNull(weather); - assertNotNull(weather.getWeatherState()); + assertNotNull(weather.getWeatherStates()); assertNotNull(weather.getCalculationTime()); assertNotNull(weather.getTemperature()); assertNotNull(weather.getLocation()); @@ -315,8 +61,7 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { public void whenGetSingleCurrentWeatherByCoordinateRequestAsJSON_thenReturnNotNull() { final String weatherJson = getClient() .currentWeather() - .single() - .byCoordinate(Coordinate.of(5, 5)) + .byCoordinates(Coordinates.of(5, 5)) .unitSystem(UnitSystem.METRIC) .retrieve() .asJSON(); @@ -328,8 +73,7 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { public void whenGetSingleCurrentWeatherByCoordinateRequestAsXML_thenReturnNotNull() { final String weatherXml = getClient() .currentWeather() - .single() - .byCoordinate(Coordinate.of(5, 5)) + .byCoordinates(Coordinates.of(5, 5)) .unitSystem(UnitSystem.METRIC) .retrieve() .asXML(); @@ -341,8 +85,7 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { public void whenGetSingleCurrentWeatherByCoordinateRequestAsHTML_thenReturnNotNull() { final String weatherHtml = getClient() .currentWeather() - .single() - .byCoordinate(Coordinate.of(5, 5)) + .byCoordinates(Coordinates.of(5, 5)) .unitSystem(UnitSystem.METRIC) .retrieve() .asHTML(); @@ -351,10 +94,262 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameRequestAsJava_thenReturnNotNull() { + final Weather weather = getClient() + .currentWeather() + .byCityName("Minsk") + .language(Language.RUSSIAN) + .unitSystem(UnitSystem.METRIC) + .retrieve() + .asJava(); + + assertNotNull(weather); + assertNotNull(weather.getWeatherStates()); + assertNotNull(weather.getCalculationTime()); + assertNotNull(weather.getTemperature()); + assertNotNull(weather.getLocation()); + assertNotNull(weather.getAtmosphericPressure()); + assertNotNull(weather.getHumidity()); + assertNotNull(weather.getWind()); + System.out.println(weather); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameRequestAsJSON_thenReturnNotNull() { + final String weatherJson = getClient() + .currentWeather() + .byCityName("Minsk") + .language(Language.RUSSIAN) + .unitSystem(UnitSystem.IMPERIAL) + .retrieve() + .asJSON(); + + assertTrue(weatherJson.startsWith("{")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameRequestAsXML_thenReturnNotNull() { + final String weatherXml = getClient() + .currentWeather() + .byCityName("Minsk") + .language(Language.RUSSIAN) + .unitSystem(UnitSystem.STANDARD) + .retrieve() + .asXML(); + + assertTrue(weatherXml.startsWith("<")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameRequestAsHTML_thenReturnNotNull() { + final String weatherHtml = getClient() + .currentWeather() + .byCityName("Minsk") + .language(Language.RUSSIAN) + .unitSystem(UnitSystem.METRIC) + .retrieve() + .asHTML(); + + assertTrue(weatherHtml.startsWith("<")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameAndCountryCodeRequestAsJava_thenReturnNotNull() { + final Weather weather = getClient() + .currentWeather() + .byCityName("Minsk", "BY") + .language(Language.RUSSIAN) + .unitSystem(UnitSystem.METRIC) + .retrieve() + .asJava(); + + assertNotNull(weather); + assertNotNull(weather.getWeatherStates()); + assertNotNull(weather.getCalculationTime()); + assertNotNull(weather.getTemperature()); + assertNotNull(weather.getLocation()); + assertNotNull(weather.getAtmosphericPressure()); + assertNotNull(weather.getHumidity()); + assertNotNull(weather.getWind()); + System.out.println(weather); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameAndCountryCodeRequestAsJSON_thenReturnNotNull() { + final String weatherJson = getClient() + .currentWeather() + .byCityName("Minsk", "by") + .language(Language.RUSSIAN) + .unitSystem(UnitSystem.METRIC) + .retrieve() + .asJSON(); + + assertTrue(weatherJson.startsWith("{")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameAndCountryCodeRequestAsXML_thenReturnNotNull() { + final String weatherXml = getClient() + .currentWeather() + .byCityName("Minsk", "by") + .language(Language.RUSSIAN) + .unitSystem(UnitSystem.METRIC) + .retrieve() + .asXML(); + + assertTrue(weatherXml.startsWith("<")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameAndCountryCodeRequestAsHTML_thenReturnNotNull() { + final String weatherHtml = getClient() + .currentWeather() + .byCityName("Minsk", "by") + .language(Language.RUSSIAN) + .unitSystem(UnitSystem.STANDARD) + .retrieve() + .asHTML(); + + assertTrue(weatherHtml.startsWith("<")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameAndStateCodeAndCountryCodeRequestAsJava_thenReturnNotNull() { + final Weather weather = getClient() + .currentWeather() + .byCityName("New York", "ny", "us") + .language(Language.SLOVAK) + .unitSystem(UnitSystem.METRIC) + .retrieve() + .asJava(); + + assertNotNull(weather); + assertNotNull(weather.getWeatherStates()); + assertNotNull(weather.getCalculationTime()); + assertNotNull(weather.getTemperature()); + assertNotNull(weather.getLocation()); + assertNotNull(weather.getAtmosphericPressure()); + assertNotNull(weather.getHumidity()); + assertNotNull(weather.getWind()); + System.out.println(weather); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameAndStateCodeAndCountryCodeRequestAsJSON_thenReturnNotNull() { + final String weatherJson = getClient() + .currentWeather() + .byCityName("New York", "ny", "us") + .language(Language.HUNGARIAN) + .unitSystem(UnitSystem.IMPERIAL) + .retrieve() + .asJSON(); + + assertTrue(weatherJson.startsWith("{")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameAndStateCodeAndCountryCodeRequestAsXML_thenReturnNotNull() { + final String weatherXml = getClient() + .currentWeather() + .byCityName("New York", "ny", "us") + .language(Language.ROMANIAN) + .unitSystem(UnitSystem.METRIC) + .retrieve() + .asXML(); + + assertTrue(weatherXml.startsWith("<")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityNameAndStateCodeAndCountryCodeRequestAsHTML_thenReturnNotNull() { + final String weatherHtml = getClient() + .currentWeather() + .byCityName("New York", "ny", "us") + .language(Language.ARABIC) + .unitSystem(UnitSystem.METRIC) + .retrieve() + .asHTML(); + + assertTrue(weatherHtml.startsWith("<")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityIdRequestAsJava_thenReturnNotNull() { + final Weather weather = getClient() + .currentWeather() + .byCityId(350001514) + .language(Language.GERMAN) + .retrieve() + .asJava(); + + assertNotNull(weather); + assertNotNull(weather.getWeatherStates()); + assertNotNull(weather.getCalculationTime()); + assertNotNull(weather.getTemperature()); + assertNotNull(weather.getLocation()); + assertNotNull(weather.getAtmosphericPressure()); + assertNotNull(weather.getHumidity()); + assertNotNull(weather.getWind()); + System.out.println(weather); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityIdRequestAsJSON_thenReturnNotNull() { + final String weatherJson = getClient() + .currentWeather() + .byCityId(350001514) + .language(Language.GERMAN) + .retrieve() + .asJSON(); + + assertTrue(weatherJson.startsWith("{")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityIdRequestAsXML_thenReturnNotNull() { + final String weatherXml = getClient() + .currentWeather() + .byCityId(350001514) + .language(Language.GERMAN) + .retrieve() + .asXML(); + + assertTrue(weatherXml.startsWith("<")); + } + + @Test + @Disabled + public void whenGetSingleCurrentWeatherByCityIdRequestAsHTML_thenReturnNotNull() { + final String weatherHtml = getClient() + .currentWeather() + .byCityId(350001514) + .language(Language.GERMAN) + .retrieve() + .asXML(); + + assertTrue(weatherHtml.startsWith("<")); + } + + @Test + @Disabled public void whenGetSingleCurrentWeatherByZipCodeAndCountryRequestAsJava_thenReturnNotNull() { final Weather weather = getClient() .currentWeather() - .single() .byZipCodeAndCountry("220015", "by") .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) @@ -362,7 +357,7 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { .asJava(); assertNotNull(weather); - assertNotNull(weather.getWeatherState()); + assertNotNull(weather.getWeatherStates()); assertNotNull(weather.getCalculationTime()); assertNotNull(weather.getTemperature()); assertNotNull(weather.getLocation()); @@ -373,10 +368,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetSingleCurrentWeatherByZipCodeAndCountryRequestAsJSON_thenReturnNotNull() { final String weatherJson = getClient() .currentWeather() - .single() .byZipCodeAndCountry("220015", "by") .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) @@ -387,10 +382,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetSingleCurrentWeatherByZipCodeAndCountryRequestAsXML_thenReturnNotNull() { final String weatherXml = getClient() .currentWeather() - .single() .byZipCodeAndCountry("220015", "by") .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) @@ -401,10 +396,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetSingleCurrentWeatherByZipCodeAndCountryRequestAsHTML_thenReturnNotNull() { final String weatherHtml = getClient() .currentWeather() - .single() .byZipCodeAndCountry("220015", "by") .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) @@ -415,10 +410,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetSingleCurrentWeatherByZipCodeInUSARequestAsJava_thenReturnNotNull() { final Weather weather = getClient() .currentWeather() - .single() .byZipCodeInUSA("10006") .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) @@ -426,7 +421,7 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { .asJava(); assertNotNull(weather); - assertNotNull(weather.getWeatherState()); + assertNotNull(weather.getWeatherStates()); assertNotNull(weather.getCalculationTime()); assertNotNull(weather.getTemperature()); assertNotNull(weather.getLocation()); @@ -437,10 +432,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetSingleCurrentWeatherByZipCodeInUSARequestAsJSON_thenReturnNotNull() { final String weatherJson = getClient() .currentWeather() - .single() .byZipCodeInUSA("10006") .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) @@ -451,10 +446,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetSingleCurrentWeatherByZipCodeInUSARequestAsXML_thenReturnNotNull() { final String weatherXml = getClient() .currentWeather() - .single() .byZipCodeInUSA("10006") .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) @@ -465,10 +460,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetSingleCurrentWeatherByZipCodeInUSARequestAsHTML_thenReturnNotNull() { final String weatherHtml = getClient() .currentWeather() - .single() .byZipCodeInUSA("10006") .language(Language.ENGLISH) .unitSystem(UnitSystem.METRIC) @@ -479,10 +474,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetAnySingleCurrentWeatherAsyncRequestAsJava_thenReturnNotNull() throws ExecutionException, InterruptedException { final CompletableFuture weatherFuture = getClient() .currentWeather() - .single() .byZipCodeAndCountry("220015", "by") .language(Language.RUSSIAN) .unitSystem(UnitSystem.METRIC) @@ -494,10 +489,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetAnySingleCurrentWeatherAsyncRequestAsJson_thenReturnNotNull() throws ExecutionException, InterruptedException { final CompletableFuture weatherFuture = getClient() .currentWeather() - .single() .byZipCodeAndCountry("220015", "by") .language(Language.RUSSIAN) .unitSystem(UnitSystem.METRIC) @@ -509,10 +504,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetAnySingleCurrentWeatherAsyncRequestAsXml_thenReturnNotNull() throws ExecutionException, InterruptedException { final CompletableFuture weatherXmlFuture = getClient() .currentWeather() - .single() .byZipCodeAndCountry("220015", "by") .language(Language.RUSSIAN) .unitSystem(UnitSystem.METRIC) @@ -524,10 +519,10 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { } @Test + @Disabled public void whenGetAnySingleCurrentWeatherAsyncRequestAsHtml_thenReturnNotNull() throws ExecutionException, InterruptedException { final CompletableFuture weatherFuture = getClient() .currentWeather() - .single() .byZipCodeAndCountry("220015", "by") .language(Language.RUSSIAN) .unitSystem(UnitSystem.METRIC) @@ -537,29 +532,4 @@ public class SingleResultCurrentWeatherIntegrationTest extends ApiTest { assertNotNull(weatherFuture); System.out.println(weatherFuture.get()); } - - @Test - public void whenRequestCurrentWeatherWithInvalidApiKey_thenThrowAnException() { - OpenWeatherMapClient client = new OpenWeatherMapClient("invalidKey"); - assertThrows(InvalidAuthTokenException.class, () -> - client - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(34.53, 66.74), 10) - .retrieve() - .asJSON() - ); - } - - @Test - public void whenRequestCurrentWeatherForInvalidLocation_thenThrowAnException() { - assertThrows(NoDataFoundException.class, () -> - getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(90.00, 66.74), 10) - .retrieve() - .asJava() - ); - } } diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherResponseMapperUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherResponseMapperUnitTest.java deleted file mode 100644 index 5fe0b22..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherResponseMapperUnitTest.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2021 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 com.github.prominence.openweathermap.api.request.weather; - -import com.github.prominence.openweathermap.api.enums.UnitSystem; -import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper; -import com.github.prominence.openweathermap.api.model.weather.Weather; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -public class CurrentWeatherResponseMapperUnitTest { - @Test - public void getSingle() { - final String jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - - final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).getSingle(jsonString); - - assertNotNull(weather); - } - - @Test - public void getSingle_withDamagedJSON() { - final String jsonString = "{\"coord\":\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - assertThrows(RuntimeException.class, () -> new CurrentWeatherResponseMapper(null).getSingle(jsonString)); - } - - @Test - public void getSingle_withoutDt() { - final String jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - - final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).getSingle(jsonString); - - assertNotNull(weather); - assertNull(weather.getCalculationTime()); - } - - @Test - public void getSingle_withoutWeatherNode() { - final String jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - - final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).getSingle(jsonString); - - assertNotNull(weather); - assertNull(weather.getWeatherState()); - } - - @Test - public void getSingle_withTemperatureVariations() { - String jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); - - Weather weather = mapper.getSingle(jsonString); - - assertNotNull(weather); - assertEquals(1.84, weather.getTemperature().getValue(), 0.00001); - assertEquals(-0.31, weather.getTemperature().getFeelsLike(), 0.00001); - assertEquals(1.67, weather.getTemperature().getMinTemperature(), 0.00001); - assertEquals(2, weather.getTemperature().getMaxTemperature(), 0.00001); - - // without feels like node - jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - weather = mapper.getSingle(jsonString); - - assertNotNull(weather); - assertNotNull(weather.getTemperature()); - assertNull(weather.getTemperature().getFeelsLike()); - assertNotNull(weather.getTemperature().getMinTemperature()); - assertNotNull(weather.getTemperature().getMaxTemperature()); - - // without min temperature node - jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - weather = mapper.getSingle(jsonString); - - assertNotNull(weather); - assertNotNull(weather.getTemperature()); - assertNotNull(weather.getTemperature().getFeelsLike()); - assertNull(weather.getTemperature().getMinTemperature()); - assertNotNull(weather.getTemperature().getMaxTemperature()); - - // without max temperature node - jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - weather = mapper.getSingle(jsonString); - - assertNotNull(weather); - assertNotNull(weather.getTemperature()); - assertNotNull(weather.getTemperature().getFeelsLike()); - assertNotNull(weather.getTemperature().getMinTemperature()); - assertNull(weather.getTemperature().getMaxTemperature()); - } - - @Test - public void getSingle_withWindVariations() { - String jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - - final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); - Weather weather = mapper.getSingle(jsonString); - - assertNotNull(weather); - assertEquals(2, weather.getWind().getSpeed(), 0.00001); - assertEquals(250, weather.getWind().getDegrees(), 0.00001); - assertNull(weather.getWind().getGust()); - - // without degrees - jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - weather = mapper.getSingle(jsonString); - - assertNotNull(weather); - assertNotNull(weather.getWind()); - assertNull(weather.getWind().getDegrees()); - - // with gust - jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250, \"gust\": 2.44},\"snow\":{\"1h\":0.2},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - weather = mapper.getSingle(jsonString); - - assertNotNull(weather); - assertNotNull(weather.getWind()); - assertNotNull(weather.getWind().getDegrees()); - assertEquals(2.44, weather.getWind().getGust(), 0.00001); - } - - @Test - public void getSingle_withRainVariations() { - final String jsonWith1Hr = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"rain\":{\"1h\":0.1},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - final String jsonWith3Hr = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"rain\":{\"3h\":0.3},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - final String jsonWithBoth = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"rain\":{\"1h\":0.1, \"3h\":0.3},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - - final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); - Weather weather = mapper.getSingle(jsonWith1Hr); - - // with 1h level only - assertNotNull(weather.getRain()); - assertEquals(0.1, weather.getRain().getOneHourLevel(), 0.00001); - assertNull(weather.getRain().getThreeHourLevel()); - - weather = mapper.getSingle(jsonWith3Hr); - - // with 3h level only - assertNotNull(weather.getRain()); - assertNull(weather.getRain().getOneHourLevel()); - assertEquals(0.3, weather.getRain().getThreeHourLevel(), 0.00001); - - weather = mapper.getSingle(jsonWithBoth); - - // with both levels - assertNotNull(weather.getRain()); - assertEquals(0.1, weather.getRain().getOneHourLevel(), 0.00001); - assertEquals(0.3, weather.getRain().getThreeHourLevel(), 0.00001); - } - - @Test - public void getSingle_withSnowVariations() { - final String jsonWith1Hr = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.1},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - final String jsonWith3Hr = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"3h\":0.3},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - final String jsonWithBoth = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.1, \"3h\":0.3},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - - final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); - Weather weather = mapper.getSingle(jsonWith1Hr); - - // with 1h level only - assertNotNull(weather.getSnow()); - assertEquals(0.1, weather.getSnow().getOneHourLevel(), 0.00001); - assertNull(weather.getSnow().getThreeHourLevel()); - - weather = mapper.getSingle(jsonWith3Hr); - - // with 3h level only - assertNotNull(weather.getSnow()); - assertNull(weather.getSnow().getOneHourLevel()); - assertEquals(0.3, weather.getSnow().getThreeHourLevel(), 0.00001); - - weather = mapper.getSingle(jsonWithBoth); - - // with both levels - assertNotNull(weather.getSnow()); - assertEquals(0.1, weather.getSnow().getOneHourLevel(), 0.00001); - assertEquals(0.3, weather.getSnow().getThreeHourLevel(), 0.00001); - } - - @Test - public void getSingle_withLocationVariations() { - String jsonString = "{\"coord\":{\"lon\":27.5667,\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.1},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); - - Weather weather = mapper.getSingle(jsonString); - - assertNotNull(weather.getLocation().getCoordinate()); - assertNotNull(weather.getLocation().getCountryCode()); - - // without coordinates and country code - jsonString = "{\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.1},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - weather = mapper.getSingle(jsonString); - assertNull(weather.getLocation().getCoordinate()); - assertNull(weather.getLocation().getCountryCode()); - - // coordinates without latitude - jsonString = "{\"coord\":{\"lon\":27.5667},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.1},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - weather = mapper.getSingle(jsonString); - assertNull(weather.getLocation().getCoordinate()); - assertNotNull(weather.getLocation().getCountryCode()); - - // coordinates without longitude - jsonString = "{\"coord\":{\"lat\":53.9},\"weather\":[{\"id\":600,\"main\":\"Snow\",\"description\":\"небольшой снег\",\"icon\":\"13n\"}],\"base\":\"stations\",\"main\":{\"temp\":1.84,\"feels_like\":-0.31,\"temp_min\":1.67,\"temp_max\":2,\"pressure\":1001,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":2,\"deg\":250},\"snow\":{\"1h\":0.1},\"clouds\":{\"all\":75},\"dt\":1617746826,\"sys\":{\"type\":1,\"id\":8939,\"country\":\"BY\",\"sunrise\":1617766068,\"sunset\":1617814530},\"timezone\":10800,\"id\":0,\"name\":\"Minsk\",\"cod\":200}"; - weather = mapper.getSingle(jsonString); - assertNull(weather.getLocation().getCoordinate()); - assertNotNull(weather.getLocation().getCountryCode()); - } - - @Test - public void getList() { - final String jsonString = "{\"cod\":200,\"calctime\":0.002580978,\"cnt\":15,\"list\":[{\"id\":2563191,\"dt\":1617746970,\"name\":\"Birkirkara\",\"coord\":{\"Lon\":14.4611,\"Lat\":35.8972},\"main\":{\"temp\":14.42,\"feels_like\":11.94,\"temp_min\":14,\"temp_max\":15,\"pressure\":1013,\"humidity\":88},\"visibility\":10000,\"wind\":{\"speed\":4.63,\"deg\":240},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2210247,\"dt\":1617746968,\"name\":\"Tripoli\",\"coord\":{\"Lon\":13.1875,\"Lat\":32.8752},\"main\":{\"temp\":16.44,\"feels_like\":14.28,\"temp_min\":16.44,\"temp_max\":16.44,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":1013,\"humidity\":65},\"visibility\":10000,\"wind\":{\"speed\":3.09,\"deg\":150},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2216885,\"dt\":1617746968,\"name\":\"Zawiya\",\"coord\":{\"Lon\":12.7278,\"Lat\":32.7522},\"main\":{\"temp\":16.87,\"feels_like\":14.35,\"temp_min\":16.87,\"temp_max\":16.87,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":1013,\"humidity\":60},\"visibility\":10000,\"wind\":{\"speed\":3.31,\"deg\":135},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2212771,\"dt\":1617746968,\"name\":\"Şabrātah\",\"coord\":{\"Lon\":12.4885,\"Lat\":32.7933},\"main\":{\"temp\":16.51,\"feels_like\":13.71,\"temp_min\":16.51,\"temp_max\":16.51,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":1014,\"humidity\":61},\"visibility\":10000,\"wind\":{\"speed\":3.67,\"deg\":136},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2215163,\"dt\":1617746968,\"name\":\"Masallātah\",\"coord\":{\"Lon\":14,\"Lat\":32.6167},\"main\":{\"temp\":14.09,\"feels_like\":13.24,\"temp_min\":14.09,\"temp_max\":14.09,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":989,\"humidity\":68},\"visibility\":10000,\"wind\":{\"speed\":0.64,\"deg\":226},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2219905,\"dt\":1617746968,\"name\":\"Al Khums\",\"coord\":{\"Lon\":14.2619,\"Lat\":32.6486},\"main\":{\"temp\":15.7,\"feels_like\":15.67,\"temp_min\":15.7,\"temp_max\":15.7,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":1014,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":0.12,\"deg\":348},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2208425,\"dt\":1617746968,\"name\":\"Zuwārah\",\"coord\":{\"Lon\":12.082,\"Lat\":32.9312},\"main\":{\"temp\":16.55,\"feels_like\":13.33,\"temp_min\":16.55,\"temp_max\":16.55,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":1015,\"humidity\":67},\"visibility\":10000,\"wind\":{\"speed\":4.82,\"deg\":145},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2210221,\"dt\":1617746968,\"name\":\"Tarhuna\",\"coord\":{\"Lon\":13.6332,\"Lat\":32.435},\"main\":{\"temp\":13.37,\"feels_like\":12.26,\"temp_min\":13.37,\"temp_max\":13.37,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":970,\"humidity\":62},\"visibility\":10000,\"wind\":{\"speed\":0.35,\"deg\":135},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2208485,\"dt\":1617746968,\"name\":\"Zliten\",\"coord\":{\"Lon\":14.5687,\"Lat\":32.4674},\"main\":{\"temp\":15.76,\"feels_like\":14.69,\"temp_min\":15.76,\"temp_max\":15.76,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":1015,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":1.63,\"deg\":133},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2217362,\"dt\":1617746968,\"name\":\"Gharyan\",\"coord\":{\"Lon\":13.0203,\"Lat\":32.1722},\"main\":{\"temp\":13.79,\"feels_like\":11.83,\"temp_min\":13.79,\"temp_max\":13.79,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":936,\"humidity\":56},\"visibility\":10000,\"wind\":{\"speed\":1.24,\"deg\":188},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2523693,\"dt\":1617746921,\"name\":\"Pozzallo\",\"coord\":{\"Lon\":14.8499,\"Lat\":36.7305},\"main\":{\"temp\":11.65,\"feels_like\":8.3,\"temp_min\":10,\"temp_max\":13,\"pressure\":1012,\"humidity\":94},\"visibility\":10000,\"wind\":{\"speed\":5.14,\"deg\":260},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":75},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"cer fragmentat\",\"icon\":\"04n\"}]},{\"id\":2524119,\"dt\":1617746921,\"name\":\"Modica\",\"coord\":{\"Lon\":14.774,\"Lat\":36.8459},\"main\":{\"temp\":11.51,\"feels_like\":8.12,\"temp_min\":10,\"temp_max\":13,\"pressure\":1012,\"humidity\":94},\"visibility\":10000,\"wind\":{\"speed\":5.14,\"deg\":260},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":75},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"cer fragmentat\",\"icon\":\"04n\"}]},{\"id\":2208791,\"dt\":1617746968,\"name\":\"Yafran\",\"coord\":{\"Lon\":12.5286,\"Lat\":32.0633},\"main\":{\"temp\":14.29,\"feels_like\":11.33,\"temp_min\":14.29,\"temp_max\":14.29,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":937,\"humidity\":50},\"visibility\":10000,\"wind\":{\"speed\":2.34,\"deg\":142},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2523581,\"dt\":1617746920,\"name\":\"Rosolini\",\"coord\":{\"Lon\":14.9478,\"Lat\":36.8242},\"main\":{\"temp\":11.54,\"feels_like\":8.16,\"temp_min\":10,\"temp_max\":13,\"pressure\":1012,\"humidity\":94},\"visibility\":10000,\"wind\":{\"speed\":5.14,\"deg\":260},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":75},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"cer fragmentat\",\"icon\":\"04n\"}]},{\"id\":2523650,\"dt\":1617746922,\"name\":\"Ragusa\",\"coord\":{\"Lon\":14.7172,\"Lat\":36.9282},\"main\":{\"temp\":11.63,\"feels_like\":8.27,\"temp_min\":10,\"temp_max\":13,\"pressure\":1012,\"humidity\":94},\"visibility\":10000,\"wind\":{\"speed\":5.14,\"deg\":260},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":75},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"cer fragmentat\",\"icon\":\"04n\"}]}]}"; - final List weatherList = new CurrentWeatherResponseMapper(null).getList(jsonString); - - assertNotNull(weatherList); - assertNotEquals(0, weatherList.size()); - } - - @Test - public void getList_withDamagedJSON() { - final String jsonString = "{\"cod\":200,\"calctime\":0.002580978,\"cnt\":15,\"list\":{\"id\":2563191,\"dt\":1617746970,\"name\":\"Birkirkara\",\"coord\":{\"Lon\":14.4611,\"Lat\":35.8972},\"main\":{\"temp\":14.42,\"feels_like\":11.94,\"temp_min\":14,\"temp_max\":15,\"pressure\":1013,\"humidity\":88},\"visibility\":10000,\"wind\":{\"speed\":4.63,\"deg\":240},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2210247,\"dt\":1617746968,\"name\":\"Tripoli\",\"coord\":{\"Lon\":13.1875,\"Lat\":32.8752},\"main\":{\"temp\":16.44,\"feels_like\":14.28,\"temp_min\":16.44,\"temp_max\":16.44,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":1013,\"humidity\":65},\"visibility\":10000,\"wind\":{\"speed\":3.09,\"deg\":150},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2216885,\"dt\":1617746968,\"name\":\"Zawiya\",\"coord\":{\"Lon\":12.7278,\"Lat\":32.7522},\"main\":{\"temp\":16.87,\"feels_like\":14.35,\"temp_min\":16.87,\"temp_max\":16.87,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":1013,\"humidity\":60},\"visibility\":10000,\"wind\":{\"speed\":3.31,\"deg\":135},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2212771,\"dt\":1617746968,\"name\":\"Şabrātah\",\"coord\":{\"Lon\":12.4885,\"Lat\":32.7933},\"main\":{\"temp\":16.51,\"feels_like\":13.71,\"temp_min\":16.51,\"temp_max\":16.51,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":1014,\"humidity\":61},\"visibility\":10000,\"wind\":{\"speed\":3.67,\"deg\":136},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2215163,\"dt\":1617746968,\"name\":\"Masallātah\",\"coord\":{\"Lon\":14,\"Lat\":32.6167},\"main\":{\"temp\":14.09,\"feels_like\":13.24,\"temp_min\":14.09,\"temp_max\":14.09,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":989,\"humidity\":68},\"visibility\":10000,\"wind\":{\"speed\":0.64,\"deg\":226},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2219905,\"dt\":1617746968,\"name\":\"Al Khums\",\"coord\":{\"Lon\":14.2619,\"Lat\":32.6486},\"main\":{\"temp\":15.7,\"feels_like\":15.67,\"temp_min\":15.7,\"temp_max\":15.7,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":1014,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":0.12,\"deg\":348},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2208425,\"dt\":1617746968,\"name\":\"Zuwārah\",\"coord\":{\"Lon\":12.082,\"Lat\":32.9312},\"main\":{\"temp\":16.55,\"feels_like\":13.33,\"temp_min\":16.55,\"temp_max\":16.55,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":1015,\"humidity\":67},\"visibility\":10000,\"wind\":{\"speed\":4.82,\"deg\":145},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2210221,\"dt\":1617746968,\"name\":\"Tarhuna\",\"coord\":{\"Lon\":13.6332,\"Lat\":32.435},\"main\":{\"temp\":13.37,\"feels_like\":12.26,\"temp_min\":13.37,\"temp_max\":13.37,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":970,\"humidity\":62},\"visibility\":10000,\"wind\":{\"speed\":0.35,\"deg\":135},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2208485,\"dt\":1617746968,\"name\":\"Zliten\",\"coord\":{\"Lon\":14.5687,\"Lat\":32.4674},\"main\":{\"temp\":15.76,\"feels_like\":14.69,\"temp_min\":15.76,\"temp_max\":15.76,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":1015,\"humidity\":69},\"visibility\":10000,\"wind\":{\"speed\":1.63,\"deg\":133},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2217362,\"dt\":1617746968,\"name\":\"Gharyan\",\"coord\":{\"Lon\":13.0203,\"Lat\":32.1722},\"main\":{\"temp\":13.79,\"feels_like\":11.83,\"temp_min\":13.79,\"temp_max\":13.79,\"pressure\":1016,\"sea_level\":1016,\"grnd_level\":936,\"humidity\":56},\"visibility\":10000,\"wind\":{\"speed\":1.24,\"deg\":188},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2523693,\"dt\":1617746921,\"name\":\"Pozzallo\",\"coord\":{\"Lon\":14.8499,\"Lat\":36.7305},\"main\":{\"temp\":11.65,\"feels_like\":8.3,\"temp_min\":10,\"temp_max\":13,\"pressure\":1012,\"humidity\":94},\"visibility\":10000,\"wind\":{\"speed\":5.14,\"deg\":260},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":75},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"cer fragmentat\",\"icon\":\"04n\"}]},{\"id\":2524119,\"dt\":1617746921,\"name\":\"Modica\",\"coord\":{\"Lon\":14.774,\"Lat\":36.8459},\"main\":{\"temp\":11.51,\"feels_like\":8.12,\"temp_min\":10,\"temp_max\":13,\"pressure\":1012,\"humidity\":94},\"visibility\":10000,\"wind\":{\"speed\":5.14,\"deg\":260},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":75},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"cer fragmentat\",\"icon\":\"04n\"}]},{\"id\":2208791,\"dt\":1617746968,\"name\":\"Yafran\",\"coord\":{\"Lon\":12.5286,\"Lat\":32.0633},\"main\":{\"temp\":14.29,\"feels_like\":11.33,\"temp_min\":14.29,\"temp_max\":14.29,\"pressure\":1015,\"sea_level\":1015,\"grnd_level\":937,\"humidity\":50},\"visibility\":10000,\"wind\":{\"speed\":2.34,\"deg\":142},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"cer senin\",\"icon\":\"01n\"}]},{\"id\":2523581,\"dt\":1617746920,\"name\":\"Rosolini\",\"coord\":{\"Lon\":14.9478,\"Lat\":36.8242},\"main\":{\"temp\":11.54,\"feels_like\":8.16,\"temp_min\":10,\"temp_max\":13,\"pressure\":1012,\"humidity\":94},\"visibility\":10000,\"wind\":{\"speed\":5.14,\"deg\":260},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":75},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"cer fragmentat\",\"icon\":\"04n\"}]},{\"id\":2523650,\"dt\":1617746922,\"name\":\"Ragusa\",\"coord\":{\"Lon\":14.7172,\"Lat\":36.9282},\"main\":{\"temp\":11.63,\"feels_like\":8.27,\"temp_min\":10,\"temp_max\":13,\"pressure\":1012,\"humidity\":94},\"visibility\":10000,\"wind\":{\"speed\":5.14,\"deg\":260},\"rain\":null,\"snow\":null,\"clouds\":{\"today\":75},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"cer fragmentat\",\"icon\":\"04n\"}]}]}"; - assertThrows(RuntimeException.class, () -> new CurrentWeatherResponseMapper(null).getList(jsonString)); - } -} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherIntegrationTest.java deleted file mode 100644 index 2996967..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherIntegrationTest.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2021 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 com.github.prominence.openweathermap.api.request.weather.multiple; - -import com.github.prominence.openweathermap.api.ApiTest; -import com.github.prominence.openweathermap.api.enums.Language; -import com.github.prominence.openweathermap.api.enums.UnitSystem; -import com.github.prominence.openweathermap.api.exception.InvalidAuthTokenException; -import com.github.prominence.openweathermap.api.exception.NoDataFoundException; -import com.github.prominence.openweathermap.api.model.Coordinate; -import com.github.prominence.openweathermap.api.model.CoordinateRectangle; -import com.github.prominence.openweathermap.api.model.weather.Weather; -import com.github.prominence.openweathermap.api.OpenWeatherMapClient; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import static org.junit.jupiter.api.Assertions.*; - -public class MultipleResultCurrentWeatherIntegrationTest extends ApiTest { - @Test - public void whenGetMultipleCurrentWeatherByCoordinateRectangleRequestAsJava_thenReturnNotNull() { - final List weatherList = getClient() - .currentWeather() - .multiple() - .byRectangle( - new CoordinateRectangle.Builder() - .setLongitudeLeft(12) - .setLatitudeBottom(32) - .setLongitudeRight(15) - .setLatitudeTop(37) - .build(), - 10 - ) - .language(Language.ROMANIAN) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asJava(); - - assertNotNull(weatherList); - for (Weather weather : weatherList) { - assertNotNull(weather); - assertNotNull(weather.getWeatherState()); - assertNotNull(weather.getCalculationTime()); - assertNotNull(weather.getTemperature()); - assertNotNull(weather.getLocation()); - assertNotNull(weather.getAtmosphericPressure()); - assertNotNull(weather.getHumidity()); - assertNotNull(weather.getWind()); - } - } - - @Test - public void whenGetMultipleCurrentWeatherByCoordinateRectangleRequestAsJSON_thenReturnNotNull() { - final String weatherJson = getClient() - .currentWeather() - .multiple() - .byRectangle(CoordinateRectangle.withValues(12, 32, 15, 37), 10) - .language(Language.ROMANIAN) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asJSON(); - - assertTrue(weatherJson.startsWith("{")); - } - - @Test - public void whenGetMultipleCurrentWeatherByCoordinateRectangleAsyncRequestAsJava_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture> weatherListFuture = getClient() - .currentWeather() - .multiple() - .byRectangle(CoordinateRectangle.withValues(12, 32, 15, 37), 10) - .language(Language.ROMANIAN) - .unitSystem(UnitSystem.METRIC) - .retrieveAsync() - .asJava(); - - assertNotNull(weatherListFuture.get()); - } - - @Test - public void whenGetMultipleCurrentWeatherByCoordinateRectangleAsyncRequestAsJSON_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture weatherJsonFuture = getClient() - .currentWeather() - .multiple() - .byRectangle(CoordinateRectangle.withValues(12, 32, 15, 37), 10) - .language(Language.ROMANIAN) - .unitSystem(UnitSystem.METRIC) - .retrieveAsync() - .asJSON(); - - assertTrue(weatherJsonFuture.get().startsWith("{")); - } - - @Test - public void whenGetMultipleCurrentWeatherByCitiesInCycleRequestAsJava_thenReturnNotNull() { - final List weatherList = getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(55.5, 37.5)) - .language(Language.GERMAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieve() - .asJava(); - - assertNotNull(weatherList); - for (Weather weather : weatherList) { - System.out.println(weather); - assertNotNull(weather); - assertNotNull(weather.getWeatherState()); - assertNotNull(weather.getCalculationTime()); - assertNotNull(weather.getTemperature()); - assertNotNull(weather.getLocation()); - assertNotNull(weather.getAtmosphericPressure()); - assertNotNull(weather.getHumidity()); - assertNotNull(weather.getWind()); - } - } - - @Test - public void whenGetMultipleCurrentWeatherByCitiesInCycleRequestAsJSON_thenReturnNotNull() { - final String weatherJson = getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(55.5, 37.5)) - .language(Language.GERMAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieve() - .asJSON(); - - assertTrue(weatherJson.startsWith("{")); - } - - @Test - public void whenGetMultipleCurrentWeatherByCitiesInCycleRequestAsXML_thenReturnNotNull() { - final String weatherXml = getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(55.5, 37.5)) - .language(Language.GERMAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieve() - .asXML(); - - assertTrue(weatherXml.startsWith("<")); - System.out.println(weatherXml); - } - - @Test - public void whenGetMultipleCurrentWeatherByCitiesInCycleAndCountRequestAsJava_thenReturnNotNull() { - final List weatherList = getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(55.5, 37.5), 10) - .language(Language.GERMAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieve() - .asJava(); - - assertNotNull(weatherList); - for (Weather weather : weatherList) { - System.out.println(weather); - assertNotNull(weather); - assertNotNull(weather.getWeatherState()); - assertNotNull(weather.getCalculationTime()); - assertNotNull(weather.getTemperature()); - assertNotNull(weather.getLocation()); - assertNotNull(weather.getAtmosphericPressure()); - assertNotNull(weather.getHumidity()); - assertNotNull(weather.getWind()); - } - } - - @Test - public void whenGetMultipleCurrentWeatherByCitiesInCycleAndCountRequestAsJSON_thenReturnNotNull() { - final String weatherJson = getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(55.5, 37.5), 10) - .language(Language.GERMAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieve() - .asJSON(); - - assertTrue(weatherJson.startsWith("{")); - } - - @Test - public void whenGetMultipleCurrentWeatherByCitiesInCycleAndCountRequestAsXML_thenReturnNotNull() { - final String weatherXml = getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(55.5, 37.5), 10) - .language(Language.GERMAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieve() - .asXML(); - - assertTrue(weatherXml.startsWith("<")); - } - - @Test - public void whenGetMultipleCurrentWeatherByCoordinateAsyncRequestAsJava_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture> weatherListFuture = getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(55.5, 37.5), 10) - .language(Language.GERMAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieveAsync() - .asJava(); - - assertNotNull(weatherListFuture); - List weatherList = weatherListFuture.get(); - assertTrue(weatherList.size() > 0); - System.out.println(weatherList); - } - - @Test - public void whenGetMultipleCurrentWeatherByCoordinateAsyncRequestAsJson_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture weatherFuture = getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(55.5, 37.5), 10) - .language(Language.GERMAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieveAsync() - .asJSON(); - - assertNotNull(weatherFuture); - System.out.println(weatherFuture.get()); - } - - @Test - public void whenGetMultipleCurrentWeatherByCoordinateAsyncRequestAsXML_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture weatherXMLFuture = getClient() - .currentWeather() - .multiple() - .byCitiesInCycle(Coordinate.of(55.5, 37.5), 10) - .language(Language.GERMAN) - .unitSystem(UnitSystem.IMPERIAL) - .retrieveAsync() - .asXML(); - - assertNotNull(weatherXMLFuture); - System.out.println(weatherXMLFuture.get()); - } - - @Test - public void whenRequestCurrentWeatherWithInvalidApiKey_thenThrowAnException() { - OpenWeatherMapClient client = new OpenWeatherMapClient("invalidKey"); - assertThrows(InvalidAuthTokenException.class, () -> - client - .currentWeather() - .single() - .byCityName("London") - .retrieve() - .asJSON() - ); - } - - @Test - public void whenRequestCurrentWeatherForInvalidLocation_thenThrowAnException() { - assertThrows(NoDataFoundException.class, () -> - getClient() - .currentWeather() - .single() - .byCityName("InvalidCity") - .retrieve() - .asJava() - ); - } -}