From 4fdb48986efa89c5dde1748ec8744761e7253e3c Mon Sep 17 00:00:00 2001 From: Prominence Date: Sat, 30 Apr 2022 01:35:45 +0300 Subject: [PATCH] A bunch of global refactoring and improvements. Improved coverage reports generation. Updated docs. Moved logic out of large mappers into small deserializers. Implemented Geocoding API functionality. Implemented Hourly forecast functionality. Implemented Daily forecast functionality. Renamed Coordinate class. Reimplemented Current Weather API: removed multiple locations requests. Marked officially deprecated methods as @Deprecated. Updated tests. --- .gitignore | 7 +- build.gradle | 4 +- docs/SNAPSHOT.md | 11 +- .../api/OpenWeatherMapClient.java | 28 +- .../AtmosphericPressureDeserializer.java | 52 + .../api/deserializer/CloudsDeserializer.java | 45 + .../deserializer/CoordinatesDeserializer.java | 43 + .../GeocodingRecordDeserializer.java | 57 + .../deserializer/HumidityDeserializer.java | 41 + .../deserializer/TemperatureDeserializer.java | 59 + .../WeatherStateDeserializer.java | 46 + .../api/deserializer/WindDeserializer.java | 66 + .../ZipCodeGeocodingDeserializer.java | 57 + .../HourlyForecastLocationDeserializer.java | 82 ++ .../HourlyForecastRainDeserializer.java | 44 + .../HourlyForecastSnowDeserializer.java | 44 + .../onecall/AlertDeserializer.java | 60 + ...neCallAtmosphericPressureDeserializer.java | 40 + .../onecall/OneCallDailyRainDeserializer.java | 44 + .../onecall/OneCallDailySnowDeserializer.java | 45 + .../OneCallDailyTemperatureDeserializer.java | 56 + .../onecall/OneCallRainDeserializer.java | 47 + .../onecall/OneCallSnowDeserializer.java | 48 + .../OneCallTemperatureDeserializer.java | 55 + .../weather/WeatherLocationDeserializer.java | 85 ++ .../weather/WeatherRainDeserializer.java | 51 + .../weather/WeatherSnowDeserializer.java | 51 + .../api/enums/SubscriptionPlan.java | 5 + .../api/mapper/AbstractMapper.java | 61 + .../mapper/AirPollutionResponseMapper.java | 8 +- .../mapper/CurrentWeatherResponseMapper.java | 298 +--- .../mapper/DailyForecastResponseMapper.java | 210 +++ ...ayThreeHourStepForecastResponseMapper.java | 146 +- .../api/mapper/GeocodingResponseMapper.java | 64 + .../mapper/HourlyForecastResponseMapper.java | 143 ++ .../mapper/OneCallWeatherResponseMapper.java | 348 ++--- .../api/model/AtmosphericPressure.java | 9 +- .../openweathermap/api/model/Clouds.java | 3 +- .../{Coordinate.java => Coordinates.java} | 31 +- ...ctangle.java => CoordinatesRectangle.java} | 22 +- .../openweathermap/api/model/Humidity.java | 5 +- .../openweathermap/api/model/Temperature.java | 16 +- .../api/model/{weather => }/Wind.java | 11 +- .../air/pollution/AirPollutionDetails.java | 18 +- .../api/model/forecast/Wind.java | 145 -- .../forecast/daily/AtmosphericPressure.java | 98 ++ .../api/model/forecast/daily/Forecast.java | 85 ++ .../api/model/forecast/daily/Location.java | 198 +++ .../api/model/forecast/daily/Rain.java | 97 ++ .../api/model/forecast/daily/Snow.java | 97 ++ .../api/model/forecast/daily/Temperature.java | 263 ++++ .../model/forecast/daily/WeatherForecast.java | 278 ++++ .../model/forecast/{ => free}/Forecast.java | 4 +- .../model/forecast/{ => free}/Location.java | 26 +- .../api/model/forecast/{ => free}/Rain.java | 4 +- .../api/model/forecast/{ => free}/Snow.java | 4 +- .../forecast/{ => free}/WeatherForecast.java | 5 +- .../model/forecast/hourly/HourlyForecast.java | 84 ++ .../api/model/forecast/hourly/Location.java | 211 +++ .../api/model/forecast/hourly/Rain.java | 97 ++ .../api/model/forecast/hourly/Snow.java | 97 ++ .../forecast/hourly/WeatherForecast.java | 338 +++++ .../api/model/geocoding/GeocodingRecord.java | 84 ++ .../geocoding/ZipCodeGeocodingRecord.java | 83 ++ .../api/model/onecall/Current.java | 18 +- .../api/model/onecall/Wind.java | 159 --- .../api/model/onecall/current/Alert.java | 20 +- .../onecall/current/CurrentWeatherData.java | 20 +- .../api/model/onecall/current/Daily.java | 23 +- .../api/model/onecall/current/Hourly.java | 18 +- .../historical/HistoricalWeatherData.java | 20 +- .../onecall/historical/HourlyHistorical.java | 18 +- .../api/model/weather/Location.java | 39 +- .../api/model/weather/Weather.java | 39 +- .../api/request/RequestSettings.java | 12 +- .../AirPollutionAsyncRequestTerminator.java | 2 +- .../AirPollutionRequestCustomizer.java | 2 +- .../AirPollutionRequestTerminator.java | 2 +- .../air/pollution/AirPollutionRequester.java | 6 +- .../CurrentAirPollutionRequester.java | 10 +- .../ForecastAirPollutionRequester.java | 10 +- .../HistoricalAirPollutionRequester.java | 10 +- .../DailyForecastAsyncRequestTerminator.java} | 23 +- .../DailyForecastRequestCustomizer.java} | 44 +- .../DailyForecastRequestTerminator.java} | 24 +- .../daily/DailyForecastRequester.java | 41 + ...ourStepForecastAsyncRequestTerminator.java | 4 +- ...hreeHourStepForecastRequestCustomizer.java | 2 +- ...hreeHourStepForecastRequestTerminator.java | 4 +- ...FiveDayThreeHourStepForecastRequester.java | 10 +- ...HourlyForecastAsyncRequestTerminator.java} | 29 +- ...rDaysHourlyForecastRequestCustomizer.java} | 33 +- ...rDaysHourlyForecastRequestTerminator.java} | 30 +- .../FourDaysHourlyForecastRequester.java | 42 + .../request/geocoding/GeocodingRequester.java | 44 + ...DirectGeocodingRequestAsyncTerminator.java | 51 + .../DirectGeocodingRequestCustomizer.java | 52 + .../DirectGeocodingRequestTerminator.java | 50 + .../direct/DirectGeocodingRequester.java | 50 + ...everseGeocodingRequestAsyncTerminator.java | 51 + .../ReverseGeocodingRequestCustomizer.java | 46 + .../ReverseGeocodingRequestTerminator.java | 50 + .../reverse/ReverseGeocodingRequester.java | 41 + .../onecall/OneCallWeatherRequester.java | 1 + ...lCurrentWeatherAsyncRequestTerminator.java | 2 +- ...neCallCurrentWeatherRequestCustomizer.java | 2 +- ...neCallCurrentWeatherRequestTerminator.java | 2 +- .../OneCallCurrentWeatherRequester.java | 9 +- ...storicalWeatherAsyncRequestTerminator.java | 2 +- ...allHistoricalWeatherRequestCustomizer.java | 2 +- ...allHistoricalWeatherRequestTerminator.java | 2 +- .../OneCallHistoricalWeatherRequester.java | 10 +- ...CurrentWeatherAsyncRequestTerminator.java} | 10 +- ...a => CurrentWeatherRequestCustomizer.java} | 20 +- ...a => CurrentWeatherRequestTerminator.java} | 10 +- .../weather/CurrentWeatherRequester.java | 52 +- ...tipleLocationsCurrentWeatherRequester.java | 68 - ...SingleLocationCurrentWeatherRequester.java | 79 -- .../api/utils/JsonDeserializationUtils.java | 45 + .../api/utils/RequestUtils.java | 4 +- .../CurrentWeatherResponseMapperTest.java | 1254 +++++++++++++++++ .../mapper/GeocodingResponseMapperTest.java | 199 +++ .../HourlyForecastResponseMapperTest.java | 158 +++ .../OneCallWeatherResponseMapperTest.java | 223 +++ ...java => CoordinatesRectangleUnitTest.java} | 70 +- ...UnitTest.java => CoordinatesUnitTest.java} | 84 +- .../AirPollutionDetailsUnitTest.java | 18 +- .../forecast/{ => free}/ForecastUnitTest.java | 4 +- .../forecast/{ => free}/LocationUnitTest.java | 20 +- .../forecast/{ => free}/RainUnitTest.java | 4 +- .../forecast/{ => free}/SnowUnitTest.java | 5 +- .../{ => free}/WeatherForecastUnitTest.java | 4 +- .../forecast/{ => free}/WindUnitTest.java | 5 +- .../api/model/onecall/CurrentUnitTest.java | 10 +- .../api/model/onecall/WindUnitTest.java | 1 + .../model/onecall/current/AlertUnitTest.java | 7 +- .../current/CurrentWeatherDataUnitTest.java | 18 +- .../model/onecall/current/DailyUnitTest.java | 13 +- .../model/onecall/current/HourlyUnitTest.java | 10 +- .../HistoricalWeatherDataUnitTest.java | 18 +- .../historical/HistoricalWeatherUnitTest.java | 10 +- .../historical/HourlyHistoricalUnitTest.java | 10 +- .../api/model/weather/LocationUnitTest.java | 16 +- .../api/model/weather/WeatherUnitTest.java | 6 +- .../api/model/weather/WindUnitTest.java | 1 + .../AirPollutionIntegrationTest.java | 26 +- ...yThreeHourStepForecastIntegrationTest.java | 12 +- ...ourStepForecastResponseMapperUnitTest.java | 2 +- .../OneCallWeatherResponseMapperUnitTest.java | 515 ++++++- .../CurrentWeatherOneCallIntegrationTest.java | 15 +- ...storicalWeatherOneCallIntegrationTest.java | 13 +- ...ava => CurrentWeatherIntegrationTest.java} | 586 ++++---- .../CurrentWeatherResponseMapperUnitTest.java | 245 ---- ...leResultCurrentWeatherIntegrationTest.java | 295 ---- 154 files changed, 7881 insertions(+), 2429 deletions(-) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/AtmosphericPressureDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/CloudsDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/CoordinatesDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/GeocodingRecordDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/HumidityDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/TemperatureDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/WeatherStateDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/WindDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/ZipCodeGeocodingDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastLocationDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastRainDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastSnowDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/AlertDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallAtmosphericPressureDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyRainDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailySnowDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyTemperatureDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallRainDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallSnowDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallTemperatureDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherLocationDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherRainDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherSnowDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/AbstractMapper.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapper.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapper.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapper.java rename src/main/java/com/github/prominence/openweathermap/api/model/{Coordinate.java => Coordinates.java} (83%) rename src/main/java/com/github/prominence/openweathermap/api/model/{CoordinateRectangle.java => CoordinatesRectangle.java} (87%) rename src/main/java/com/github/prominence/openweathermap/api/model/{weather => }/Wind.java (95%) delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/Wind.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/AtmosphericPressure.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Forecast.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Location.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Rain.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Snow.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Temperature.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/WeatherForecast.java rename src/main/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/Forecast.java (96%) rename src/main/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/Location.java (91%) rename src/main/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/Rain.java (96%) rename src/main/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/Snow.java (96%) rename src/main/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/WeatherForecast.java (97%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyForecast.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Location.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Rain.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Snow.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/WeatherForecast.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/geocoding/GeocodingRecord.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocodingRecord.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/Wind.java rename src/main/java/com/github/prominence/openweathermap/api/request/{weather/multiple/MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator.java => forecast/daily/DailyForecastAsyncRequestTerminator.java} (68%) rename src/main/java/com/github/prominence/openweathermap/api/request/{weather/multiple/MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer.java => forecast/daily/DailyForecastRequestCustomizer.java} (56%) rename src/main/java/com/github/prominence/openweathermap/api/request/{weather/multiple/MultipleResultCitiesInCircleCurrentWeatherRequestTerminator.java => forecast/daily/DailyForecastRequestTerminator.java} (68%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequester.java rename src/main/java/com/github/prominence/openweathermap/api/request/{weather/multiple/MultipleResultCurrentWeatherAsyncRequestTerminator.java => forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminator.java} (66%) rename src/main/java/com/github/prominence/openweathermap/api/request/{weather/multiple/MultipleResultCurrentWeatherRequestCustomizer.java => forecast/hourly/FourDaysHourlyForecastRequestCustomizer.java} (56%) rename src/main/java/com/github/prominence/openweathermap/api/request/{weather/multiple/MultipleResultCurrentWeatherRequestTerminator.java => forecast/hourly/FourDaysHourlyForecastRequestTerminator.java} (66%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequester.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/GeocodingRequester.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestAsyncTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestCustomizer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequester.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestAsyncTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestCustomizer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequester.java rename src/main/java/com/github/prominence/openweathermap/api/request/weather/{single/SingleResultCurrentWeatherAsyncRequestTerminator.java => CurrentWeatherAsyncRequestTerminator.java} (90%) rename src/main/java/com/github/prominence/openweathermap/api/request/weather/{single/SingleResultCurrentWeatherRequestCustomizer.java => CurrentWeatherRequestCustomizer.java} (73%) rename src/main/java/com/github/prominence/openweathermap/api/request/weather/{single/SingleResultCurrentWeatherRequestTerminator.java => CurrentWeatherRequestTerminator.java} (91%) delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleLocationsCurrentWeatherRequester.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/weather/single/SingleLocationCurrentWeatherRequester.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/utils/JsonDeserializationUtils.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapperTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapperTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapperTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapperTest.java rename src/test/java/com/github/prominence/openweathermap/api/model/{CoordinateRectangleUnitTest.java => CoordinatesRectangleUnitTest.java} (77%) rename src/test/java/com/github/prominence/openweathermap/api/model/{CoordinateUnitTest.java => CoordinatesUnitTest.java} (65%) rename src/test/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/ForecastUnitTest.java (95%) rename src/test/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/LocationUnitTest.java (92%) rename src/test/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/RainUnitTest.java (96%) rename src/test/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/SnowUnitTest.java (96%) rename src/test/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/WeatherForecastUnitTest.java (98%) rename src/test/java/com/github/prominence/openweathermap/api/model/forecast/{ => free}/WindUnitTest.java (96%) rename src/test/java/com/github/prominence/openweathermap/api/request/weather/{single/SingleResultCurrentWeatherIntegrationTest.java => CurrentWeatherIntegrationTest.java} (86%) delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherResponseMapperUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherIntegrationTest.java 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() - ); - } -}