From a2b0360e4b45311c729a07ff5daf90afc6c107ee Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Fri, 30 Sep 2022 23:57:01 +0200 Subject: [PATCH] New mapping approach (#41) * New mapping approach - Refreshes license information in file headers - Rewrites API models to eliminate most of the custom mapping code - Redefines API configuration options - Simplifies fetching and mapping logic - Updates dependency versions - Reduces Java source level to 8 everywhere to eliminate JavaDoc warnings related to generated code - Moves some in-line JSONs to class path resources to make tests more clean - Adds assumptions to skip integration tests if API key is not set - Adds assumptions to skip One Call API tests unless RUN_ONE_CALL env var is set - Solves issue around UnsupportedOperationExceptions in certain terminators - Adds option to use secure channel for picture URLs - Adds new tests Signed-off-by: Esta Nagy * New mapping approach - Code review - Minor fixes - Adds new tests Signed-off-by: Esta Nagy * New mapping approach - Code review - Add more tests Signed-off-by: Esta Nagy * New mapping approach - Code review - Unified coordinate and time period usage - Fixed local system dependent test Signed-off-by: Esta Nagy * New mapping approach - Code review - Fixed line separator issue in response processing - Changed how unitSystem can be defined by moving this parameter to the JSON/XML/HTML terminator methods Signed-off-by: Esta Nagy Signed-off-by: Esta Nagy --- .cirrus.yml | 2 +- build.gradle | 24 +- lombok.config | 5 + .../api/OpenWeatherMapClient.java | 64 +- .../annotation/SubscriptionAvailability.java | 2 +- .../api/conf/TimeoutSettings.java | 21 +- .../api/context/ApiConfiguration.java | 121 ++ .../api/context/ApiConfigurationHolder.java | 39 + .../api/core/net/HttpClient.java | 22 + .../net/HttpURLConnectionBasedHttpClient.java | 161 +- .../api/core/net/RequestExecutor.java | 33 +- .../AtmosphericPressureDeserializer.java | 52 - ...er.java => ConcentrationDeserializer.java} | 19 +- ...zer.java => EpochSecondsDeserializer.java} | 23 +- .../GeocodingRecordDeserializer.java | 57 - ...a => PercentageZeroToOneDeserializer.java} | 21 +- .../PrecipitationIntensityDeserializer.java | 42 + .../RequiredPercentageDeserializer.java | 40 + .../deserializer/TemperatureDeserializer.java | 59 - .../TemperatureValueDeserializer.java | 42 + .../deserializer/VisibilityDeserializer.java | 42 + .../WeatherStateDeserializer.java | 46 - .../api/deserializer/WindDeserializer.java | 66 - .../deserializer/WindSpeedDeserializer.java | 42 + .../ZipCodeGeocodingDeserializer.java | 57 - ...erializer.java => ZoneIdDeserializer.java} | 22 +- .../deserializer/ZoneOffsetDeserializer.java | 41 + ...recastAtmosphericPressureDeserializer.java | 18 - .../ClimaticForecastCloudsDeserializer.java | 23 - .../ClimaticForecastLocationDeserializer.java | 54 - .../ClimaticForecastRainDeserializer.java | 22 - .../ClimaticForecastSnowDeserializer.java | 22 - ...imaticForecastTemperatureDeserializer.java | 34 - .../ClimaticForecastWindDeserializer.java | 58 - ...recastAtmosphericPressureDeserializer.java | 18 - .../DailyForecastCloudsDeserializer.java | 23 - .../DailyForecastLocationDeserializer.java | 54 - .../daily/DailyForecastRainDeserializer.java | 22 - .../daily/DailyForecastSnowDeserializer.java | 22 - .../DailyForecastTemperatureDeserializer.java | 34 - .../FreeForecastLocationDeserializer.java | 87 - .../HourlyForecastLocationDeserializer.java | 82 - .../HourlyForecastRainDeserializer.java | 44 - .../HourlyForecastSnowDeserializer.java | 44 - .../onecall/AlertDeserializer.java | 60 - .../onecall/OneCallDailyRainDeserializer.java | 44 - .../OneCallDailyTemperatureDeserializer.java | 56 - .../onecall/OneCallRainDeserializer.java | 47 - .../onecall/OneCallSnowDeserializer.java | 48 - .../OneCallTemperatureDeserializer.java | 55 - .../SolarRadiationRecordDeserializer.java | 29 - .../roadrisk/RoadRiskAlertDeserializer.java | 23 - .../RoadRiskRoadDetailsDeserializer.java | 23 - .../roadrisk/RoadRiskWeatherDeserializer.java | 31 - .../weather/WeatherLocationDeserializer.java | 85 - .../weather/WeatherRainDeserializer.java | 51 - .../weather/WeatherSnowDeserializer.java | 51 - .../api/enums/AirQualityIndex.java | 49 +- .../openweathermap/api/enums/ApiVariant.java | 39 + .../api/{model => enums}/DayTime.java | 23 +- .../openweathermap/api/enums/EventLevel.java | 51 +- .../openweathermap/api/enums/Language.java | 2 +- .../openweathermap/api/enums/MoonType.java | 5 +- .../api/enums/OneCallResultOptions.java | 2 +- .../api/enums/ResponseType.java | 3 +- .../openweathermap/api/enums/RoadState.java | 31 + .../api/enums/SubscriptionPlan.java | 2 +- .../openweathermap/api/enums/UnitSystem.java | 25 +- .../api/enums/WeatherCondition.java | 47 +- .../exception/ApiPayloadParseException.java | 29 + .../exception/InvalidAuthTokenException.java | 2 +- .../api/exception/NoDataFoundException.java | 2 +- .../api/mapper/AbstractMapper.java | 61 - .../mapper/AirPollutionResponseMapper.java | 102 -- .../ClimaticForecastResponseMapper.java | 84 - .../mapper/CurrentWeatherResponseMapper.java | 112 -- .../mapper/DailyForecastResponseMapper.java | 119 -- ...ayThreeHourStepForecastResponseMapper.java | 137 -- .../api/mapper/GeocodingResponseMapper.java | 64 - .../mapper/HourlyForecastResponseMapper.java | 143 -- .../mapper/OneCallWeatherResponseMapper.java | 334 ---- .../api/mapper/RoadRiskResponseMapper.java | 72 - .../mapper/SolarRadiationResponseMapper.java | 49 - .../api/model/AtmosphericPressure.java | 156 -- .../openweathermap/api/model/Clouds.java | 107 -- .../openweathermap/api/model/Coordinates.java | 126 -- .../openweathermap/api/model/Humidity.java | 107 -- .../openweathermap/api/model/Temperature.java | 193 --- .../api/model/WeatherState.java | 136 -- .../openweathermap/api/model/Wind.java | 173 -- .../pollution/AirPollutionConcentration.java | 102 ++ .../air/pollution/AirPollutionDetails.java | 94 +- .../pollution/AirPollutionDetailsModel.java | 50 + .../pollution/AirPollutionMeasurements.java | 61 + .../air/pollution/AirPollutionRecord.java | 423 +---- .../model/air/pollution/Concentration.java | 55 + .../api/model/forecast/MetaData.java | 33 + .../climatic/AtmosphericPressure.java | 98 -- .../api/model/forecast/climatic/Forecast.java | 85 - .../api/model/forecast/climatic/Location.java | 198 --- .../api/model/forecast/climatic/Rain.java | 97 -- .../api/model/forecast/climatic/Snow.java | 97 -- .../model/forecast/climatic/Temperature.java | 263 ---- .../climatic/ThirtyDaysDailyForecast.java | 48 + .../ThirtyDaysDailyForecastModel.java | 62 + .../forecast/climatic/WeatherForecast.java | 354 ++--- .../forecast/climatic/WeatherForecastDay.java | 104 ++ .../api/model/forecast/climatic/Wind.java | 146 -- .../forecast/daily/AtmosphericPressure.java | 98 -- .../model/forecast/daily/DailyWeather.java | 105 ++ .../api/model/forecast/daily/Forecast.java | 85 - .../api/model/forecast/daily/Location.java | 198 --- .../api/model/forecast/daily/Rain.java | 97 -- .../daily/SixteenDaysDailyForecast.java | 49 + .../daily/SixteenDaysDailyForecastModel.java | 64 + .../api/model/forecast/daily/Snow.java | 97 -- .../api/model/forecast/daily/Temperature.java | 263 ---- .../model/forecast/daily/WeatherForecast.java | 372 ++--- .../free/FiveDaysThreeHoursForecast.java | 58 + .../free/FiveDaysThreeHoursForecastModel.java | 69 + .../api/model/forecast/free/Forecast.java | 84 - .../api/model/forecast/free/Location.java | 235 --- .../model/forecast/free/LocationModel.java | 51 + .../model/forecast/free/Precipitation.java | 37 + .../api/model/forecast/free/Rain.java | 97 -- .../api/model/forecast/free/Snow.java | 97 -- .../model/forecast/free/ThreeHourWeather.java | 111 ++ .../model/forecast/free/WeatherForecast.java | 368 ++--- .../hourly/FourDaysHourlyForecast.java | 59 + .../hourly/FourDaysHourlyForecastModel.java | 70 + .../model/forecast/hourly/HourlyForecast.java | 84 - .../model/forecast/hourly/HourlyWeather.java | 110 ++ .../hourly/HourlyWeatherForecast.java | 138 ++ .../api/model/forecast/hourly/Location.java | 211 --- .../model/forecast/hourly/LocationModel.java | 50 + .../api/model/forecast/hourly/Rain.java | 97 -- .../api/model/forecast/hourly/Snow.java | 97 -- .../forecast/hourly/WeatherForecast.java | 337 ---- .../api/model/generic/MainMetrics.java | 65 + .../api/model/generic/TimeAware.java | 37 + .../model/generic/clouds/CloudCoverage.java | 28 + .../api/model/generic/clouds/Clouds.java | 41 + .../generic/location/BaseLocation.java} | 51 +- .../generic/location/BaseLocationModel.java | 48 + .../generic/location/CoordinateAware.java | 36 + .../generic/location/Coordinates.java} | 40 +- .../location}/CoordinatesRectangle.java | 4 +- .../location/DetailedLocationInfo.java | 36 + .../location/DetailedLocationModel.java | 39 + .../generic/location/MoonlightStages.java} | 47 +- .../generic/location/SunlightStages.java | 45 + .../precipitation/BasePrecipitation.java | 38 + .../model/generic/precipitation/Humidity.java | 36 + .../precipitation/PrecipitationForecast.java | 36 + .../precipitation/PrecipitationIntensity.java | 55 + .../precipitation/PrecipitationValues.java | 45 + .../pressure/BaseAtmosphericPressure.java | 38 + .../pressure/DetailedAtmosphericPressure.java | 38 + .../pressure/SeaLevelAtmosphericPressure.java | 38 + .../generic/temperature/BaseTemperature.java | 41 + .../generic/temperature/DailyTemperature.java | 98 ++ .../temperature/DewPointAwareTemperature.java | 36 + .../temperature/TemperatureDailyBasic.java | 45 + .../temperature/TemperatureDailyDetailed.java | 42 + .../generic/temperature/TemperatureValue.java | 63 + .../temperature/TemperatureWithRange.java | 45 + .../model/generic/visibility/Visibility.java | 62 + .../api/model/generic/wind/BasicWind.java | 43 + .../model/generic/wind/DetailedWindInfo.java | 36 + .../api/model/generic/wind/WindModel.java | 43 + .../api/model/generic/wind/WindSpeed.java | 80 + .../api/model/geocoding/BasicPlaceModel.java | 48 + .../api/model/geocoding/Geocoding.java | 47 + .../api/model/geocoding/GeocodingModel.java | 42 + .../api/model/geocoding/GeocodingRecord.java | 84 - .../api/model/geocoding/Place.java | 43 + .../api/model/geocoding/ZipCodeGeocoding.java | 37 + .../geocoding/ZipCodeGeocodingModel.java | 37 + .../geocoding/ZipCodeGeocodingRecord.java | 83 - .../model/onecall/AtmosphericPressure.java | 98 -- .../api/model/onecall/BaseMeasurement.java | 177 +++ .../api/model/onecall/Current.java | 322 ---- .../api/model/onecall/Measurement.java | 41 + .../onecall/OneCallBaseMeasurementCore.java | 104 ++ .../api/model/onecall/OneCallMeasurement.java | 39 + .../api/model/onecall/Rain.java | 99 -- .../api/model/onecall/Snow.java | 99 -- .../api/model/onecall/Temperature.java | 143 -- .../api/model/onecall/current/Alert.java | 171 +- .../onecall/current/CurrentWeatherData.java | 215 --- .../api/model/onecall/current/Daily.java | 520 ++---- .../api/model/onecall/current/DailyRain.java | 99 -- .../api/model/onecall/current/DailySnow.java | 99 -- .../onecall/current/DailyTemperature.java | 283 ---- .../api/model/onecall/current/Hourly.java | 307 +--- .../api/model/onecall/current/Minutely.java | 89 +- .../api/model/onecall/current/MoonPhase.java | 31 +- .../current/OneCallCurrentForecast.java | 86 + .../current/OneCallCurrentForecastModel.java | 106 ++ .../current/OneCallDailyTemperature.java | 38 + .../onecall/current/OneCallDailyWeather.java | 112 ++ .../onecall/current/OneCallHourlyWeather.java | 39 + .../current/OneCallMinutelyWeather.java | 39 + .../onecall/historical/HistoricalWeather.java | 55 +- .../historical/HistoricalWeatherData.java | 154 -- .../onecall/historical/HourlyHistorical.java | 260 --- .../historical/OneCallHistoricalWeather.java | 57 + .../api/model/radiation/SolarRadiation.java | 74 +- .../model/radiation/SolarRadiationEntry.java | 41 + .../radiation/SolarRadiationMeasurement.java | 43 + .../model/radiation/SolarRadiationModel.java | 39 + .../model/radiation/SolarRadiationRecord.java | 98 -- .../api/model/roadrisk/Alert.java | 76 +- .../api/model/roadrisk/RoadDetails.java | 72 +- .../api/model/roadrisk/RoadRisk.java | 55 + .../api/model/roadrisk/RoadRiskModel.java | 57 + .../api/model/roadrisk/RoadRiskRecord.java | 81 - .../api/model/roadrisk/TrackPoint.java | 82 +- .../api/model/roadrisk/Weather.java | 86 - .../api/model/roadrisk/WeatherModel.java | 58 + .../api/model/weather/City.java | 53 + .../api/model/weather/CurrentWeather.java | 113 ++ .../model/weather/CurrentWeatherModel.java | 182 +++ .../api/model/weather/Location.java | 227 --- .../api/model/weather/Precipitation.java | 40 + .../model/weather/PrecipitationDetails.java | 59 + .../api/model/weather/Rain.java | 160 -- .../api/model/weather/Snow.java | 160 -- .../api/model/weather/Weather.java | 309 ---- .../api/request/RequestSettings.java | 86 +- .../AirPollutionAsyncRequestTerminator.java | 60 +- .../AirPollutionRequestCustomizer.java | 43 +- .../AirPollutionRequestTerminator.java | 70 +- .../air/pollution/AirPollutionRequester.java | 43 +- .../CurrentAirPollutionRequester.java | 11 +- .../ForecastAirPollutionRequester.java | 11 +- .../HistoricalAirPollutionRequester.java | 17 +- ...limaticForecastAsyncRequestTerminator.java | 35 +- .../ClimaticForecastRequestCustomizer.java | 39 +- .../ClimaticForecastRequestTerminator.java | 40 +- .../climatic/ClimaticForecastRequester.java | 38 +- .../DailyForecastAsyncRequestTerminator.java | 36 +- .../daily/DailyForecastRequestCustomizer.java | 19 +- .../daily/DailyForecastRequestTerminator.java | 40 +- .../daily/DailyForecastRequester.java | 17 +- ...ourStepForecastAsyncRequestTerminator.java | 36 +- ...hreeHourStepForecastRequestCustomizer.java | 19 +- ...hreeHourStepForecastRequestTerminator.java | 38 +- ...FiveDayThreeHourStepForecastRequester.java | 50 +- ...sHourlyForecastAsyncRequestTerminator.java | 36 +- ...urDaysHourlyForecastRequestCustomizer.java | 13 +- ...urDaysHourlyForecastRequestTerminator.java | 42 +- .../FourDaysHourlyForecastRequester.java | 17 +- .../GenericAsyncRequestTerminator.java | 52 + .../GenericListAsyncRequestTerminator.java | 53 + .../generic/GenericListRequestTerminator.java | 96 ++ .../generic/GenericRequestTerminator.java | 87 + .../api/request/generic/GenericRequester.java | 43 + .../request/generic/HtmlApiTerminator.java | 45 + .../generic/HtmlAsyncApiTerminator.java | 47 + .../request/generic/JsonApiTerminator.java | 52 + .../generic/JsonAsyncApiTerminator.java | 55 + .../request/generic/JsonXmlApiTerminator.java | 27 + .../generic/JsonXmlAsyncApiTerminator.java | 27 + .../generic/UniversalFormatApiTerminator.java | 27 + .../UniversalFormatAsyncApiTerminator.java | 27 + .../api/request/generic/XmlApiTerminator.java | 45 + .../generic/XmlAsyncApiTerminator.java | 47 + .../request/geocoding/GeocodingRequester.java | 8 +- ...irectGeocodingAsyncRequestTerminator.java} | 34 +- .../DirectGeocodingRequestCustomizer.java | 23 +- .../DirectGeocodingRequestTerminator.java | 48 +- .../direct/DirectGeocodingRequester.java | 20 +- ...ipCodeGeocodingAsyncRequestTerminator.java | 37 + .../ZipCodeGeocodingRequestCustomizer.java} | 30 +- .../ZipCodeGeocodingRequestTerminator.java | 56 + ...everseGeocodingAsyncRequestTerminator.java | 39 + .../ReverseGeocodingRequestCustomizer.java | 13 +- .../ReverseGeocodingRequestTerminator.java | 44 +- .../reverse/ReverseGeocodingRequester.java | 11 +- .../onecall/OneCallWeatherRequester.java | 10 +- ...lCurrentWeatherAsyncRequestTerminator.java | 30 +- ...neCallCurrentWeatherRequestCustomizer.java | 15 +- ...neCallCurrentWeatherRequestTerminator.java | 35 +- .../OneCallCurrentWeatherRequester.java | 11 +- ...storicalWeatherAsyncRequestTerminator.java | 29 +- ...allHistoricalWeatherRequestCustomizer.java | 15 +- ...allHistoricalWeatherRequestTerminator.java | 37 +- .../OneCallHistoricalWeatherRequester.java | 14 +- .../CurrentSolarRadiationRequester.java | 31 +- .../ForecastSolarRadiationRequester.java | 31 +- .../HistoricalSolarRadiationRequester.java | 40 +- .../SolarRadiationAsyncRequestTerminator.java | 29 +- .../SolarRadiationRequestCustomizer.java | 29 +- .../SolarRadiationRequestTerminator.java | 26 +- .../radiation/SolarRadiationRequester.java | 28 +- .../RoadRiskAsyncRequestTerminator.java | 39 +- .../roadrisk/RoadRiskRequestCustomizer.java | 31 +- .../roadrisk/RoadRiskRequestTerminator.java | 43 +- .../request/roadrisk/RoadRiskRequester.java | 31 +- .../model/RoadRiskRequestPayload.java | 36 +- .../CurrentWeatherAsyncRequestTerminator.java | 41 +- .../CurrentWeatherRequestCustomizer.java | 17 +- .../CurrentWeatherRequestTerminator.java | 39 +- .../weather/CurrentWeatherRequester.java | 52 +- .../serializer/EpochSecondsSerializer.java | 47 + .../serializer/RoadRiskRequestSerializer.java | 35 - .../openweathermap/api/ApiTest.java | 12 +- .../api/context/ApiConfigurationTest.java | 141 ++ .../api/context/TestMappingUtils.java | 66 + .../HttpURLConnectionBasedHttpClientTest.java | 216 +++ .../api/core/net/MockHttpClient.java | 31 - .../api/enums/AirQualityIndexTest.java | 57 + .../openweathermap/api/enums/DayTimeTest.java | 54 + .../api/enums/EventLevelTest.java | 57 + .../api/enums/MoonTypeTest.java | 65 + .../api/enums/WeatherConditionUnitTest.java | 134 +- .../ClimaticForecastResponseMapperTest.java | 185 +-- .../CurrentWeatherResponseMapperTest.java | 1394 +++-------------- .../DailyForecastResponseMapperTest.java | 191 +-- ...reeHourStepForecastResponseMapperTest.java | 232 ++- .../mapper/GeocodingResponseMapperTest.java | 188 +-- .../HourlyForecastResponseMapperTest.java | 171 +- .../OneCallWeatherResponseMapperTest.java | 210 +-- .../mapper/RoadRiskResponseMapperTest.java | 87 +- .../SolarRadiationResponseMapperTest.java | 83 +- .../model/AtmosphericPressureUnitTest.java | 130 -- .../api/model/CloudsUnitTest.java | 102 -- .../model/CoordinatesRectangleUnitTest.java | 8 +- .../api/model/CoordinatesUnitTest.java | 113 +- .../api/model/DayTimeUnitTest.java | 3 +- .../api/model/HumidityUnitTest.java | 100 -- .../api/model/TemperatureUnitTest.java | 175 --- .../api/model/WeatherStateUnitTest.java | 79 +- .../AirPollutionDetailsModelTest.java | 67 + .../AirPollutionDetailsUnitTest.java | 98 -- .../pollution/AirPollutionRecordUnitTest.java | 366 ++--- .../model/forecast/free/ForecastUnitTest.java | 82 - .../model/forecast/free/LocationUnitTest.java | 222 --- .../api/model/forecast/free/RainUnitTest.java | 99 -- .../api/model/forecast/free/SnowUnitTest.java | 99 -- .../free/WeatherForecastUnitTest.java | 310 ---- .../api/model/forecast/free/WindUnitTest.java | 187 --- .../api/model/free/RainUnitTest.java} | 33 +- .../PrecipitationIntensityTest.java | 74 + .../temperature/TemperatureValueTest.java | 94 ++ .../generic/visibility/VisibilityTest.java | 95 ++ .../api/model/generic/wind/WindSpeedTest.java | 105 ++ .../onecall/AtmosphericPressureUnitTest.java | 85 - .../api/model/onecall/CurrentUnitTest.java | 297 +--- .../api/model/onecall/RainUnitTest.java | 85 - .../api/model/onecall/SnowUnitTest.java | 85 - .../model/onecall/TemperatureUnitTest.java | 129 -- .../api/model/onecall/WindUnitTest.java | 156 -- .../model/onecall/current/AlertUnitTest.java | 88 +- .../current/CurrentWeatherDataUnitTest.java | 175 +-- .../onecall/current/DailyRainUnitTest.java | 81 - .../onecall/current/DailySnowUnitTest.java | 81 - .../current/DailyTemperatureUnitTest.java | 258 --- .../model/onecall/current/DailyUnitTest.java | 425 ++--- .../model/onecall/current/HourlyUnitTest.java | 251 +-- .../onecall/current/MinutelyUnitTest.java | 86 - .../onecall/current/MoonPhaseUnitTest.java | 34 +- .../HistoricalWeatherDataUnitTest.java | 119 +- .../historical/HistoricalWeatherUnitTest.java | 304 +--- .../historical/HourlyHistoricalUnitTest.java | 254 --- .../api/model/roadrisk/RoadRiskModelTest.java | 64 + .../api/model/weather/LocationUnitTest.java | 197 +-- .../api/model/weather/RainUnitTest.java | 129 -- .../api/model/weather/SnowUnitTest.java | 132 -- .../api/model/weather/WeatherUnitTest.java | 276 ---- .../api/model/weather/WindUnitTest.java | 214 --- ...irPollutionAsyncRequestTerminatorTest.java | 60 + .../AirPollutionIntegrationTest.java | 142 +- .../AirPollutionRequestTerminatorTest.java | 75 + .../AirPollutionResponseMapperUnitTest.java | 61 +- ...ticForecastAsyncRequestTerminatorTest.java | 47 + .../ClimaticForecastIntegrationTest.java | 59 + ...ClimaticForecastRequestTerminatorTest.java | 62 + ...ilyForecastAsyncRequestTerminatorTest.java | 47 + .../daily/DailyForecastIntegrationTest.java | 59 + .../DailyForecastRequestTerminatorTest.java | 62 + ...tepForecastAsyncRequestTerminatorTest.java | 47 + ...yThreeHourStepForecastIntegrationTest.java | 315 +--- ...HourStepForecastRequestTerminatorTest.java | 62 + ...ourStepForecastResponseMapperUnitTest.java | 96 +- ...rlyForecastAsyncRequestTerminatorTest.java | 47 + ...ysHourlyForecastRequestTerminatorTest.java | 62 + .../hourly/HourlyForecastIntegrationTest.java | 59 + .../GenericListRequestTerminatorTest.java | 249 +++ .../generic/GenericRequestTerminatorTest.java | 207 +++ ...ctGeocodingAsyncRequestTerminatorTest.java | 60 + .../DirectGeocodingRequestTerminatorTest.java | 90 ++ ...deGeocodingAsyncRequestTerminatorTest.java | 60 + ...ZipCodeGeocodingRequestTerminatorTest.java | 75 + ...seGeocodingAsyncRequestTerminatorTest.java | 60 + ...ReverseGeocodingRequestTerminatorTest.java | 75 + .../OneCallWeatherResponseMapperUnitTest.java | 618 +------- .../CurrentWeatherOneCallIntegrationTest.java | 98 +- ...rentWeatherAsyncRequestTerminatorTest.java | 60 + ...llCurrentWeatherRequestTerminatorTest.java | 75 + ...storicalWeatherOneCallIntegrationTest.java | 57 +- ...icalWeatherAsyncRequestTerminatorTest.java | 60 + ...istoricalWeatherRequestTerminatorTest.java | 75 + .../radiation/RadiationIntegrationTest.java | 78 + .../SolarRadiationRequestTerminatorTest.java | 47 + .../roadrisk/RoadRiskIntegrationTest.java | 141 +- .../CurrentWeatherIntegrationTest.java | 480 +----- .../CurrentWeatherRequestTerminatorTest.java | 47 + .../api/utils/TestMappingUtils.java | 12 - src/test/resources/logback-test.xml | 34 + .../current-weather-minsk-invalid.json | 46 + .../responses/valid/16days-daily.json | 54 + .../responses/valid/5days3hours.json | 98 ++ .../resources/responses/valid/climatic.json | 49 + .../current-weather-minsk-missing-1h.json | 49 + .../current-weather-minsk-missing-3h.json | 49 + ...ather-minsk-missing-coord-and-country.json | 41 + .../current-weather-minsk-missing-dt.json | 45 + ...rrent-weather-minsk-missing-feelslike.json | 45 + .../current-weather-minsk-missing-gust.json | 51 + ...current-weather-minsk-missing-maxtemp.json | 45 + ...current-weather-minsk-missing-mintemp.json | 45 + ...-weather-minsk-missing-wind-direction.json | 51 + .../valid/current-weather-minsk.json | 52 + .../valid/current-weather-official.json | 44 + .../responses/valid/geocoding-reverse.json | 133 ++ .../responses/valid/geocoding-zipcode.json | 7 + .../responses/valid/hourly-forecast.json | 61 + .../responses/valid/onecall-current.json | 116 ++ .../responses/valid/onecall-historical.json | 469 ++++++ .../resources/responses/valid/road-risk.json | 46 + .../responses/valid/solar-radiation.json | 19 + 433 files changed, 15057 insertions(+), 22885 deletions(-) create mode 100644 lombok.config create mode 100644 src/main/java/com/github/prominence/openweathermap/api/context/ApiConfiguration.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/context/ApiConfigurationHolder.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/AtmosphericPressureDeserializer.java rename src/main/java/com/github/prominence/openweathermap/api/deserializer/{HumidityDeserializer.java => ConcentrationDeserializer.java} (72%) rename src/main/java/com/github/prominence/openweathermap/api/deserializer/{CoordinatesDeserializer.java => EpochSecondsDeserializer.java} (67%) delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/GeocodingRecordDeserializer.java rename src/main/java/com/github/prominence/openweathermap/api/deserializer/{onecall/OneCallAtmosphericPressureDeserializer.java => PercentageZeroToOneDeserializer.java} (66%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/PrecipitationIntensityDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/RequiredPercentageDeserializer.java delete 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/TemperatureValueDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/VisibilityDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/WeatherStateDeserializer.java delete 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/WindSpeedDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/ZipCodeGeocodingDeserializer.java rename src/main/java/com/github/prominence/openweathermap/api/deserializer/{CloudsDeserializer.java => ZoneIdDeserializer.java} (68%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/ZoneOffsetDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastAtmosphericPressureDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastCloudsDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastLocationDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastRainDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastSnowDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastTemperatureDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastWindDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastAtmosphericPressureDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastCloudsDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastLocationDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastRainDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastSnowDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastTemperatureDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastLocationDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastLocationDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastRainDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastSnowDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/AlertDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyRainDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyTemperatureDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallRainDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallSnowDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallTemperatureDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/radiation/SolarRadiationRecordDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskAlertDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskRoadDetailsDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskWeatherDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherLocationDeserializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherRainDeserializer.java delete 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/enums/ApiVariant.java rename src/main/java/com/github/prominence/openweathermap/api/{model => enums}/DayTime.java (71%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/exception/ApiPayloadParseException.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/AbstractMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/AirPollutionResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/ClimaticForecastResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/SolarRadiationResponseMapper.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/AtmosphericPressure.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/Clouds.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/Coordinates.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/Humidity.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/Temperature.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/WeatherState.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/Wind.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionConcentration.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsModel.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionMeasurements.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/Concentration.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/MetaData.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/AtmosphericPressure.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Forecast.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Location.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Rain.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Snow.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Temperature.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/ThirtyDaysDailyForecast.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/ThirtyDaysDailyForecastModel.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/WeatherForecastDay.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Wind.java delete 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/DailyWeather.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Forecast.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Location.java delete 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/SixteenDaysDailyForecast.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/SixteenDaysDailyForecastModel.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Snow.java delete 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/free/FiveDaysThreeHoursForecast.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/FiveDaysThreeHoursForecastModel.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Forecast.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Location.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationModel.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Precipitation.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Rain.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Snow.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/ThreeHourWeather.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/FourDaysHourlyForecast.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/FourDaysHourlyForecastModel.java delete 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/HourlyWeather.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyWeatherForecast.java delete 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/LocationModel.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Rain.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Snow.java delete 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/generic/MainMetrics.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/TimeAware.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/clouds/CloudCoverage.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/clouds/Clouds.java rename src/main/java/com/github/prominence/openweathermap/api/{utils/JsonDeserializationUtils.java => model/generic/location/BaseLocation.java} (60%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/location/BaseLocationModel.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/location/CoordinateAware.java rename src/main/java/com/github/prominence/openweathermap/api/{deserializer/forecast/free/FreeForecastRainDeserializer.java => model/generic/location/Coordinates.java} (52%) rename src/main/java/com/github/prominence/openweathermap/api/model/{ => generic/location}/CoordinatesRectangle.java (98%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/location/DetailedLocationInfo.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/location/DetailedLocationModel.java rename src/main/java/com/github/prominence/openweathermap/api/{deserializer/onecall/OneCallDailySnowDeserializer.java => model/generic/location/MoonlightStages.java} (56%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/location/SunlightStages.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/BasePrecipitation.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/Humidity.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationForecast.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationIntensity.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationValues.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/BaseAtmosphericPressure.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/DetailedAtmosphericPressure.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/SeaLevelAtmosphericPressure.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/BaseTemperature.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/DailyTemperature.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/DewPointAwareTemperature.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureDailyBasic.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureDailyDetailed.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureValue.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureWithRange.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/visibility/Visibility.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/BasicWind.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/DetailedWindInfo.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/WindModel.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/WindSpeed.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/geocoding/BasicPlaceModel.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/geocoding/Geocoding.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/geocoding/GeocodingModel.java delete 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/Place.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocoding.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocodingModel.java delete 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/AtmosphericPressure.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/BaseMeasurement.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/Current.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/Measurement.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/OneCallBaseMeasurementCore.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/OneCallMeasurement.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/Rain.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/Snow.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/Temperature.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherData.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyRain.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailySnow.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyTemperature.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallCurrentForecast.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallCurrentForecastModel.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallDailyTemperature.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallDailyWeather.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallHourlyWeather.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallMinutelyWeather.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherData.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistorical.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/OneCallHistoricalWeather.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationEntry.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationMeasurement.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationModel.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationRecord.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRisk.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskModel.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskRecord.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Weather.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/WeatherModel.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/weather/City.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/weather/CurrentWeather.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/weather/CurrentWeatherModel.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/weather/Location.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/weather/Precipitation.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/weather/PrecipitationDetails.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/weather/Rain.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/weather/Snow.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/weather/Weather.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericAsyncRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericListAsyncRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericListRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericRequester.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/HtmlApiTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/HtmlAsyncApiTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonApiTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonAsyncApiTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonXmlApiTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonXmlAsyncApiTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/UniversalFormatApiTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/UniversalFormatAsyncApiTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/XmlApiTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/generic/XmlAsyncApiTerminator.java rename src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/{DirectGeocodingRequestAsyncTerminator.java => DirectGeocodingAsyncRequestTerminator.java} (56%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingAsyncRequestTerminator.java rename src/main/java/com/github/prominence/openweathermap/api/request/geocoding/{reverse/ReverseGeocodingRequestAsyncTerminator.java => direct/ZipCodeGeocodingRequestCustomizer.java} (63%) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingAsyncRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/serializer/EpochSecondsSerializer.java delete mode 100644 src/main/java/com/github/prominence/openweathermap/api/serializer/RoadRiskRequestSerializer.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/context/ApiConfigurationTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/context/TestMappingUtils.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/core/net/HttpURLConnectionBasedHttpClientTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/core/net/MockHttpClient.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/enums/AirQualityIndexTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/enums/DayTimeTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/enums/EventLevelTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/enums/MoonTypeTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/AtmosphericPressureUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/CloudsUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/HumidityUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/TemperatureUnitTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsModelTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/ForecastUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/RainUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/SnowUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecastUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WindUnitTest.java rename src/{main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastSnowDeserializer.java => test/java/com/github/prominence/openweathermap/api/model/free/RainUnitTest.java} (57%) create mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationIntensityTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureValueTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/generic/visibility/VisibilityTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/generic/wind/WindSpeedTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/AtmosphericPressureUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/RainUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/SnowUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/TemperatureUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/WindUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyRainUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailySnowUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyTemperatureUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/MinutelyUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistoricalUnitTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskModelTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/weather/RainUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/weather/SnowUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/weather/WeatherUnitTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/model/weather/WindUnitTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastIntegrationTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastIntegrationTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/HourlyForecastIntegrationTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/generic/GenericListRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/generic/GenericRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherAsyncRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/radiation/RadiationIntegrationTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestTerminatorTest.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminatorTest.java delete mode 100644 src/test/java/com/github/prominence/openweathermap/api/utils/TestMappingUtils.java create mode 100644 src/test/resources/logback-test.xml create mode 100644 src/test/resources/responses/invalid/current-weather-minsk-invalid.json create mode 100644 src/test/resources/responses/valid/16days-daily.json create mode 100644 src/test/resources/responses/valid/5days3hours.json create mode 100644 src/test/resources/responses/valid/climatic.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk-missing-1h.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk-missing-3h.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk-missing-coord-and-country.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk-missing-dt.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk-missing-feelslike.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk-missing-gust.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk-missing-maxtemp.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk-missing-mintemp.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk-missing-wind-direction.json create mode 100644 src/test/resources/responses/valid/current-weather-minsk.json create mode 100644 src/test/resources/responses/valid/current-weather-official.json create mode 100644 src/test/resources/responses/valid/geocoding-reverse.json create mode 100644 src/test/resources/responses/valid/geocoding-zipcode.json create mode 100644 src/test/resources/responses/valid/hourly-forecast.json create mode 100644 src/test/resources/responses/valid/onecall-current.json create mode 100644 src/test/resources/responses/valid/onecall-historical.json create mode 100644 src/test/resources/responses/valid/road-risk.json create mode 100644 src/test/resources/responses/valid/solar-radiation.json diff --git a/.cirrus.yml b/.cirrus.yml index 76f548e..112813e 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,5 +1,5 @@ container: - image: gradle:jdk17 + image: gradle:jdk8 testCoverage_task: gradle_cache: diff --git a/build.gradle b/build.gradle index f31b2ce..34ef296 100644 --- a/build.gradle +++ b/build.gradle @@ -3,22 +3,23 @@ plugins { id 'maven-publish' id 'signing' id 'jacoco' + id 'io.freefair.lombok' version '6.5.0.3' } repositories { - mavenLocal() - maven { - url = uri('https://repo.maven.apache.org/maven2/') - } + mavenCentral() } dependencies { - implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4' implementation 'org.slf4j:slf4j-api:1.7.36' - testImplementation 'org.junit.platform:junit-platform-runner:1.8.2' - testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2' - annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:0.4.2' + testImplementation 'org.junit.platform:junit-platform-runner:1.9.0' + testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.0' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.9.0' + testImplementation 'ch.qos.logback:logback-classic:1.2.11' + testImplementation 'commons-io:commons-io:2.11.0' + testImplementation 'org.mockito:mockito-core:4.8.0' } group = 'com.github.prominence' @@ -26,12 +27,7 @@ version = '3.0.0-SNAPSHOT' description = 'Java OpenWeatherMap API' configure([tasks.compileJava]) { - sourceCompatibility = 17 // for the IDE support - options.release = 8 - - javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(17) - } + sourceCompatibility = 8 } ext { diff --git a/lombok.config b/lombok.config new file mode 100644 index 0000000..0181d35 --- /dev/null +++ b/lombok.config @@ -0,0 +1,5 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true +lombok.addSuppressWarnings = true +lombok.addLombokGeneratedAnnotation = true +lombok.nonNull.exceptionType = IllegalArgumentException 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 1ebe83d..7041ef1 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java +++ b/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,9 +23,8 @@ package com.github.prominence.openweathermap.api; import com.github.prominence.openweathermap.api.annotation.SubscriptionAvailability; -import com.github.prominence.openweathermap.api.conf.TimeoutSettings; -import com.github.prominence.openweathermap.api.core.net.HttpClient; -import com.github.prominence.openweathermap.api.core.net.HttpURLConnectionBasedHttpClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.context.ApiConfigurationHolder; 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.climatic.ClimaticForecastRequester; @@ -37,47 +36,38 @@ import com.github.prominence.openweathermap.api.request.onecall.OneCallWeatherRe import com.github.prominence.openweathermap.api.request.radiation.SolarRadiationRequester; import com.github.prominence.openweathermap.api.request.roadrisk.RoadRiskRequester; import com.github.prominence.openweathermap.api.request.weather.CurrentWeatherRequester; +import lombok.NonNull; -import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.*; +import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.ALL; +import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.DEVELOPER; +import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.ENTERPRISE; +import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.PAID; +import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.PROFESSIONAL; +import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.SPECIAL; /** * The main public API client to communicate with OpenWeatherMap services. * Requires API key for usage. More info on the website https://openweathermap.org/api. */ public class OpenWeatherMapClient { - private final String apiKey; - private final TimeoutSettings timeoutSettings = new TimeoutSettings(); + private final ApiConfiguration apiConfiguration; - private boolean useInsecureConnection = false; - - private HttpClient httpClient = new HttpURLConnectionBasedHttpClient(); + public OpenWeatherMapClient() { + this(ApiConfigurationHolder.getConfiguration()); + } /** * Created OpenWeatherMap client object. - * @param apiKey API key obtained on OpenWeatherMap site. + * + * @param apiConfiguration configuration options. */ - public OpenWeatherMapClient(String apiKey) { - this.apiKey = apiKey; - } - - public void setConnectionTimeout(int connectionTimeout) { - timeoutSettings.setConnectionTimeout(connectionTimeout); - } - - public void setReadTimeout(int readTimeout) { - timeoutSettings.setReadTimeout(readTimeout); - } - - public void useInsecureConnection(boolean value) { - this.useInsecureConnection = value; - } - - public void setHttpClient(HttpClient httpClient) { - this.httpClient = httpClient; + public OpenWeatherMapClient(@NonNull ApiConfiguration apiConfiguration) { + this.apiConfiguration = apiConfiguration; } /** * Current Weather API. + * * @return requester for retrieving current weather information. */ @SubscriptionAvailability(plans = ALL) @@ -87,9 +77,10 @@ public class OpenWeatherMapClient { /** * Hourly forecast API. + * * @return requester for retrieving hourly weather forecast information for 4 days. */ - @SubscriptionAvailability(plans = { DEVELOPER, PROFESSIONAL, ENTERPRISE }) + @SubscriptionAvailability(plans = {DEVELOPER, PROFESSIONAL, ENTERPRISE}) public FourDaysHourlyForecastRequester forecastHourly4Days() { return new FourDaysHourlyForecastRequester(getRequestSettings()); } @@ -97,6 +88,7 @@ public class OpenWeatherMapClient { /** * 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. + * * @return requester for retrieving one call weather information. */ @SubscriptionAvailability(plans = ALL) @@ -106,6 +98,7 @@ public class OpenWeatherMapClient { /** * Daily forecast API. + * * @return requester for retrieving daily weather forecast information for 16 days. */ @SubscriptionAvailability(plans = PAID) @@ -115,15 +108,17 @@ public class OpenWeatherMapClient { /** * Climatic forecast API. + * * @return requester for retrieving climatic weather forecast information for 30 days. */ - @SubscriptionAvailability(plans = { DEVELOPER, PROFESSIONAL, ENTERPRISE }) + @SubscriptionAvailability(plans = {DEVELOPER, PROFESSIONAL, ENTERPRISE}) public ClimaticForecastRequester climaticForecast30Days() { return new ClimaticForecastRequester(getRequestSettings()); } /** * Solar Radiation API. + * * @return requester for retrieving solar radiation information. */ @SubscriptionAvailability(plans = SPECIAL) @@ -133,6 +128,7 @@ public class OpenWeatherMapClient { /** * 5 Day / 3 Hour Forecast API. + * * @return requester for retrieving 5 day/3-hour weather forecast information. */ @SubscriptionAvailability(plans = ALL) @@ -142,6 +138,7 @@ public class OpenWeatherMapClient { /** * Road Risk API. + * * @return requester for retrieving road risk information. */ @SubscriptionAvailability(plans = SPECIAL) @@ -152,6 +149,7 @@ public class OpenWeatherMapClient { /** * Air Pollution API. * Air Pollution API provides current, forecast and historical air pollution data for any coordinates on the globe. + * * @return requester for air pollution information retrieval. */ @SubscriptionAvailability(plans = ALL) @@ -165,8 +163,6 @@ public class OpenWeatherMapClient { } private RequestSettings getRequestSettings() { - final RequestSettings requestSettings = new RequestSettings(apiKey, timeoutSettings, useInsecureConnection); - requestSettings.setHttpClient(httpClient); - return requestSettings; + return new RequestSettings(apiConfiguration); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/annotation/SubscriptionAvailability.java b/src/main/java/com/github/prominence/openweathermap/api/annotation/SubscriptionAvailability.java index 8e30155..1225c77 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/annotation/SubscriptionAvailability.java +++ b/src/main/java/com/github/prominence/openweathermap/api/annotation/SubscriptionAvailability.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 diff --git a/src/main/java/com/github/prominence/openweathermap/api/conf/TimeoutSettings.java b/src/main/java/com/github/prominence/openweathermap/api/conf/TimeoutSettings.java index 45dbd10..88c16cf 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/conf/TimeoutSettings.java +++ b/src/main/java/com/github/prominence/openweathermap/api/conf/TimeoutSettings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,9 +22,12 @@ package com.github.prominence.openweathermap.api.conf; -public class TimeoutSettings { - private Integer connectionTimeout; - private Integer readTimeout; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode +public final class TimeoutSettings { + private final Integer connectionTimeout; + private final Integer readTimeout; public TimeoutSettings() { this(2000, 2000); @@ -44,15 +47,7 @@ public class TimeoutSettings { return connectionTimeout; } - public void setConnectionTimeout(Integer connectionTimeout) { - this.connectionTimeout = connectionTimeout; - } - public Integer getReadTimeout() { return readTimeout; } - - public void setReadTimeout(Integer readTimeout) { - this.readTimeout = readTimeout; - } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/context/ApiConfiguration.java b/src/main/java/com/github/prominence/openweathermap/api/context/ApiConfiguration.java new file mode 100644 index 0000000..558543f --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/context/ApiConfiguration.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021-present 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.context; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.github.prominence.openweathermap.api.conf.TimeoutSettings; +import com.github.prominence.openweathermap.api.core.net.HttpClient; +import com.github.prominence.openweathermap.api.core.net.HttpURLConnectionBasedHttpClient; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import lombok.Getter; +import lombok.NonNull; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Getter +public class ApiConfiguration { + @NonNull + private final String apiKey; + @NonNull + private final Map baseUrls; + @NonNull + private final HttpClient httpClient; + @NonNull + private final TimeoutSettings defaultTimeoutSettings; + private final ObjectReader objectReader; + private final ObjectWriter objectWriter; + + private ApiConfiguration(String apiKey, Map baseUrls, HttpClient httpClient, + ObjectMapper objectMapper, TimeoutSettings defaultTimeoutSettings) { + this.apiKey = apiKey; + this.baseUrls = Collections.unmodifiableMap(baseUrls); + this.httpClient = httpClient; + this.defaultTimeoutSettings = defaultTimeoutSettings; + this.objectReader = objectMapper.reader(); + this.objectWriter = objectMapper.writer(); + } + + public static ApiConfigurationBuilder builder() { + return new ApiConfigurationBuilder(); + } + + public static class ApiConfigurationBuilder { + private String apiKey; + private Map baseUrls; + private HttpClient httpClient = new HttpURLConnectionBasedHttpClient(); + private TimeoutSettings defaultTimeoutSettings = new TimeoutSettings(); + + private ObjectMapper objectMapper = new ObjectMapper(); + + public ApiConfigurationBuilder() { + baseUrls = Arrays.stream(ApiVariant.values()) + .collect(Collectors.toMap(Function.identity(), ApiVariant::getBaseUrl)); + } + + public ApiConfigurationBuilder apiKey(@NonNull String apiKey) { + this.apiKey = apiKey; + return this; + } + + public ApiConfigurationBuilder baseUrls(@NonNull Map baseUrls) { + final List variants = Arrays.stream(ApiVariant.values()).collect(Collectors.toList()); + if (!baseUrls.keySet().containsAll(variants)) { + throw new IllegalArgumentException("Not all API variants were found: " + baseUrls.keySet() + " , expected: " + variants); + } + this.baseUrls = new HashMap<>(baseUrls); + return this; + } + + public ApiConfigurationBuilder httpClient(@NonNull HttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + public ApiConfigurationBuilder objectMapper(@NonNull ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + return this; + } + + public ApiConfigurationBuilder defaultTimeoutSettings(@NonNull TimeoutSettings defaultTimeoutSettings) { + this.defaultTimeoutSettings = new TimeoutSettings(defaultTimeoutSettings); + return this; + } + + public ApiConfiguration build() { + return new ApiConfiguration(apiKey, baseUrls, httpClient, objectMapper, defaultTimeoutSettings); + } + + public String toString() { + return "ApiConfiguration.ApiConfigurationBuilder(apiKey=" + this.apiKey + ")"; + } + } +} + diff --git a/src/main/java/com/github/prominence/openweathermap/api/context/ApiConfigurationHolder.java b/src/main/java/com/github/prominence/openweathermap/api/context/ApiConfigurationHolder.java new file mode 100644 index 0000000..abfcdb5 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/context/ApiConfigurationHolder.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-present 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.context; + +import lombok.NonNull; + +public class ApiConfigurationHolder { + + private static ApiConfiguration configuration = ApiConfiguration.builder() + .apiKey(System.getenv("OPENWEATHER_API_KEY")) + .build(); + public static ApiConfiguration getConfiguration() { + return configuration; + } + + public static void setConfiguration(@NonNull ApiConfiguration configuration) { + ApiConfigurationHolder.configuration = configuration; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/core/net/HttpClient.java b/src/main/java/com/github/prominence/openweathermap/api/core/net/HttpClient.java index 096ff73..aefd2a7 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/core/net/HttpClient.java +++ b/src/main/java/com/github/prominence/openweathermap/api/core/net/HttpClient.java @@ -1,3 +1,25 @@ +/* + * Copyright (c) 2021-present 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.core.net; import com.github.prominence.openweathermap.api.conf.TimeoutSettings; diff --git a/src/main/java/com/github/prominence/openweathermap/api/core/net/HttpURLConnectionBasedHttpClient.java b/src/main/java/com/github/prominence/openweathermap/api/core/net/HttpURLConnectionBasedHttpClient.java index 579e67f..e59c2c6 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/core/net/HttpURLConnectionBasedHttpClient.java +++ b/src/main/java/com/github/prominence/openweathermap/api/core/net/HttpURLConnectionBasedHttpClient.java @@ -1,3 +1,25 @@ +/* + * Copyright (c) 2021-present 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.core.net; import com.github.prominence.openweathermap.api.conf.TimeoutSettings; @@ -6,10 +28,16 @@ import com.github.prominence.openweathermap.api.exception.NoDataFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.stream.Collectors; public class HttpURLConnectionBasedHttpClient implements HttpClient { private static final Logger logger = LoggerFactory.getLogger(HttpURLConnectionBasedHttpClient.class); @@ -23,82 +51,86 @@ public class HttpURLConnectionBasedHttpClient implements HttpClient { @Override public String executeGetRequest(String url) { - InputStream resultStream; + return doExecute(url, RequestExecutor.Method.GET, null); + } + private String doExecute(String url, RequestExecutor.Method method, String body) { + InputStream resultStream = null; try { - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + HttpURLConnection connection = getConnection(url); + configureTimeouts(connection); + configureConnection(connection, method, body); - if (timeoutSettings != null) { - if (timeoutSettings.getConnectionTimeout() != null) { - connection.setConnectTimeout(timeoutSettings.getConnectionTimeout()); - } - - if (timeoutSettings.getReadTimeout() != null) { - connection.setReadTimeout(timeoutSettings.getReadTimeout()); - } - } - - connection.setRequestMethod("GET"); - connection.setRequestProperty("Content-Type", "application/json; utf-8"); - connection.setRequestProperty("Accept", "application/json"); - - resultStream = switch (connection.getResponseCode()) { - case HttpURLConnection.HTTP_OK -> connection.getInputStream(); - case HttpURLConnection.HTTP_UNAUTHORIZED -> throw new InvalidAuthTokenException(); - case HttpURLConnection.HTTP_NOT_FOUND, HttpURLConnection.HTTP_BAD_REQUEST -> - throw new NoDataFoundException(); - default -> throw new IllegalStateException("Unexpected value: " + connection.getResponseCode()); - }; + resultStream = evaluateResponse(connection); + logger.debug("Executing OpenWeatherMap API request: " + url); + return convertInputStreamToString(resultStream); } catch (IllegalStateException | IOException ex) { logger.error("An error occurred during OpenWeatherMap API response parsing: ", ex); throw new NoDataFoundException(ex); + } finally { + closeQuietly(resultStream); } - logger.debug("Executing OpenWeatherMap API request: " + url); + } - return convertInputStreamToString(resultStream); + HttpURLConnection getConnection(String url) throws IOException { + return (HttpURLConnection) new URL(url).openConnection(); + } + + private void closeQuietly(InputStream resultStream) { + if (resultStream != null) { + try { + resultStream.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private InputStream evaluateResponse(HttpURLConnection connection) throws IOException { + final int responseCode = connection.getResponseCode(); + switch (responseCode) { + case HttpURLConnection.HTTP_OK: + return connection.getInputStream(); + case HttpURLConnection.HTTP_UNAUTHORIZED: + throw new InvalidAuthTokenException(); + case HttpURLConnection.HTTP_NOT_FOUND: + case HttpURLConnection.HTTP_BAD_REQUEST: + throw new NoDataFoundException(); + default: + throw new IllegalStateException("Unexpected value: " + responseCode); + } + } + + private void configureTimeouts(HttpURLConnection connection) { + Optional.ofNullable(timeoutSettings) + .ifPresent(ts -> { + Optional.ofNullable(ts.getConnectionTimeout()) + .ifPresent(connection::setConnectTimeout); + Optional.ofNullable(ts.getReadTimeout()) + .ifPresent(connection::setReadTimeout); + }); + } + + private void configureConnection(HttpURLConnection connection, RequestExecutor.Method method, String body) throws IOException { + connection.setRequestMethod(method.name()); + connection.setRequestProperty("Content-Type", "application/json; utf-8"); + connection.setRequestProperty("Accept", "application/json"); + addOptionalBodyContent(connection, body); } @Override public String executePostRequest(String url, String body) { - InputStream resultStream; + return doExecute(url, RequestExecutor.Method.POST, body); + } - try { - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); - - if (timeoutSettings != null) { - if (timeoutSettings.getConnectionTimeout() != null) { - connection.setConnectTimeout(timeoutSettings.getConnectionTimeout()); - } - - if (timeoutSettings.getReadTimeout() != null) { - connection.setReadTimeout(timeoutSettings.getReadTimeout()); - } - } - - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json; utf-8"); - connection.setRequestProperty("Accept", "application/json"); + private void addOptionalBodyContent(HttpURLConnection connection, String body) throws IOException { + if (body != null) { connection.setDoOutput(true); - - try(OutputStream os = connection.getOutputStream()) { + try (OutputStream os = connection.getOutputStream()) { byte[] input = body.getBytes(StandardCharsets.UTF_8); os.write(input, 0, input.length); } - - resultStream = switch (connection.getResponseCode()) { - case HttpURLConnection.HTTP_OK -> connection.getInputStream(); - case HttpURLConnection.HTTP_UNAUTHORIZED -> throw new InvalidAuthTokenException(); - case HttpURLConnection.HTTP_NOT_FOUND, HttpURLConnection.HTTP_BAD_REQUEST -> - throw new NoDataFoundException(); - default -> throw new IllegalStateException("Unexpected value: " + connection.getResponseCode()); - }; - } catch (IllegalStateException | IOException ex) { - logger.error("An error occurred during OpenWeatherMap API response parsing: ", ex); - throw new NoDataFoundException(ex); } - logger.debug("Executing OpenWeatherMap API request: " + url); - - return convertInputStreamToString(resultStream); } /** @@ -108,19 +140,12 @@ public class HttpURLConnectionBasedHttpClient implements HttpClient { * @return converted InputStream content. * @throws IllegalArgumentException in case if input stream is unable to be read. */ - private static String convertInputStreamToString(InputStream inputStream) { - StringBuilder result = new StringBuilder(); - + private String convertInputStreamToString(InputStream inputStream) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { - String line; - while ((line = reader.readLine()) != null) { - result.append(line); - } + return reader.lines().collect(Collectors.joining(System.lineSeparator())); } catch (IOException ex) { logger.error("Error during response reading: ", ex); throw new IllegalArgumentException(ex); } - - return result.toString(); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/core/net/RequestExecutor.java b/src/main/java/com/github/prominence/openweathermap/api/core/net/RequestExecutor.java index 282c802..f574e5f 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/core/net/RequestExecutor.java +++ b/src/main/java/com/github/prominence/openweathermap/api/core/net/RequestExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,15 +23,14 @@ package com.github.prominence.openweathermap.api.core.net; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.github.prominence.openweathermap.api.enums.ApiVariant; import com.github.prominence.openweathermap.api.request.RequestSettings; import java.net.URL; import java.util.stream.Collectors; public final class RequestExecutor { - private static final String OWM_URL_BASE = "https://SUBDOMAIN.openweathermap.org/"; private final RequestSettings requestSettings; @@ -39,12 +38,12 @@ public final class RequestExecutor { this.requestSettings = requestSettings; } - public String getResponse() { - return getResponse(Method.GET); + public String getResponse(ApiVariant variant) { + return getResponse(variant, Method.GET); } - public String getResponse(Method httpMethod) { - return getResponse(buildRequestUrl(), httpMethod); + public String getResponse(ApiVariant variant, Method httpMethod) { + return getResponse(selectRequestUrl(variant), httpMethod); } /** @@ -56,7 +55,7 @@ public final class RequestExecutor { * @throws IllegalArgumentException in case if provided parameter isn't a valid url for {@link URL} instance. */ private String getResponse(String url, Method httpMethod) { - final HttpClient httpClient = requestSettings.getHttpClient(); + final HttpClient httpClient = requestSettings.getApiConfiguration().getHttpClient(); httpClient.setTimeoutSettings(requestSettings.getTimeoutSettings()); if (httpMethod == Method.GET) { @@ -66,12 +65,8 @@ public final class RequestExecutor { } } - private String buildRequestUrl() { - String baseUrl = OWM_URL_BASE.replace("SUBDOMAIN", requestSettings.getSubdomain()); - if (requestSettings.isUseInsecureConnection()) { - baseUrl = baseUrl.replace("https", "http"); - } - StringBuilder requestUrlBuilder = new StringBuilder(baseUrl); + private String selectRequestUrl(ApiVariant variant) { + StringBuilder requestUrlBuilder = new StringBuilder(requestSettings.getApiConfiguration().getBaseUrls().get(variant)); requestUrlBuilder.append(requestSettings.getUrlAppender()); requestUrlBuilder.append('?'); String parameters = requestSettings.getRequestParameters().entrySet().stream() @@ -82,13 +77,9 @@ public final class RequestExecutor { } private String getSerializedPayload() { - final ObjectMapper objectMapper = new ObjectMapper(); - final SimpleModule module = new SimpleModule(); - module.addSerializer(requestSettings.getPayloadClass(), requestSettings.getPayloadSerializer()); - objectMapper.registerModule(module); - + final ObjectWriter objectWriter = requestSettings.getApiConfiguration().getObjectWriter(); try { - return objectMapper.writeValueAsString(requestSettings.getPayloadObject()); + return objectWriter.writeValueAsString(requestSettings.getPayloadObject()); } catch (JsonProcessingException e) { throw new RuntimeException(e); } 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 deleted file mode 100644 index 16b0d93..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/AtmosphericPressureDeserializer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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/HumidityDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/ConcentrationDeserializer.java similarity index 72% rename from src/main/java/com/github/prominence/openweathermap/api/deserializer/HumidityDeserializer.java rename to src/main/java/com/github/prominence/openweathermap/api/deserializer/ConcentrationDeserializer.java index 3311b30..b3e0f3d 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/HumidityDeserializer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/ConcentrationDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,20 +22,21 @@ 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 com.github.prominence.openweathermap.api.model.air.pollution.Concentration; import java.io.IOException; +import java.math.BigDecimal; +import java.util.Optional; + +public class ConcentrationDeserializer extends JsonDeserializer { -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())); + public Concentration deserialize(JsonParser parser, DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(BigDecimal.class)) + .map(Concentration::new) + .orElse(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/EpochSecondsDeserializer.java similarity index 67% rename from src/main/java/com/github/prominence/openweathermap/api/deserializer/CoordinatesDeserializer.java rename to src/main/java/com/github/prominence/openweathermap/api/deserializer/EpochSecondsDeserializer.java index 975412c..1029c22 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/CoordinatesDeserializer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/EpochSecondsDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,22 +22,23 @@ 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; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Optional; + +public class EpochSecondsDeserializer extends JsonDeserializer { -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; + public OffsetDateTime deserialize(final JsonParser parser, final DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(Long.class)) + .map(Instant::ofEpochSecond) + .map((Instant instant) -> OffsetDateTime.ofInstant(instant, ZoneOffset.UTC)) + .orElse(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 deleted file mode 100644 index 1dec9bc..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/GeocodingRecordDeserializer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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/onecall/OneCallAtmosphericPressureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/PercentageZeroToOneDeserializer.java similarity index 66% rename from src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallAtmosphericPressureDeserializer.java rename to src/main/java/com/github/prominence/openweathermap/api/deserializer/PercentageZeroToOneDeserializer.java index b7361b2..f1ab167 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallAtmosphericPressureDeserializer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/PercentageZeroToOneDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,21 +20,24 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.deserializer.onecall; +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.onecall.AtmosphericPressure; import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Optional; -public class OneCallAtmosphericPressureDeserializer extends JsonDeserializer { +public class PercentageZeroToOneDeserializer 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()); + public Integer deserialize(JsonParser parser, DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(BigDecimal.class)) + .map(v -> v.multiply(BigDecimal.valueOf(100))) + .map(v -> v.setScale(0, RoundingMode.HALF_EVEN)) + .map(BigDecimal::intValue) + .orElse(null); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/PrecipitationIntensityDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/PrecipitationIntensityDeserializer.java new file mode 100644 index 0000000..4f9f81f --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/PrecipitationIntensityDeserializer.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-present 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.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationIntensity; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Optional; + +public class PrecipitationIntensityDeserializer extends JsonDeserializer { + + @Override + public PrecipitationIntensity deserialize(JsonParser parser, DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(BigDecimal.class)) + .map(PrecipitationIntensity::new) + .orElse(null); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/RequiredPercentageDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/RequiredPercentageDeserializer.java new file mode 100644 index 0000000..3857f48 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/RequiredPercentageDeserializer.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021-present 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.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +import java.io.IOException; +import java.util.Optional; + +public class RequiredPercentageDeserializer extends JsonDeserializer { + @Override + public Integer deserialize(JsonParser parser, DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(Integer.class)) + .filter(v -> v <= 100) + .filter(v -> v >= 0) + .orElseThrow(() -> new IllegalArgumentException("Invalid data found for percentage")); + } +} 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 deleted file mode 100644 index 8808688..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/TemperatureDeserializer.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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/TemperatureValueDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/TemperatureValueDeserializer.java new file mode 100644 index 0000000..e0dddf9 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/TemperatureValueDeserializer.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-present 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.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Optional; + +public class TemperatureValueDeserializer extends JsonDeserializer { + + @Override + public TemperatureValue deserialize(JsonParser parser, DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(BigDecimal.class)) + .map(TemperatureValue::new) + .orElse(null); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/VisibilityDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/VisibilityDeserializer.java new file mode 100644 index 0000000..783fbb9 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/VisibilityDeserializer.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-present 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.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Optional; + +public class VisibilityDeserializer extends JsonDeserializer { + + @Override + public Visibility deserialize(JsonParser parser, DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(BigDecimal.class)) + .map(Visibility::new) + .orElse(null); + } +} 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 deleted file mode 100644 index 6876573..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/WeatherStateDeserializer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 deleted file mode 100644 index 8d8d92b..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/WindDeserializer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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/WindSpeedDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/WindSpeedDeserializer.java new file mode 100644 index 0000000..9565493 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/WindSpeedDeserializer.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-present 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.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Optional; + +public class WindSpeedDeserializer extends JsonDeserializer { + + @Override + public WindSpeed deserialize(JsonParser parser, DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(BigDecimal.class)) + .map(WindSpeed::new) + .orElse(null); + } +} 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 deleted file mode 100644 index d1bdff9..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/ZipCodeGeocodingDeserializer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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/CloudsDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/ZoneIdDeserializer.java similarity index 68% rename from src/main/java/com/github/prominence/openweathermap/api/deserializer/CloudsDeserializer.java rename to src/main/java/com/github/prominence/openweathermap/api/deserializer/ZoneIdDeserializer.java index a0a1ae9..9b57e93 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/CloudsDeserializer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/ZoneIdDeserializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,24 +22,20 @@ 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; +import java.time.ZoneId; +import java.util.Optional; + +public class ZoneIdDeserializer extends JsonDeserializer { -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; + public ZoneId deserialize(final JsonParser parser, final DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(String.class)) + .map(ZoneId::of) + .orElse(null); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/ZoneOffsetDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/ZoneOffsetDeserializer.java new file mode 100644 index 0000000..972f286 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/ZoneOffsetDeserializer.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-present 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.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +import java.io.IOException; +import java.time.ZoneOffset; +import java.util.Optional; + +public class ZoneOffsetDeserializer extends JsonDeserializer { + + @Override + public ZoneOffset deserialize(final JsonParser parser, final DeserializationContext context) throws IOException { + return Optional.ofNullable(parser.readValueAs(Integer.class)) + .map(ZoneOffset::ofTotalSeconds) + .orElse(null); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastAtmosphericPressureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastAtmosphericPressureDeserializer.java deleted file mode 100644 index 187c805..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastAtmosphericPressureDeserializer.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.climatic; - -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.climatic.AtmosphericPressure; - -import java.io.IOException; - -public class ClimaticForecastAtmosphericPressureDeserializer extends JsonDeserializer { - @Override - public AtmosphericPressure deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser); - return (AtmosphericPressure) AtmosphericPressure.withValue(jsonNode.get("pressure").asDouble()); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastCloudsDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastCloudsDeserializer.java deleted file mode 100644 index 95bf04c..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastCloudsDeserializer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.climatic; - -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 ClimaticForecastCloudsDeserializer extends JsonDeserializer { - @Override - public Clouds deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - 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/deserializer/forecast/climatic/ClimaticForecastLocationDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastLocationDeserializer.java deleted file mode 100644 index 7344b85..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastLocationDeserializer.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.climatic; - -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.climatic.Location; - -import java.io.IOException; - -import static com.github.prominence.openweathermap.api.utils.JsonDeserializationUtils.parseZoneOffset; - -public class ClimaticForecastLocationDeserializer extends JsonDeserializer { - private final ObjectMapper objectMapper = new ObjectMapper(); - - public ClimaticForecastLocationDeserializer() { - final SimpleModule module = new SimpleModule(); - module.addDeserializer(Coordinates.class, new CoordinatesDeserializer()); - objectMapper.registerModule(module); - } - - @Override - public Location deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - final Location location = (Location) Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText()); - - final JsonNode timezoneNode = rootNode.get("timezone"); - if (timezoneNode != null) { - location.setZoneOffset(parseZoneOffset(timezoneNode)); - } - - final JsonNode countryNode = rootNode.get("country"); - if (countryNode != null) { - location.setCountryCode(countryNode.asText()); - } - - final JsonNode coordNode = rootNode.get("coord"); - if (coordNode != null) { - location.setCoordinates(objectMapper.readValue(objectMapper.treeAsTokens(coordNode), Coordinates.class)); - } - - final JsonNode populationNode = rootNode.get("population"); - if (populationNode != null) { - location.setPopulation(populationNode.asLong()); - } - - return location; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastRainDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastRainDeserializer.java deleted file mode 100644 index 4af8413..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastRainDeserializer.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.climatic; - -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.climatic.Rain; - -import java.io.IOException; - -public class ClimaticForecastRainDeserializer extends JsonDeserializer { - @Override - public Rain deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - final JsonNode rainNode = rootNode.get("rain"); - if (rainNode != null) { - return (Rain) Rain.withValue(rainNode.asDouble()); - } - return null; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastSnowDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastSnowDeserializer.java deleted file mode 100644 index b7ca77a..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastSnowDeserializer.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.climatic; - -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.climatic.Snow; - -import java.io.IOException; - -public class ClimaticForecastSnowDeserializer extends JsonDeserializer { - @Override - public Snow deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - final JsonNode snowNode = rootNode.get("snow"); - if (snowNode != null) { - return (Snow) Snow.withValue(snowNode.asDouble()); - } - return null; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastTemperatureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastTemperatureDeserializer.java deleted file mode 100644 index 10d27f9..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastTemperatureDeserializer.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.climatic; - -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.climatic.Temperature; - -import java.io.IOException; - -public class ClimaticForecastTemperatureDeserializer extends JsonDeserializer { - @Override - public Temperature deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - - 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; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastWindDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastWindDeserializer.java deleted file mode 100644 index 3f4fc96..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/climatic/ClimaticForecastWindDeserializer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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.climatic; - -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 ClimaticForecastWindDeserializer 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()); - } - - return wind; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastAtmosphericPressureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastAtmosphericPressureDeserializer.java deleted file mode 100644 index 42a5a84..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastAtmosphericPressureDeserializer.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.daily; - -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.daily.AtmosphericPressure; - -import java.io.IOException; - -public class DailyForecastAtmosphericPressureDeserializer extends JsonDeserializer { - @Override - public AtmosphericPressure deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser); - return (AtmosphericPressure) AtmosphericPressure.withValue(jsonNode.get("pressure").asDouble()); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastCloudsDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastCloudsDeserializer.java deleted file mode 100644 index 8b23c9f..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastCloudsDeserializer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.daily; - -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 DailyForecastCloudsDeserializer extends JsonDeserializer { - @Override - public Clouds deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - 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/deserializer/forecast/daily/DailyForecastLocationDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastLocationDeserializer.java deleted file mode 100644 index 5ba2f17..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastLocationDeserializer.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.daily; - -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.daily.Location; - -import java.io.IOException; - -import static com.github.prominence.openweathermap.api.utils.JsonDeserializationUtils.parseZoneOffset; - -public class DailyForecastLocationDeserializer extends JsonDeserializer { - private final ObjectMapper objectMapper = new ObjectMapper(); - - public DailyForecastLocationDeserializer() { - final SimpleModule module = new SimpleModule(); - module.addDeserializer(Coordinates.class, new CoordinatesDeserializer()); - objectMapper.registerModule(module); - } - - @Override - public Location deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - final Location location = (Location) Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText()); - - final JsonNode timezoneNode = rootNode.get("timezone"); - if (timezoneNode != null) { - location.setZoneOffset(parseZoneOffset(timezoneNode)); - } - - final JsonNode countryNode = rootNode.get("country"); - if (countryNode != null) { - location.setCountryCode(countryNode.asText()); - } - - final JsonNode coordNode = rootNode.get("coord"); - if (coordNode != null) { - location.setCoordinates(objectMapper.readValue(objectMapper.treeAsTokens(coordNode), Coordinates.class)); - } - - final JsonNode populationNode = rootNode.get("population"); - if (populationNode != null) { - location.setPopulation(populationNode.asLong()); - } - - return location; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastRainDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastRainDeserializer.java deleted file mode 100644 index 9e2d604..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastRainDeserializer.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.daily; - -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.daily.Rain; - -import java.io.IOException; - -public class DailyForecastRainDeserializer extends JsonDeserializer { - @Override - public Rain deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - final JsonNode rainNode = rootNode.get("rain"); - if (rainNode != null) { - return (Rain) Rain.withValue(rainNode.asDouble()); - } - return null; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastSnowDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastSnowDeserializer.java deleted file mode 100644 index 3f8a46b..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastSnowDeserializer.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.daily; - -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.daily.Snow; - -import java.io.IOException; - -public class DailyForecastSnowDeserializer extends JsonDeserializer { - @Override - public Snow deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - final JsonNode snowNode = rootNode.get("snow"); - if (snowNode != null) { - return (Snow) Snow.withValue(snowNode.asDouble()); - } - return null; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastTemperatureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastTemperatureDeserializer.java deleted file mode 100644 index 3384664..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/daily/DailyForecastTemperatureDeserializer.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.forecast.daily; - -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.daily.Temperature; - -import java.io.IOException; - -public class DailyForecastTemperatureDeserializer extends JsonDeserializer { - @Override - public Temperature deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - - 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; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastLocationDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastLocationDeserializer.java deleted file mode 100644 index a8838a0..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastLocationDeserializer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.free; - -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.free.Location; - -import java.io.IOException; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.TimeZone; - -public class FreeForecastLocationDeserializer extends JsonDeserializer { - private final ObjectMapper objectMapper = new ObjectMapper(); - - public FreeForecastLocationDeserializer() { - 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.setCoordinates(objectMapper.readValue(objectMapper.treeAsTokens(coordNode), Coordinates.class)); - } - - final JsonNode populationNode = rootNode.get("population"); - if (populationNode != null) { - location.setPopulation(populationNode.asLong()); - } - - return location; - } -} 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 deleted file mode 100644 index ad56eec..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastLocationDeserializer.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.setCoordinates(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 deleted file mode 100644 index 8562323..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastRainDeserializer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 deleted file mode 100644 index cf63048..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/hourly/HourlyForecastSnowDeserializer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 deleted file mode 100644 index bd1c468..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/AlertDeserializer.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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/OneCallDailyRainDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyRainDeserializer.java deleted file mode 100644 index e33701e..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyRainDeserializer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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/OneCallDailyTemperatureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyTemperatureDeserializer.java deleted file mode 100644 index 244143b..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailyTemperatureDeserializer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 deleted file mode 100644 index 11be57a..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallRainDeserializer.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 deleted file mode 100644 index fc72894..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallSnowDeserializer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 deleted file mode 100644 index d776834..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallTemperatureDeserializer.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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/radiation/SolarRadiationRecordDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/radiation/SolarRadiationRecordDeserializer.java deleted file mode 100644 index 4b53994..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/radiation/SolarRadiationRecordDeserializer.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.radiation; - -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.radiation.SolarRadiationRecord; -import com.github.prominence.openweathermap.api.utils.JsonDeserializationUtils; - -import java.io.IOException; - -public class SolarRadiationRecordDeserializer extends JsonDeserializer { - @Override - public SolarRadiationRecord deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - - SolarRadiationRecord record = new SolarRadiationRecord(); - final JsonNode radiationNode = rootNode.get("radiation"); - record.setMeasurementTime(JsonDeserializationUtils.parseDateTime(rootNode.get("dt"))); - record.setCloudSkyGlobalHorizontalIrradiance(radiationNode.get("ghi").asDouble()); - record.setCloudSkyDirectNormalIrradiance(radiationNode.get("dni").asDouble()); - record.setCloudSkyDiffuseHorizontalIrradiance(radiationNode.get("dhi").asDouble()); - record.setClearSkyGlobalHorizontalIrradiance(radiationNode.get("ghi_cs").asDouble()); - record.setClearSkyDirectNormalIrradiance(radiationNode.get("dni_cs").asDouble()); - record.setClearSkyDiffuseHorizontalIrradiance(radiationNode.get("dhi_cs").asDouble()); - return record; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskAlertDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskAlertDeserializer.java deleted file mode 100644 index eb37528..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskAlertDeserializer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.roadrisk; - -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.EventLevel; -import com.github.prominence.openweathermap.api.model.roadrisk.Alert; - -import java.io.IOException; - -public class RoadRiskAlertDeserializer extends JsonDeserializer { - @Override - public Alert deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - final Alert alert = new Alert(); - alert.setEvent(rootNode.get("event").asText()); - alert.setSenderName(rootNode.get("sender_name").asText()); - alert.setEventLevel(EventLevel.findByValue(rootNode.get("event_level").asInt())); - return alert; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskRoadDetailsDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskRoadDetailsDeserializer.java deleted file mode 100644 index 943fcf6..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskRoadDetailsDeserializer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.roadrisk; - -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.RoadState; -import com.github.prominence.openweathermap.api.model.roadrisk.RoadDetails; - -import java.io.IOException; - -public class RoadRiskRoadDetailsDeserializer extends JsonDeserializer { - @Override - public RoadDetails deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - final RoadDetails roadDetails = new RoadDetails(); - roadDetails.setSurfaceTemperature(rootNode.get("temp").asDouble()); - roadDetails.setRoadState(RoadState.findByValue(rootNode.get("state").asInt())); - - return roadDetails; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskWeatherDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskWeatherDeserializer.java deleted file mode 100644 index 8627a96..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskWeatherDeserializer.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.github.prominence.openweathermap.api.deserializer.roadrisk; - -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.roadrisk.Weather; - -import java.io.IOException; - -public class RoadRiskWeatherDeserializer extends JsonDeserializer { - @Override - public Weather deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { - final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); - - final Weather weather = new Weather(); - weather.setTemperature(rootNode.get("temp").asDouble()); - weather.setDewPoint(rootNode.get("dew_point").asDouble()); - weather.setWindSpeed(rootNode.get("wind_speed").asDouble()); - weather.setWindDegrees(rootNode.get("wind_deg").asDouble()); - if (rootNode.has("precipitation_intensity")) { - weather.setPrecipitationIntensity(rootNode.get("precipitation_intensity").asDouble()); - } - if (rootNode.has("visibility")) { - weather.setVisibilityInMetres(rootNode.get("visibility").asDouble()); - } - - return weather; - } -} 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 deleted file mode 100644 index 5f60eaf..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherLocationDeserializer.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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.setCoordinates(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 deleted file mode 100644 index 4372bcc..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherRainDeserializer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 deleted file mode 100644 index ebf9c4d..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/weather/WeatherSnowDeserializer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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/AirQualityIndex.java b/src/main/java/com/github/prominence/openweathermap/api/enums/AirQualityIndex.java index e90d97c..b076c3a 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/AirQualityIndex.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/AirQualityIndex.java @@ -1,31 +1,31 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.enums; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.Arrays; -import java.util.Optional; /** * The enum Air quality index. @@ -73,8 +73,11 @@ public enum AirQualityIndex { * @param index the index * @return the by index */ - public static AirQualityIndex getByIndex(int index) { - final Optional optionalAirQualityIndex = Arrays.stream(values()).filter(airQualityIndex -> airQualityIndex.getValue() == index).findFirst(); - return optionalAirQualityIndex.orElse(null); + @JsonCreator + public static AirQualityIndex getByIndex(@JsonProperty("aqi") int index) { + return Arrays.stream(values()) + .filter(airQualityIndex -> airQualityIndex.getValue() == index) + .findFirst() + .orElse(null); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/ApiVariant.java b/src/main/java/com/github/prominence/openweathermap/api/enums/ApiVariant.java new file mode 100644 index 0000000..35ee381 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/ApiVariant.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-present 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.enums; + +public enum ApiVariant { + + BASE("https://api.openweathermap.org/"), + PRO("https://pro.openweathermap.org/"); + + private final String baseUrl; + + ApiVariant(String baseUrl) { + this.baseUrl = baseUrl; + } + + public String getBaseUrl() { + return baseUrl; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/DayTime.java b/src/main/java/com/github/prominence/openweathermap/api/enums/DayTime.java similarity index 71% rename from src/main/java/com/github/prominence/openweathermap/api/model/DayTime.java rename to src/main/java/com/github/prominence/openweathermap/api/enums/DayTime.java index 249dd35..eca9e8d 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/DayTime.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/DayTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,11 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.model; +package com.github.prominence.openweathermap.api.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import java.util.Arrays; /** * Enumeration for time of a day representation. @@ -44,9 +48,24 @@ public enum DayTime { /** * Returns time of a day value. + * * @return string value */ public String getValue() { return value; } + + /** + * Finds the appropriate day time based on the short form value. + * + * @param value the short form value (d/n). + * @return day time + */ + @JsonCreator + public static DayTime findByValue(String value) { + return Arrays.stream(values()) + .filter(dayTime -> dayTime.getValue().equals(value)) + .findFirst() + .orElse(null); + } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/EventLevel.java b/src/main/java/com/github/prominence/openweathermap/api/enums/EventLevel.java index 7133a2c..98ab5b0 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/EventLevel.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/EventLevel.java @@ -1,12 +1,51 @@ +/* + * Copyright (c) 2021-present 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.enums; +import com.fasterxml.jackson.annotation.JsonCreator; + import java.util.Arrays; public enum EventLevel { + /** + * Unknown event severity. + */ UNKNOWN(0), + /** + * Green alert. + */ GREEN(1), + /** + * Yellow alert. + */ YELLOW(2), + /** + * Orange alert. + */ ORANGE(3), + /** + * Red alert. + */ RED(4); private final int value; @@ -19,7 +58,17 @@ public enum EventLevel { return value; } + /** + * Finds the appropriate event level based on the numerical level. + * + * @param value the numerical level. + * @return event level + */ + @JsonCreator public static EventLevel findByValue(int value) { - return Arrays.stream(values()).filter(eventLevel -> eventLevel.getValue() == value).findFirst().orElse(null); + return Arrays.stream(values()) + .filter(eventLevel -> eventLevel.getValue() == value) + .findFirst() + .orElse(null); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/Language.java b/src/main/java/com/github/prominence/openweathermap/api/enums/Language.java index 5a84c30..8f0be69 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/Language.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/Language.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/MoonType.java b/src/main/java/com/github/prominence/openweathermap/api/enums/MoonType.java index 7fdaa8a..28c8e7b 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/MoonType.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/MoonType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -52,8 +52,9 @@ public enum MoonType { return WANING_GIBBOUS; } else if (numericValue > 0.75 && numericValue < 1) { return WANING_CRESCENT; + } else { + return INVALID; } - return INVALID; } private static boolean equals(double d1, double d2) { diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/OneCallResultOptions.java b/src/main/java/com/github/prominence/openweathermap/api/enums/OneCallResultOptions.java index d66bc8e..56eb7d8 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/OneCallResultOptions.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/OneCallResultOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/ResponseType.java b/src/main/java/com/github/prominence/openweathermap/api/enums/ResponseType.java index 4c70a54..c85fa53 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/ResponseType.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/ResponseType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,6 +23,7 @@ package com.github.prominence.openweathermap.api.enums; public enum ResponseType { + JSON("json"), HTML("html"), XML("xml"); diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/RoadState.java b/src/main/java/com/github/prominence/openweathermap/api/enums/RoadState.java index fe2f2f2..c890057 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/RoadState.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/RoadState.java @@ -1,5 +1,29 @@ +/* + * Copyright (c) 2021-present 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.enums; +import com.fasterxml.jackson.annotation.JsonCreator; + import java.util.Arrays; public enum RoadState { @@ -33,6 +57,13 @@ public enum RoadState { return value; } + /** + * Finds the appropriate road state based on the numerical code. + * + * @param value the numerical code. + * @return road state + */ + @JsonCreator public static RoadState findByValue(int value) { return Arrays.stream(values()).filter(roadState -> roadState.getValue() == value).findFirst().orElse(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 e96f693..0c25052 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/UnitSystem.java b/src/main/java/com/github/prominence/openweathermap/api/enums/UnitSystem.java index 979971c..7b24320 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/UnitSystem.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/UnitSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -47,29 +47,6 @@ public enum UnitSystem { this.value = value; } - /** - * Returns wind unit for current unit system. - * @return wind unit. - */ - public String getWindUnit() { - return switch (this) { - case IMPERIAL -> "miles/hour"; - case STANDARD, METRIC -> "meter/sec"; - }; - } - - /** - * Returns temperature unit for current unit system. - * @return temperature unit. - */ - public String getTemperatureUnit() { - return switch (this) { - case METRIC -> "°C"; - case IMPERIAL -> "°F"; - case STANDARD -> "K"; - }; - } - /** * Returns unit system value. * @return value unit system. diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/WeatherCondition.java b/src/main/java/com/github/prominence/openweathermap/api/enums/WeatherCondition.java index 2add033..0dcda9e 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/enums/WeatherCondition.java +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/WeatherCondition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,6 +22,9 @@ package com.github.prominence.openweathermap.api.enums; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.Arrays; import java.util.Optional; @@ -277,7 +280,7 @@ public enum WeatherCondition { private final String description; private final String iconId; - private WeatherCondition(int id, String name, String description, String iconId) { + WeatherCondition(int id, String name, String description, String iconId) { this.id = id; this.name = name; this.description = description; @@ -311,13 +314,24 @@ public enum WeatherCondition { return description; } + + /** + * Gets icon id based on part of day. + * + * @param partOfDay The part of day we need the icon for. + * @return the icon id + */ + public String getIconId(DayTime partOfDay) { + return iconId + partOfDay.getValue(); + } + /** * Gets day icon id. * * @return the day icon id */ public String getDayIconId() { - return iconId + 'd'; + return getIconId(DayTime.DAY); } /** @@ -326,35 +340,42 @@ public enum WeatherCondition { * @return the night icon id */ public String getNightIconId() { - return iconId + 'n'; + return getIconId(DayTime.NIGHT); } /** * Gets day icon url. * + * @param secure Determines whether we need to use secure channel (HTTPS) for loading the image. * @return the day icon url */ - public String getDayIconUrl() { - return getIconUrl(getDayIconId()); + public String getDayIconUrl(boolean secure) { + return getIconUrl(getDayIconId(), secure); } /** * Gets night icon url. * + * @param secure Determines whether we need to use secure channel (HTTPS) for loading the image. * @return the night icon url */ - public String getNightIconUrl() { - return getIconUrl(getNightIconId()); + public String getNightIconUrl(boolean secure) { + return getIconUrl(getNightIconId(), secure); } /** * Gets icon url. * * @param iconId the icon id + * @param secure Determines whether we need to use secure channel (HTTPS) for loading the image. * @return the icon url */ - public static String getIconUrl(String iconId) { - return "https://openweathermap.org/img/w/" + iconId + ".png"; + public static String getIconUrl(String iconId, boolean secure) { + String scheme = "http"; + if (secure) { + scheme = "https"; + } + return scheme + "://openweathermap.org/img/w/" + iconId + ".png"; } /** @@ -363,8 +384,10 @@ public enum WeatherCondition { * @param id the id * @return the by id */ - public static WeatherCondition getById(int id) { - final Optional optionalWeatherCondition = Arrays.stream(values()).filter(weatherCondition -> weatherCondition.getId() == id).findFirst(); + @JsonCreator + public static WeatherCondition getById(@JsonProperty("id") int id) { + final Optional optionalWeatherCondition = + Arrays.stream(values()).filter(weatherCondition -> weatherCondition.getId() == id).findFirst(); return optionalWeatherCondition.orElse(null); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/exception/ApiPayloadParseException.java b/src/main/java/com/github/prominence/openweathermap/api/exception/ApiPayloadParseException.java new file mode 100644 index 0000000..1da0712 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/exception/ApiPayloadParseException.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021-present 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.exception; + +public class ApiPayloadParseException extends RuntimeException { + public ApiPayloadParseException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/exception/InvalidAuthTokenException.java b/src/main/java/com/github/prominence/openweathermap/api/exception/InvalidAuthTokenException.java index db5486f..bf381a7 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/exception/InvalidAuthTokenException.java +++ b/src/main/java/com/github/prominence/openweathermap/api/exception/InvalidAuthTokenException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 diff --git a/src/main/java/com/github/prominence/openweathermap/api/exception/NoDataFoundException.java b/src/main/java/com/github/prominence/openweathermap/api/exception/NoDataFoundException.java index 95572b7..5c6f967 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/exception/NoDataFoundException.java +++ b/src/main/java/com/github/prominence/openweathermap/api/exception/NoDataFoundException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 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 deleted file mode 100644 index 0fbbf8b..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/AbstractMapper.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 deleted file mode 100644 index a0aabb4..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/AirPollutionResponseMapper.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.prominence.openweathermap.api.enums.AirQualityIndex; -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; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.TimeZone; - -/** - * Official API response documentation: https://openweathermap.org/api/air-pollution#fields. - */ -public class AirPollutionResponseMapper { - /** - * Map to air pollution air pollution. - * - * @param json the json - * @return the air pollution - */ - public AirPollutionDetails mapToAirPollution(String json) { - final ObjectMapper objectMapper = new ObjectMapper(); - AirPollutionDetails airPollutionDetails; - try { - final JsonNode root = objectMapper.readTree(json); - airPollutionDetails = mapToAirPollution(root); - } catch (JsonProcessingException e) { - throw new RuntimeException("Cannot parse Air Pollution response"); - } - - return airPollutionDetails; - } - - private AirPollutionDetails mapToAirPollution(JsonNode rootNode) { - final AirPollutionDetails airPollutionDetails = new AirPollutionDetails(); - airPollutionDetails.setCoordinates(parseCoordinate(rootNode.get("coord"))); - - final List sampleList = new ArrayList<>(); - final JsonNode sampleListNode = rootNode.get("list"); - sampleListNode.forEach(sampleNode -> { - sampleList.add(parseAirPollutionSample(sampleNode)); - }); - airPollutionDetails.setAirPollutionRecords(sampleList); - - return airPollutionDetails; - } - - private AirPollutionRecord parseAirPollutionSample(JsonNode sampleNode) { - AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - airPollutionRecord.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sampleNode.get("dt").asInt()), TimeZone.getDefault().toZoneId())); - airPollutionRecord.setAirQualityIndex(AirQualityIndex.getByIndex(sampleNode.get("main").get("aqi").asInt())); - - final JsonNode componentsNode = sampleNode.get("components"); - airPollutionRecord.setCO(componentsNode.get("co").asDouble()); - airPollutionRecord.setNO(componentsNode.get("no").asDouble()); - airPollutionRecord.setNO2(componentsNode.get("no2").asDouble()); - airPollutionRecord.setO3(componentsNode.get("o3").asDouble()); - airPollutionRecord.setSO2(componentsNode.get("so2").asDouble()); - airPollutionRecord.setPM2_5(componentsNode.get("pm2_5").asDouble()); - airPollutionRecord.setPM10(componentsNode.get("pm10").asDouble()); - airPollutionRecord.setNH3(componentsNode.get("nh3").asDouble()); - - return airPollutionRecord; - } - - 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/ClimaticForecastResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/ClimaticForecastResponseMapper.java deleted file mode 100644 index 4dcc37e..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/ClimaticForecastResponseMapper.java +++ /dev/null @@ -1,84 +0,0 @@ -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.HumidityDeserializer; -import com.github.prominence.openweathermap.api.deserializer.WeatherStateDeserializer; -import com.github.prominence.openweathermap.api.deserializer.forecast.climatic.*; -import com.github.prominence.openweathermap.api.enums.UnitSystem; -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.forecast.climatic.*; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class ClimaticForecastResponseMapper extends AbstractMapper { - - public ClimaticForecastResponseMapper(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 ClimaticForecastTemperatureDeserializer()); - module.addDeserializer(AtmosphericPressure.class, new ClimaticForecastAtmosphericPressureDeserializer()); - module.addDeserializer(Humidity.class, new HumidityDeserializer()); - module.addDeserializer(Clouds.class, new ClimaticForecastCloudsDeserializer()); - module.addDeserializer(Rain.class, new ClimaticForecastRainDeserializer()); - module.addDeserializer(Snow.class, new ClimaticForecastSnowDeserializer()); - module.addDeserializer(Wind.class, new ClimaticForecastWindDeserializer()); - module.addDeserializer(Location.class, new ClimaticForecastLocationDeserializer()); - objectMapper.registerModule(module); - } - - 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", e); - } - - return forecast; - } - - private Forecast mapToForecast(JsonNode root) throws IOException { - final Forecast forecast = new Forecast(); - forecast.setLocation(objectMapper.readValue(objectMapper.treeAsTokens(root.get("city")), Location.class)); - - final List forecasts = new ArrayList<>(); - - 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(); - - weatherForecast.setForecastTime(parseDateTime(rootNode.get("dt"))); - weatherForecast.setSunriseTime(parseDateTime(rootNode.get("sunrise"))); - weatherForecast.setSunsetTime(parseDateTime(rootNode.get("sunset"))); - - weatherForecast.setWeatherStates(parseWeatherStates(rootNode.get("weather"))); - - weatherForecast.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Temperature.class)); - weatherForecast.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), AtmosphericPressure.class)); - weatherForecast.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Humidity.class)); - weatherForecast.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Clouds.class)); - weatherForecast.setWind(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Wind.class)); - weatherForecast.setRain(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Rain.class)); - weatherForecast.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Snow.class)); - - return weatherForecast; - } -} 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 deleted file mode 100644 index 08a7968..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapper.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.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.enums.UnitSystem; -import com.github.prominence.openweathermap.api.model.*; -import com.github.prominence.openweathermap.api.model.weather.Location; -import com.github.prominence.openweathermap.api.model.weather.Rain; -import com.github.prominence.openweathermap.api.model.weather.Snow; -import com.github.prominence.openweathermap.api.model.weather.Weather; - -import java.io.IOException; - -/** - * Official API response documentation: https://openweathermap.org/current#current_JSON. - * Ignored internal parameters: "root.cod", "sys.type", "sys.id", "sys.message". - */ -public class CurrentWeatherResponseMapper extends AbstractMapper { - /** - * Instantiates a new Current weather response mapper. - * - * @param unitSystem the unit system - */ - public CurrentWeatherResponseMapper(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(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); - } - - /** - * Gets single result. - * - * @param json the json string - * @return the weather object - */ - public Weather mapToWeather(String json) { - Weather weather; - try { - final JsonNode root = objectMapper.readTree(json); - weather = mapToWeather(root); - } catch (IOException e) { - throw new RuntimeException("Cannot parse Weather response", e); - } - - return weather; - } - - private Weather mapToWeather(JsonNode rootNode) throws IOException { - final JsonNode weatherArrayNode = rootNode.get("weather"); - final Weather weather = new Weather(); - - weather.setWeatherStates(parseWeatherStates(weatherArrayNode)); - - 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(parseDateTime(dtNode)); - } - - weather.setBase(rootNode.get("base").asText()); - - return weather; - } -} 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 deleted file mode 100644 index 4af016b..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapper.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.HumidityDeserializer; -import com.github.prominence.openweathermap.api.deserializer.WeatherStateDeserializer; -import com.github.prominence.openweathermap.api.deserializer.WindDeserializer; -import com.github.prominence.openweathermap.api.deserializer.forecast.daily.*; -import com.github.prominence.openweathermap.api.enums.UnitSystem; -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.forecast.daily.*; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Official API response documentation: https://openweathermap.org/forecast16#JSON. - */ -public class DailyForecastResponseMapper extends AbstractMapper { - public DailyForecastResponseMapper(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 DailyForecastTemperatureDeserializer()); - module.addDeserializer(AtmosphericPressure.class, new DailyForecastAtmosphericPressureDeserializer()); - module.addDeserializer(Humidity.class, new HumidityDeserializer()); - module.addDeserializer(Clouds.class, new DailyForecastCloudsDeserializer()); - module.addDeserializer(Rain.class, new DailyForecastRainDeserializer()); - module.addDeserializer(Snow.class, new DailyForecastSnowDeserializer()); - module.addDeserializer(Wind.class, new WindDeserializer()); - module.addDeserializer(Location.class, new DailyForecastLocationDeserializer()); - objectMapper.registerModule(module); - } - - /** - * 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", e); - } - - return forecast; - } - - private Forecast mapToForecast(JsonNode root) throws IOException { - final Forecast forecast = new Forecast(); - forecast.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)); - } - - forecast.setWeatherForecasts(forecasts); - - return forecast; - } - - private WeatherForecast parseWeatherForecast(JsonNode rootNode) throws IOException { - final WeatherForecast weatherForecast = new WeatherForecast(); - - weatherForecast.setForecastTime(parseDateTime(rootNode.get("dt"))); - weatherForecast.setSunriseTime(parseDateTime(rootNode.get("sunrise"))); - weatherForecast.setSunsetTime(parseDateTime(rootNode.get("sunset"))); - - weatherForecast.setWeatherStates(parseWeatherStates(rootNode.get("weather"))); - - weatherForecast.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Temperature.class)); - weatherForecast.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), AtmosphericPressure.class)); - weatherForecast.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Humidity.class)); - weatherForecast.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Clouds.class)); - weatherForecast.setWind(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Wind.class)); - weatherForecast.setRain(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Rain.class)); - weatherForecast.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Snow.class)); - - if (rootNode.has("pop")) { - weatherForecast.setProbabilityOfPrecipitation(rootNode.get("pop").asDouble()); - } - - return weatherForecast; - } -} 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 deleted file mode 100644 index 8789d78..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapper.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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.free.FreeForecastLocationDeserializer; -import com.github.prominence.openweathermap.api.deserializer.forecast.free.FreeForecastRainDeserializer; -import com.github.prominence.openweathermap.api.deserializer.forecast.free.FreeForecastSnowDeserializer; -import com.github.prominence.openweathermap.api.enums.UnitSystem; -import com.github.prominence.openweathermap.api.model.*; -import com.github.prominence.openweathermap.api.model.forecast.free.*; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Official API response documentation: https://openweathermap.org/forecast5#JSON. - */ -public class FiveDayThreeHourStepForecastResponseMapper extends AbstractMapper { - /** - * Instantiates a new forecast response mapper. - * - * @param unitSystem the unit system - */ - public FiveDayThreeHourStepForecastResponseMapper(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(Humidity.class, new HumidityDeserializer()); - module.addDeserializer(Clouds.class, new CloudsDeserializer()); - module.addDeserializer(Wind.class, new WindDeserializer()); - module.addDeserializer(Rain.class, new FreeForecastRainDeserializer()); - module.addDeserializer(Snow.class, new FreeForecastSnowDeserializer()); - module.addDeserializer(Location.class, new FreeForecastLocationDeserializer()); - objectMapper.registerModule(module); - - } - - /** - * 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", e); - } - - return forecast; - } - - private Forecast mapToForecast(JsonNode rootNode) throws IOException { - final Forecast forecast = new Forecast(); - forecast.setLocation(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("city")), Location.class)); - - final List forecasts = new ArrayList<>(rootNode.get("cnt").asInt()); - - final JsonNode forecastListNode = rootNode.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"); - weatherForecast.setWeatherStates(parseWeatherStates(weatherArrayNode)); - - 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); - } - - final JsonNode visibilityNode = rootNode.get("visibility"); - if (visibilityNode != null) { - weatherForecast.setVisibilityInMetres(visibilityNode.asDouble()); - } - final JsonNode popNode = rootNode.get("pop"); - if (popNode != null) { - weatherForecast.setProbabilityOfPrecipitation(popNode.asDouble()); - } - - weatherForecast.setForecastTime(parseDateTime(rootNode.get("dt"))); - weatherForecast.setForecastTimeISO(rootNode.get("dt_txt").asText()); - - return weatherForecast; - } -} 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 deleted file mode 100644 index 135c772..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapper.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.GeocodingRecord; -import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingRecord; - -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 deleted file mode 100644 index fa83130..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapper.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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 deleted file mode 100644 index 3ed4176..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapper.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * 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.onecall.*; -import com.github.prominence.openweathermap.api.enums.UnitSystem; -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.HistoricalWeatherData; -import com.github.prominence.openweathermap.api.model.onecall.historical.HourlyHistorical; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Official API response documentation: - * - */ -public class OneCallWeatherResponseMapper extends AbstractMapper { - /** - * Instantiates a new forecast response mapper. - * - * @param unitSystem the unit system - */ - public OneCallWeatherResponseMapper(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); - } - - /** - * Maps current weather data response into java object. - * - * @param json the json string - * @return the current data object - */ - public CurrentWeatherData mapToCurrent(String json) { - CurrentWeatherData currentData; - try { - final JsonNode root = objectMapper.readTree(json); - currentData = mapToCurrent(root); - } catch (IOException e) { - throw new RuntimeException("Cannot parse OneCall response", e); - } - - return currentData; - } - - /** - * Maps current weather data response into java object. - * - * @param json the json string - * @return the current data object - */ - public HistoricalWeatherData mapToHistorical(String json) { - HistoricalWeatherData historicalData; - try { - final JsonNode root = objectMapper.readTree(json); - historicalData = mapToHistorical(root); - } catch (IOException e) { - throw new RuntimeException("Cannot parse OneCall response"); - } - - return historicalData; - } - - private CurrentWeatherData mapToCurrent(JsonNode rootNode) throws IOException { - final CurrentWeatherData currentData = new CurrentWeatherData(); - currentData.setCoordinates(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"))); - currentData.setDailyList(parseDailyList(rootNode.get("daily"))); - currentData.setAlerts(parseAlerts(rootNode.get("alerts"))); - - return currentData; - } - - private Current parseCurrent(JsonNode currentNode) throws IOException { - if (currentNode == null) { - return null; - } - final Current current = new Current(); - 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.setUvIndex(currentNode.get("uvi").asDouble()); - final JsonNode visibilityNode = currentNode.get("visibility"); - if (visibilityNode != null) { - current.setVisibilityInMetres(visibilityNode.asDouble()); - } - - 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; - } - - private List parseMinutelyList(JsonNode minutelyListNode) { - if (minutelyListNode == null) { - return null; - } - final List minutelyList = new ArrayList<>(); - for (final JsonNode minutelyNode : minutelyListNode) { - minutelyList.add(Minutely.withValue( - parseDateTime(minutelyNode.get("dt")), - minutelyNode.get("precipitation").asDouble() - )); - } - - return minutelyList; - } - - 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(parseDateTime(hourlyNode.get("dt"))); - - 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) { - hourly.setUvIndex(uviNode.asDouble()); - } - - final JsonNode visibilityNode = hourlyNode.get("visibility"); - if (visibilityNode != null) { - hourly.setVisibilityInMetres(visibilityNode.asDouble()); - } - hourly.setWind(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Wind.class)); - final JsonNode popNode = hourlyNode.get("pop"); - if (popNode != null) { - hourly.setProbabilityOfPrecipitation(popNode.asDouble()); - } - hourly.setRain(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Rain.class)); - hourly.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Snow.class)); - - hourlyList.add(hourly); - } - - return hourlyList; - } - - 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(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(parseDateTime(moonriseTimeNode)); - } - final JsonNode moonsetTimeNode = dailyNode.get("moonset"); - if (moonsetTimeNode != null) { - daily.setMoonsetTime(parseDateTime(moonsetTimeNode)); - } - final JsonNode moonPhaseNode = dailyNode.get("moon_phase"); - if (moonPhaseNode != null) { - daily.setMoonPhase(new MoonPhase(moonPhaseNode.asDouble())); - } - - 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(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), DailyRain.class)); - daily.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), DailySnow.class)); - - dailyList.add(daily); - } - - return dailyList; - } - - private List parseAlerts(JsonNode alertsNode) throws IOException { - if (alertsNode == null || !alertsNode.isArray()) { - return null; - } - final List alerts = new ArrayList<>(); - for (final JsonNode alertNode : alertsNode) { - alerts.add(objectMapper.readValue(objectMapper.treeAsTokens(alertNode), Alert.class)); - } - return alerts; - } - - private HistoricalWeatherData mapToHistorical(JsonNode rootNode) throws IOException { - final HistoricalWeatherData historicalData = new HistoricalWeatherData(); - historicalData.setCoordinates(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) throws IOException { - if (currentNode == null) { - return null; - } - final HistoricalWeather historicalWeather = new HistoricalWeather(); - historicalWeather.setForecastTime(parseDateTime(currentNode.get("dt"))); - historicalWeather.setSunriseTime(parseDateTime(currentNode.get("sunrise"))); - historicalWeather.setSunsetTime(parseDateTime(currentNode.get("sunset"))); - - 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()); - } - - final JsonNode visibilityNode = currentNode.get("visibility"); - if (visibilityNode != null) { - historicalWeather.setVisibilityInMetres(visibilityNode.asDouble()); - } - 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) throws IOException { - if (hourlyListNode == null) { - return null; - } - final List hourlyList = new ArrayList<>(); - for (final JsonNode hourlyNode : hourlyListNode) { - final HourlyHistorical hourly = new HourlyHistorical(); - hourly.setForecastTime(parseDateTime(hourlyNode.get("dt"))); - - 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(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; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapper.java deleted file mode 100644 index cd62814..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapper.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.github.prominence.openweathermap.api.mapper; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.github.prominence.openweathermap.api.deserializer.roadrisk.RoadRiskAlertDeserializer; -import com.github.prominence.openweathermap.api.deserializer.roadrisk.RoadRiskRoadDetailsDeserializer; -import com.github.prominence.openweathermap.api.deserializer.roadrisk.RoadRiskWeatherDeserializer; -import com.github.prominence.openweathermap.api.model.Coordinates; -import com.github.prominence.openweathermap.api.model.roadrisk.Alert; -import com.github.prominence.openweathermap.api.model.roadrisk.RoadDetails; -import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskRecord; -import com.github.prominence.openweathermap.api.model.roadrisk.Weather; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class RoadRiskResponseMapper extends AbstractMapper { - - public RoadRiskResponseMapper() { - final SimpleModule module = new SimpleModule(); - module.addDeserializer(Weather.class, new RoadRiskWeatherDeserializer()); - module.addDeserializer(RoadDetails.class, new RoadRiskRoadDetailsDeserializer()); - module.addDeserializer(Alert.class, new RoadRiskAlertDeserializer()); - objectMapper.registerModule(module); - } - - public List mapToObjects(String jsonResponse) { - List roadRiskRecords; - try { - final JsonNode root = objectMapper.readTree(jsonResponse); - roadRiskRecords = mapToObjects(root); - } catch (IOException e) { - throw new RuntimeException("Cannot parse SolarRadiation response", e); - } - - return roadRiskRecords; - } - - private List mapToObjects(JsonNode rootNode) throws IOException { - List roadRiskRecords = new ArrayList<>(); - - if (rootNode.isArray()) { - for (JsonNode recordNode : rootNode) { - RoadRiskRecord roadRiskRecord = new RoadRiskRecord(); - roadRiskRecord.setForecastTime(parseDateTime(recordNode.get("dt"))); - - final JsonNode coordNode = recordNode.get("coord"); - roadRiskRecord.setCoordinates(Coordinates.of(coordNode.get(0).asDouble(), coordNode.get(1).asDouble())); - - roadRiskRecord.setWeather(objectMapper.readValue(objectMapper.treeAsTokens(recordNode.get("weather")), Weather.class)); - if (recordNode.has("road")) { - roadRiskRecord.setRoadDetails(objectMapper.readValue(objectMapper.treeAsTokens(recordNode.get("road")), RoadDetails.class)); - } - - final JsonNode alertsNode = recordNode.get("alerts"); - if (alertsNode != null && alertsNode.isArray()) { - List alerts = new ArrayList<>(); - for (JsonNode alertNode : alertsNode) { - alerts.add(objectMapper.readValue(objectMapper.treeAsTokens(alertNode), Alert.class)); - } - - roadRiskRecord.setAlerts(alerts); - } - - roadRiskRecords.add(roadRiskRecord); - } - } - - return roadRiskRecords; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/SolarRadiationResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/SolarRadiationResponseMapper.java deleted file mode 100644 index f99a3b9..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/mapper/SolarRadiationResponseMapper.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.github.prominence.openweathermap.api.mapper; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.github.prominence.openweathermap.api.deserializer.CoordinatesDeserializer; -import com.github.prominence.openweathermap.api.deserializer.radiation.SolarRadiationRecordDeserializer; -import com.github.prominence.openweathermap.api.model.Coordinates; -import com.github.prominence.openweathermap.api.model.radiation.SolarRadiation; -import com.github.prominence.openweathermap.api.model.radiation.SolarRadiationRecord; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class SolarRadiationResponseMapper extends AbstractMapper { - - public SolarRadiationResponseMapper() { - final SimpleModule module = new SimpleModule(); - module.addDeserializer(SolarRadiationRecord.class, new SolarRadiationRecordDeserializer()); - module.addDeserializer(Coordinates.class, new CoordinatesDeserializer()); - objectMapper.registerModule(module); - } - - public SolarRadiation mapToObject(String jsonResponse) { - SolarRadiation solarRadiation; - try { - final JsonNode root = objectMapper.readTree(jsonResponse); - solarRadiation = mapToObject(root); - } catch (IOException e) { - throw new RuntimeException("Cannot parse SolarRadiation response", e); - } - - return solarRadiation; - } - - private SolarRadiation mapToObject(JsonNode rootNode) throws IOException { - final SolarRadiation solarRadiation = new SolarRadiation(); - solarRadiation.setCoordinates(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("coord")), Coordinates.class)); - - final JsonNode listRecordsNode = rootNode.get("list"); - List radiationRecords = new ArrayList<>(); - for (JsonNode recordNode : listRecordsNode) { - radiationRecords.add(objectMapper.readValue(objectMapper.treeAsTokens(recordNode), SolarRadiationRecord.class)); - } - solarRadiation.setSolarRadiationRecords(radiationRecords); - - return solarRadiation; - } -} 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 deleted file mode 100644 index 663f39b..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/AtmosphericPressure.java +++ /dev/null @@ -1,156 +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; - -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 value; - - private Double seaLevelValue; - private Double groundLevelValue; - - /** - * Instantiates a new Pressure. - * - * @param value the value representing pressure value. - * @throws IllegalArgumentException in case if provided value isn't in allowed range. - */ - private AtmosphericPressure(double value) { - this.value = value; - } - - /** - * 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) { - throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range."); - } - return new AtmosphericPressure(value); - } - - /** - * Returns pressure value. - * - * @return pressure value. - */ - public double getValue() { - return value; - } - - /** - * Sets pressure value. - * - * @param value new pressure value. - * @throws IllegalArgumentException in case if provided value isn't in allowed range. - */ - public void setValue(double value) { - if (value < 0) { - throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range."); - } - this.value = value; - } - - /** - * 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; - } - - /** - * Gets ground level value. - * - * @return the ground level value. - */ - public Double getGroundLevelValue() { - return groundLevelValue; - } - - /** - * Sets ground level value. - * - * @param groundLevelValue the ground level value. - * @throws IllegalArgumentException in case if provided value isn't in allowed range. - */ - public void setGroundLevelValue(double groundLevelValue) { - if (groundLevelValue < 0) { - throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range."); - } - this.groundLevelValue = groundLevelValue; - } - - /** - * 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 instanceof AtmosphericPressure)) return false; - AtmosphericPressure atmosphericPressure = (AtmosphericPressure) o; - return Double.compare(atmosphericPressure.value, value) == 0 && - Objects.equals(seaLevelValue, atmosphericPressure.seaLevelValue) && - Objects.equals(groundLevelValue, atmosphericPressure.groundLevelValue); - } - - @Override - public int hashCode() { - return Objects.hash(value, seaLevelValue, groundLevelValue); - } - - @Override - public String toString() { - return "Pressure: " + value + ' ' + getUnit(); - } -} 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 deleted file mode 100644 index ad4cd5e..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Clouds.java +++ /dev/null @@ -1,107 +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; - -import java.util.Objects; - -/** - * The Clouds type represents cloudiness value percentage. - * Its value can only be an integer in [0, 100] range. - */ -public class Clouds { - private static final String DEFAULT_UNIT = "%"; - - private byte value; - - /** - * Instantiates a new Clouds. - * - * @param value the value representing cloudiness percentage. - * @throws IllegalArgumentException in case if provided value isn't in allowed range. - */ - private Clouds(byte value) { - this.value = value; - } - - /** - * 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) { - throw new IllegalArgumentException("Cloudiness value must be in [0, 100] range."); - } - return new Clouds(value); - } - - /** - * Returns cloudiness percentage value. - * - * @return cloudiness percentage. - */ - public byte getValue() { - return value; - } - - /** - * Sets cloudiness percentage value. - * - * @param value new cloudiness value. - * @throws IllegalArgumentException in case if provided value isn't in allowed range. - */ - public void setValue(byte value) { - if (value < 0 || value > 100) { - throw new IllegalArgumentException("Cloudiness value must be in [0, 100] range."); - } - this.value = value; - } - - /** - * Returns cloudiness unitSystem. Constantly equals to '%'. - * - * @return the cloudiness unitSystem. - */ - public String getUnit() { - return DEFAULT_UNIT; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Clouds)) return false; - Clouds clouds = (Clouds) o; - return value == clouds.value; - } - - @Override - public int hashCode() { - return Objects.hash(value); - } - - @Override - public String toString() { - return "Clouds: " + value + getUnit(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/Coordinates.java b/src/main/java/com/github/prominence/openweathermap/api/model/Coordinates.java deleted file mode 100644 index 0066b8f..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Coordinates.java +++ /dev/null @@ -1,126 +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; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.Objects; - -/** - * Represents some location by its latitude and longitude. - */ -public class Coordinates { - @JsonProperty("lat") - private double latitude; - @JsonProperty("lon") - private double longitude; - - private Coordinates() { - - } - - /** - * Method for {@link Coordinates} creation with correctness check. - * - * @param latitude latitude - * @param longitude longitude - * @return coordinate object. - */ - 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) { - if (latitude < -90 || latitude > 90) { - throw new IllegalArgumentException("Latitude value must be in the next range: [-90.0; 90.0]."); - } - this.latitude = latitude; - } - - /** - * Sets longitude with checks. - * - * @param longitude longitude value - */ - public void setLongitude(double longitude) { - if (longitude < -180 || longitude > 180) { - throw new IllegalArgumentException("Longitude value must be in the next range: [-180.0; 180.0]."); - } - this.longitude = longitude; - } - - /** - * Returns latitude. - * - * @return latitude - */ - public double getLatitude() { - return latitude; - } - - /** - * Returns longitude. - * - * @return longitude - */ - public double getLongitude() { - return longitude; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Coordinates)) return false; - Coordinates that = (Coordinates) o; - return Double.compare(that.latitude, latitude) == 0 && - Double.compare(that.longitude, longitude) == 0; - } - - @Override - public int hashCode() { - return Objects.hash(latitude, longitude); - } - - @Override - public String toString() { - return formatAsDegree(latitude) + - ", " + formatAsDegree(longitude); - } - - private String formatAsDegree(double value) { - int degrees = (int) value; - double secondsDouble = value % 1 * 60; - int minutes = (int) secondsDouble; - int seconds = (int) (secondsDouble % 1 * 60); - - return String.format("%s° %s′ %s″", degrees, minutes, seconds); - } -} 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 deleted file mode 100644 index 6ae7322..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Humidity.java +++ /dev/null @@ -1,107 +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; - -import java.util.Objects; - -/** - * The Humidity type represents humidity value percentage. - * Its value can only be an integer in [0, 100] range. - */ -public class Humidity { - private static final String DEFAULT_UNIT = "%"; - - private int value; - - /** - * Instantiates a new Humidity. - * - * @param value the value representing humidity percentage. - * @throws IllegalArgumentException in case if provided value isn't in allowed range. - */ - private Humidity(byte value) { - this.value = value; - } - - /** - * 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) { - throw new IllegalArgumentException("Humidity value must be in [0, 100] range."); - } - return new Humidity(value); - } - - /** - * Returns humidity percentage value. - * - * @return humidity percentage. - */ - public int getValue() { - return value; - } - - /** - * Sets humidity percentage value. - * - * @param value new humidity value. - * @throws IllegalArgumentException in case if provided value isn't in allowed range. - */ - public void setValue(int value) { - if (value < 0 || value > 100) { - throw new IllegalArgumentException("Humidity value must be in [0, 100] range."); - } - this.value = value; - } - - /** - * Returns humidity unitSystem. Constantly equals to '%'. - * - * @return the humidity unitSystem. - */ - public String getUnit() { - return DEFAULT_UNIT; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Humidity)) return false; - Humidity humidity = (Humidity) o; - return value == humidity.value; - } - - @Override - public int hashCode() { - return Objects.hash(value); - } - - @Override - public String toString() { - return "Humidity: " + value + getUnit(); - } -} 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 deleted file mode 100644 index b400e99..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Temperature.java +++ /dev/null @@ -1,193 +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; - -import java.util.Objects; - -/** - * Represents temperature values and unit. - */ -public class Temperature { - private double value; - private Double maxTemperature; - private Double minTemperature; - private Double feelsLike; - private String unit; - - private Temperature(double value, String unit) { - this.value = value; - this.unit = unit; - } - - /** - * Creates {@link Temperature} object with correctness check. - * - * @param value temperature value - * @param unit temperature unit - * @return temperature object - */ - public static Temperature withValue(double value, String unit) { - if (unit == null) { - throw new IllegalArgumentException("Unit must be set."); - } - return new Temperature(value, unit); - } - - /** - * Returns temperature value. - * - * @return value - */ - public double getValue() { - return value; - } - - /** - * Sets temperature value. - * - * @param value temperature - */ - public void setValue(double value) { - this.value = value; - } - - /** - * Returns maximal temperature value. - * - * @return maximal temperature value - */ - public Double getMaxTemperature() { - return maxTemperature; - } - - /** - * Sets maximal temperature value. - * - * @param maxTemperature maximal temperature - */ - public void setMaxTemperature(Double maxTemperature) { - this.maxTemperature = maxTemperature; - } - - /** - * Returns minimal temperature value. - * - * @return minimal temperature value - */ - public Double getMinTemperature() { - return minTemperature; - } - - /** - * Sets minimal temperature value. - * - * @param minTemperature minimal temperature - */ - public void setMinTemperature(Double minTemperature) { - this.minTemperature = minTemperature; - } - - /** - * Returns 'feels like' temperature value. - * - * @return 'feels like' temperature value - */ - public Double getFeelsLike() { - return feelsLike; - } - - /** - * Sets 'feels like' temperature value. - * - * @param feelsLike 'feels like' temperature - */ - public void setFeelsLike(Double feelsLike) { - this.feelsLike = feelsLike; - } - - /** - * Returns temperature unit. - * - * @return unit - */ - public String getUnit() { - return unit; - } - - /** - * Sets temperature unit with correctness check. - * - * @param unit temperature unit - */ - 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 Temperature that)) return false; - return Double.compare(that.value, value) == 0 && - Objects.equals(maxTemperature, that.maxTemperature) && - Objects.equals(minTemperature, that.minTemperature) && - Objects.equals(feelsLike, that.feelsLike) && - Objects.equals(unit, that.unit); - } - - @Override - public int hashCode() { - return Objects.hash(value, maxTemperature, minTemperature, feelsLike, unit); - } - - @Override - public String toString() { - final StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Temperature: "); - stringBuilder.append(value); - stringBuilder.append(' '); - stringBuilder.append(unit); - if (maxTemperature != null) { - stringBuilder.append(", Maximum value: "); - stringBuilder.append(maxTemperature); - stringBuilder.append(' '); - stringBuilder.append(unit); - } - if (minTemperature != null) { - stringBuilder.append(", Minimum value: "); - stringBuilder.append(minTemperature); - stringBuilder.append(' '); - stringBuilder.append(unit); - } - if (feelsLike != null) { - stringBuilder.append(", Feels like: "); - stringBuilder.append(feelsLike); - stringBuilder.append(' '); - stringBuilder.append(unit); - } - - return stringBuilder.toString(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/WeatherState.java b/src/main/java/com/github/prominence/openweathermap/api/model/WeatherState.java deleted file mode 100644 index c729a2e..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/WeatherState.java +++ /dev/null @@ -1,136 +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; - -import com.github.prominence.openweathermap.api.enums.WeatherCondition; - -import java.util.Objects; - -/** - * The type Weather state. - */ -public class WeatherState { - private final int id; - private final String name; - private final String description; - private String iconId; - private final WeatherCondition weatherConditionEnum; - - public WeatherState(Integer id, String name, String description) { - this.id = id; - this.name = name; - this.description = description; - this.weatherConditionEnum = WeatherCondition.getById(id); - } - - /** - * Gets id. - * - * @return the id - */ - public int getId() { - return id; - } - - /** - * Gets name. - * - * @return the name - */ - public String getName() { - return name; - } - - /** - * Gets description. - * - * @return the description - */ - public String getDescription() { - return description; - } - - /** - * Gets icon id. - * - * @return the icon id - */ - public String getIconId() { - return iconId; - } - - /** - * Sets icon id. - * - * @param iconId the icon id - */ - public void setIconId(String iconId) { - this.iconId = iconId; - } - - /** - * Gets weather condition enum. - * - * @return the weather condition enum - */ - public WeatherCondition getWeatherConditionEnum() { - return weatherConditionEnum; - } - - /** - * Gets weather icon url. - * - * @return the weather icon url - */ - public String getWeatherIconUrl() { - if (iconId != null) { - return WeatherCondition.getIconUrl(iconId); - } - if (weatherConditionEnum != null) { - // return the default one for the current weather condition - return weatherConditionEnum.getDayIconUrl(); - } - return null; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - WeatherState that = (WeatherState) o; - return Objects.equals(id, that.id) && - Objects.equals(name, that.name) && - Objects.equals(description, that.description) && - Objects.equals(iconId, that.iconId); - } - - @Override - public int hashCode() { - return Objects.hash(id, name, description, iconId, weatherConditionEnum); - } - - @Override - public String toString() { - return "Weather state: " + name + "(" + description + ")."; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/Wind.java b/src/main/java/com/github/prominence/openweathermap/api/model/Wind.java deleted file mode 100644 index 282da8a..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Wind.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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; - -import java.util.Objects; - -/** - * The type Wind. - */ -public class Wind { - private double speed; - private Double degrees; - private Double gust; - 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 speed - * @param unit the unitSystem - * @return 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 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/air/pollution/AirPollutionConcentration.java b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionConcentration.java new file mode 100644 index 0000000..228699c --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionConcentration.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021-present 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.air.pollution; + +import com.github.prominence.openweathermap.api.enums.AirQualityIndex; + +import java.time.OffsetDateTime; + +/** + * Interface of air pollution concentration measurements. + */ +public interface AirPollutionConcentration { + /** + * The date time when the measurement happened. + * + * @return datetime + */ + OffsetDateTime getMeasurementTime(); + + /** + * The air quality index as an (overview). + * + * @return index + */ + AirQualityIndex getAirQualityIndex(); + + /** + * The concentration of CO in the air. + * + * @return CO + */ + Concentration getCarbonMonoxide(); + + /** + * The concentration of NO in the air. + * + * @return NO + */ + Concentration getNitrogenMonoxide(); + + /** + * The concentration of NO2 in the air. + * + * @return NO2 + */ + Concentration getNitrogenDioxide(); + + /** + * The concentration of O3 in the air. + * + * @return O3 + */ + Concentration getOzone(); + + /** + * The concentration of SO2 in the air. + * + * @return SO2 + */ + Concentration getSulphurDioxide(); + + /** + * The concentration of pine particles matter in the air. + * + * @return fine particles + */ + Concentration getFineParticlesMatter(); + + /** + * The concentration of coarse particulate matter in the air. + * + * @return coarse particles + */ + Concentration getCoarseParticulateMatter(); + + /** + * The concentration of NH3 in the air. + * + * @return NH3 + */ + Concentration getAmmonia(); +} 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 ba6fbf4..9bf79b9 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 @@ -1,87 +1,39 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.air.pollution; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.CoordinateAware; import java.util.List; -import java.util.Objects; /** - * The type Air pollution. + * Interface of air pollution overview. */ -public class AirPollutionDetails { - private Coordinates coordinates; - private List airPollutionRecords; +public interface AirPollutionDetails extends CoordinateAware { /** - * Gets coordinate. - * - * @return the coordinate + * The pollution details. + * @return pollution */ - public Coordinates getCoordinates() { - return coordinates; - } - - /** - * Sets coordinate. - * - * @param coordinates the coordinate - */ - public void setCoordinates(Coordinates coordinates) { - this.coordinates = coordinates; - } - - /** - * Gets air pollution details. - * - * @return the air pollution details - */ - public List getAirPollutionRecords() { - return airPollutionRecords; - } - - /** - * Sets air pollution details. - * - * @param airPollutionRecords the air pollution details - */ - public void setAirPollutionRecords(List airPollutionRecords) { - this.airPollutionRecords = airPollutionRecords; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AirPollutionDetails that = (AirPollutionDetails) o; - return Objects.equals(coordinates, that.coordinates) && Objects.equals(airPollutionRecords, that.airPollutionRecords); - } - - @Override - public int hashCode() { - return Objects.hash(coordinates, airPollutionRecords); - } + List getAirPollutionConcentration(); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsModel.java new file mode 100644 index 0000000..ffce322 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsModel.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021-present 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.air.pollution; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import lombok.Data; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * The type representing Air pollution data. + */ +@Data +public class AirPollutionDetailsModel implements AirPollutionDetails { + @JsonProperty("coord") + private Coordinates coordinates; + @JsonProperty("list") + private List airPollutionRecords; + + @JsonIgnore + @Override + public List getAirPollutionConcentration() { + return airPollutionRecords.stream() + .map(AirPollutionConcentration.class::cast) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionMeasurements.java b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionMeasurements.java new file mode 100644 index 0000000..d8310e6 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionMeasurements.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021-present 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.air.pollution; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.ConcentrationDeserializer; +import lombok.Data; + +/** + * The type Air pollution record. + */ +@Data +public class AirPollutionMeasurements { + + @JsonDeserialize(using = ConcentrationDeserializer.class) + @JsonProperty("co") + private Concentration carbonMonoxide; + @JsonDeserialize(using = ConcentrationDeserializer.class) + @JsonProperty("no") + private Concentration nitrogenMonoxide; + @JsonDeserialize(using = ConcentrationDeserializer.class) + @JsonProperty("no2") + private Concentration nitrogenDioxide; + @JsonDeserialize(using = ConcentrationDeserializer.class) + @JsonProperty("o3") + private Concentration ozone; + @JsonDeserialize(using = ConcentrationDeserializer.class) + @JsonProperty("so2") + private Concentration sulphurDioxide; + @JsonDeserialize(using = ConcentrationDeserializer.class) + @JsonProperty("pm2_5") + private Concentration fineParticlesMatter; + @JsonDeserialize(using = ConcentrationDeserializer.class) + @JsonProperty("pm10") + private Concentration coarseParticulateMatter; + @JsonDeserialize(using = ConcentrationDeserializer.class) + @JsonProperty("nh3") + private Concentration ammonia; + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecord.java b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecord.java index 7ced2be..c0e0e4f 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecord.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecord.java @@ -1,376 +1,105 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.air.pollution; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; import com.github.prominence.openweathermap.api.enums.AirQualityIndex; +import lombok.Data; -import java.time.LocalDateTime; -import java.util.Objects; -import java.util.stream.Stream; +import java.time.OffsetDateTime; +import java.util.Optional; /** - * The type Air pollution record. + * The type representing an Air pollution record. */ -public class AirPollutionRecord { - private LocalDateTime forecastTime; +@Data +public class AirPollutionRecord implements AirPollutionConcentration { + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime measurementTime; + @JsonProperty("main") private AirQualityIndex airQualityIndex; + @JsonProperty("components") + private AirPollutionMeasurements components; - private Double CO; - private Double NO; - private Double NO2; - private Double O3; - private Double SO2; - private Double PM2_5; - private Double PM10; - private Double NH3; - - /** - * Gets forecast time. - * - * @return the forecast time - */ - public LocalDateTime getForecastTime() { - return forecastTime; + @Override + public OffsetDateTime getMeasurementTime() { + return measurementTime; } - /** - * Sets forecast time. - * - * @param forecastTime the forecast time - */ - public void setForecastTime(LocalDateTime forecastTime) { - this.forecastTime = forecastTime; - } - - /** - * Gets air quality index. - * - * @return the air quality index - */ + @Override public AirQualityIndex getAirQualityIndex() { return airQualityIndex; } - /** - * Sets air quality index. - * - * @param airQualityIndex the air quality index - */ - public void setAirQualityIndex(AirQualityIndex airQualityIndex) { - this.airQualityIndex = airQualityIndex; - } - - /** - * Gets carbon monoxide concentration value in μg/m^3. - * - * @return the carbon monoxide value - */ - public Double getCO() { - return CO; - } - - /** - * Gets carbon monoxide concentration value in μg/m^3. - * - * @return the carbon monoxide value - */ - public Double getCarbonMonoxide() { - return getCO(); - } - - /** - * Sets carbon monoxide concentration value in μg/m^3. - * - * @param CO the carbon monoxide value - */ - public void setCO(Double CO) { - this.CO = CO; - } - - /** - * Gets nitrogen monoxide concentration value in μg/m^3. - * - * @return the nitrogen monoxide value - */ - public Double getNO() { - return NO; - } - - /** - * Gets nitrogen monoxide concentration value in μg/m^3. - * - * @return the nitrogen monoxide value - */ - public Double getNitrogenMonoxide() { - return getNO(); - } - - /** - * Sets nitrogen monoxide concentration value in μg/m^3. - * - * @param NO the nitrogen monoxide value - */ - public void setNO(Double NO) { - this.NO = NO; - } - - /** - * Gets nitrogen dioxide concentration value in μg/m^3. - * - * @return the nitrogen dioxide value - */ - public Double getNO2() { - return NO2; - } - - /** - * Gets nitrogen dioxide concentration value in μg/m^3. - * - * @return the nitrogen dioxide value - */ - public Double getNitrogenDioxide() { - return getNO2(); - } - - /** - * Sets nitrogen dioxide concentration value in μg/m^3. - * - * @param NO2 the nitrogen dioxide value - */ - public void setNO2(Double NO2) { - this.NO2 = NO2; - } - - /** - * Gets ozone concentration value in μg/m^3. - * - * @return the ozone value - */ - public Double getO3() { - return O3; - } - - /** - * Gets ozone concentration value in μg/m^3. - * - * @return the ozone value - */ - public Double getOzone() { - return getO3(); - } - - /** - * Sets ozone concentration value in μg/m^3. - * - * @param o3 the ozone value - */ - public void setO3(Double o3) { - O3 = o3; - } - - /** - * Gets sulphur dioxide concentration value in μg/m^3. - * - * @return the sulphur dioxide value - */ - public Double getSO2() { - return SO2; - } - - /** - * Gets sulphur dioxide concentration value in μg/m^3. - * - * @return the sulphur dioxide value - */ - public Double getSulphurDioxide() { - return getSO2(); - } - - /** - * Sets sulphur dioxide concentration value in μg/m^3. - * - * @param SO2 the sulphur dioxide value - */ - public void setSO2(Double SO2) { - this.SO2 = SO2; - } - - /** - * Gets fine particles matter concentration value in μg/m^3. - * - * @return the fine particles matter value - */ - public Double getPM2_5() { - return PM2_5; - } - - /** - * Gets fine particles matter concentration value in μg/m^3. - * - * @return the fine particles matter value - */ - public Double getFineParticlesMatter() { - return getPM2_5(); - } - - /** - * Sets fine particles matter concentration value in μg/m^3. - * - * @param PM2_5 the fine particles matter value - */ - public void setPM2_5(Double PM2_5) { - this.PM2_5 = PM2_5; - } - - /** - * Gets coarse particulate matter concentration value in μg/m^3. - * - * @return the coarse particulate matter value - */ - public Double getPM10() { - return PM10; - } - - /** - * Gets coarse particulate matter concentration value in μg/m^3. - * - * @return the coarse particulate matter value - */ - public Double getCoarseParticulateMatter() { - return getPM10(); - } - - /** - * Sets coarse particulate matter concentration value in μg/m^3. - * - * @param PM10 the coarse particulate matter value - */ - public void setPM10(Double PM10) { - this.PM10 = PM10; - } - - /** - * Gets ammonia concentration value in μg/m^3. - * - * @return the ammonia value - */ - public Double getNH3() { - return NH3; - } - - /** - * Gets ammonia concentration value in μg/m^3. - * - * @return the ammonia value - */ - public Double getAmmonia() { - return getNH3(); - } - - /** - * Sets ammonia concentration value in μg/m^3. - * - * @param NH3 the ammonia value - */ - public void setNH3(Double NH3) { - this.NH3 = NH3; - } - + @JsonIgnore @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AirPollutionRecord that = (AirPollutionRecord) o; - return Objects.equals(forecastTime, that.forecastTime) && airQualityIndex == that.airQualityIndex && Objects.equals(CO, that.CO) && Objects.equals(NO, that.NO) && Objects.equals(NO2, that.NO2) && Objects.equals(O3, that.O3) && Objects.equals(SO2, that.SO2) && Objects.equals(PM2_5, that.PM2_5) && Objects.equals(PM10, that.PM10) && Objects.equals(NH3, that.NH3); + public Concentration getCarbonMonoxide() { + return Optional.ofNullable(components).map(AirPollutionMeasurements::getCarbonMonoxide).orElse(null); } + @JsonIgnore @Override - public int hashCode() { - return Objects.hash(forecastTime, airQualityIndex, CO, NO, NO2, O3, SO2, PM2_5, PM10, NH3); + public Concentration getNitrogenMonoxide() { + return Optional.ofNullable(components).map(AirPollutionMeasurements::getNitrogenMonoxide).orElse(null); } + @JsonIgnore @Override - public String toString() { - final StringBuilder stringBuilder = new StringBuilder() - .append("Air Pollution Record for ") - .append(forecastTime) - .append(", AQI=") - .append(airQualityIndex.name()) - .append("."); - final boolean anyConcentrationAvailable = Stream.of(CO, NO, NO2, O3, SO2, PM2_5, PM10, NH3).anyMatch(Objects::nonNull); - if (anyConcentrationAvailable) { - stringBuilder.append(" Concentrations:"); - if (CO != null) { - stringBuilder - .append(" CO(Carbon monoxide) = ") - .append(CO) - .append(" μg/m^3;"); - } - if (NO != null) { - stringBuilder - .append(" NO(Nitrogen monoxide) = ") - .append(NO) - .append(" μg/m^3;"); - } - if (NO2 != null) { - stringBuilder - .append(" NO2(Nitrogen dioxide) = ") - .append(NO2) - .append(" μg/m^3;"); - } - if (O3 != null) { - stringBuilder - .append(" O3(Ozone) = ") - .append(O3) - .append(" μg/m^3;"); - } - if (SO2 != null) { - stringBuilder - .append(" SO2(Sulphur dioxide) = ") - .append(SO2) - .append(" μg/m^3;"); - } - if (PM2_5 != null) { - stringBuilder - .append(" PM2.5(Fine particles matter) = ") - .append(PM2_5) - .append(" μg/m^3;"); - } - if (PM10 != null) { - stringBuilder - .append(" PM10(Coarse particulate matter) = ") - .append(PM10) - .append(" μg/m^3;"); - } - if (NH3 != null) { - stringBuilder - .append(" NH3(Ammonia) = ") - .append(NH3) - .append(" μg/m^3;"); - } - } - return stringBuilder.toString(); + public Concentration getNitrogenDioxide() { + return Optional.ofNullable(components).map(AirPollutionMeasurements::getNitrogenDioxide).orElse(null); + } + + @JsonIgnore + @Override + public Concentration getOzone() { + return Optional.ofNullable(components).map(AirPollutionMeasurements::getOzone).orElse(null); + } + + @JsonIgnore + @Override + public Concentration getSulphurDioxide() { + return Optional.ofNullable(components).map(AirPollutionMeasurements::getSulphurDioxide).orElse(null); + } + + @JsonIgnore + @Override + public Concentration getFineParticlesMatter() { + return Optional.ofNullable(components).map(AirPollutionMeasurements::getFineParticlesMatter).orElse(null); + } + + @JsonIgnore + @Override + public Concentration getCoarseParticulateMatter() { + return Optional.ofNullable(components).map(AirPollutionMeasurements::getCoarseParticulateMatter).orElse(null); + } + + @JsonIgnore + @Override + public Concentration getAmmonia() { + return Optional.ofNullable(components).map(AirPollutionMeasurements::getAmmonia).orElse(null); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/Concentration.java b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/Concentration.java new file mode 100644 index 0000000..4161014 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/Concentration.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021-present 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.air.pollution; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NonNull; +import lombok.ToString; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * Entity for air pollution concentration measurement. + */ +@EqualsAndHashCode +@ToString +@AllArgsConstructor +public class Concentration { + private static final int DECIMAL_PLACES = 10; + @NonNull + private final BigDecimal value; + + /** + * Returns the measured value in micrograms/m^3. + * + * @return value + */ + @JsonIgnore + public BigDecimal asMicrogramsPerCubicMeters() { + return value.setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/MetaData.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/MetaData.java new file mode 100644 index 0000000..9edbfcd --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/MetaData.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021-present 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 com.fasterxml.jackson.annotation.JsonProperty; +import com.github.prominence.openweathermap.api.enums.DayTime; +import lombok.Data; + +@Data +public class MetaData { + @JsonProperty("pod") + private DayTime partOfDay; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/AtmosphericPressure.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/AtmosphericPressure.java deleted file mode 100644 index 164a524..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/AtmosphericPressure.java +++ /dev/null @@ -1,98 +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.climatic; - -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; - - protected 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/climatic/Forecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Forecast.java deleted file mode 100644 index e36295a..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Forecast.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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.climatic; - - -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/climatic/Location.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Location.java deleted file mode 100644 index 1730300..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Location.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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.climatic; - -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; - - protected 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 getCoordinates() { - return coordinates; - } - - /** - * Sets location coordinates. - * @param coordinates location coordinates - */ - public void setCoordinates(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/climatic/Rain.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Rain.java deleted file mode 100644 index 055c6a4..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Rain.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.climatic; - -import java.util.Objects; - -/** - * Represents rain information. - */ -public class Rain { - private static final String DEFAULT_UNIT = "mm"; - - private double level; - - protected Rain(double level) { - this.level = level; - } - - /** - * Creates {@link Rain} object with correctness check. - * @param level rain level value - * @return rain object. - */ - public static Rain withValue(double level) { - if (level < 0) { - throw new IllegalArgumentException("Rain level value cannot be negative."); - } - return new Rain(level); - } - - /** - * Returns rain level value. - * @return rain level value - */ - public double getLevel() { - return level; - } - - /** - * Sets rain level value with correctness check. - * @param level 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 "Rain precipitation volume, mm: " + - level + ' ' + - getUnit(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Snow.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Snow.java deleted file mode 100644 index 1e8e01d..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Snow.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.climatic; - -import java.util.Objects; - -/** - * Represents snow information. - */ -public class Snow { - private static final String DEFAULT_UNIT = "mm"; - - private double level; - - protected Snow(double level) { - this.level = level; - } - - /** - * Creates {@link Snow} object with correctness check. - * @param threeHourLevel snow level value - * @return snow object. - */ - public static Snow withValue(double threeHourLevel) { - if (threeHourLevel < 0) { - throw new IllegalArgumentException("Snow level value cannot be negative."); - } - return new Snow(threeHourLevel); - } - - /** - * Returns snow level value. - * @return snow level value - */ - public double getLevel() { - return level; - } - - /** - * Sets snow level value with correctness check. - * @param level 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 "Snow volume, mm: " + - level + ' ' + - getUnit(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Temperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Temperature.java deleted file mode 100644 index 18e003d..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Temperature.java +++ /dev/null @@ -1,263 +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.climatic; - -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/climatic/ThirtyDaysDailyForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/ThirtyDaysDailyForecast.java new file mode 100644 index 0000000..f20f1e1 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/ThirtyDaysDailyForecast.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021-present 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.climatic; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; + +import java.util.List; + +/** + * Root object for 30 days long daily forecasts. + */ +public interface ThirtyDaysDailyForecast { + + /** + * The location where the forecast belongs to. + * @return location + */ + @JsonIgnore + BaseLocation getLocation(); + + /** + * The forecasts. + * @return days + */ + @JsonIgnore + List getWeatherForecasts(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/ThirtyDaysDailyForecastModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/ThirtyDaysDailyForecastModel.java new file mode 100644 index 0000000..46d3cb3 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/ThirtyDaysDailyForecastModel.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021-present 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.climatic; + + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocationModel; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Represents information about forecast for different timestamps. + */ +@Data +public class ThirtyDaysDailyForecastModel implements ThirtyDaysDailyForecast { + @JsonProperty("cod") + private long cod; + @JsonProperty("message") + private BigDecimal message; + @JsonProperty("city") + private BaseLocationModel locationModel; + @JsonProperty("list") + private List forecasts; + + @Override + @JsonIgnore + public BaseLocation getLocation() { + return locationModel; + } + + @Override + @JsonIgnore + public List getWeatherForecasts() { + return forecasts.stream().map(WeatherForecastDay.class::cast).collect(Collectors.toList()); + } + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/WeatherForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/WeatherForecast.java index 6427b21..a622a5a 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/WeatherForecast.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/WeatherForecast.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,273 +23,171 @@ package com.github.prominence.openweathermap.api.model.forecast.climatic; -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.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.deserializer.RequiredPercentageDeserializer; +import com.github.prominence.openweathermap.api.deserializer.WindSpeedDeserializer; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.clouds.Clouds; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationValues; +import com.github.prominence.openweathermap.api.model.generic.pressure.BaseAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.DailyTemperature; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureDailyBasic; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureDailyDetailed; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.wind.BasicWind; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; +import lombok.Data; -import java.time.LocalDateTime; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; +import java.util.Optional; /** * Represents weather forecast information for a particular timestamp. */ -public class WeatherForecast { - private LocalDateTime forecastTime; - private LocalDateTime sunriseTime; - private LocalDateTime sunsetTime; +@Data +public class WeatherForecast implements WeatherForecastDay, DailyTemperature, BaseAtmosphericPressure, BasicWind, Humidity, + PrecipitationValues, SunlightStages { + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime forecastTime; + @JsonProperty("temp") + private TemperatureDailyDetailed temperature; + @JsonProperty("feels_like") + private TemperatureDailyBasic feelsLike; + @JsonProperty("weather") + private List weatherStates = new ArrayList<>(); + @JsonDeserialize(using = RequiredPercentageDeserializer.class) + @JsonProperty("humidity") + private int humidityPercentage; + @JsonProperty("pressure") + private BigDecimal pressure; + @JsonDeserialize(using = RequiredPercentageDeserializer.class) + @JsonProperty("clouds") + private int clouds; + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("speed") + private WindSpeed speed; + @JsonProperty("deg") + private Integer directionDegrees; + @JsonProperty("rain") + private BigDecimal rain; + @JsonProperty("snow") + private BigDecimal snow; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunrise") + private OffsetDateTime sunriseTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunset") + private OffsetDateTime sunsetTime; - private List weatherStates; - 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; + @Override + @JsonIgnore + public DailyTemperature getTemperature() { + return this; } - /** - * Sets forecast time. - * - * @param forecastTime the forecast time - */ - public void setForecastTime(LocalDateTime forecastTime) { - this.forecastTime = forecastTime; + @Override + @JsonIgnore + public BasicWind getWind() { + return this; } - public LocalDateTime getSunriseTime() { - return sunriseTime; + @Override + @JsonIgnore + public TemperatureValue getMorning() { + return Optional.ofNullable(temperature).map(TemperatureDailyBasic::getMorning).orElse(null); } - public void setSunriseTime(LocalDateTime sunriseTime) { - this.sunriseTime = sunriseTime; + @Override + @JsonIgnore + public TemperatureValue getDay() { + return Optional.ofNullable(temperature).map(TemperatureDailyBasic::getDay).orElse(null); } - public LocalDateTime getSunsetTime() { - return sunsetTime; + @Override + @JsonIgnore + public TemperatureValue getEve() { + return Optional.ofNullable(temperature).map(TemperatureDailyBasic::getEve).orElse(null); } - public void setSunsetTime(LocalDateTime sunsetTime) { - this.sunsetTime = sunsetTime; + @Override + @JsonIgnore + public TemperatureValue getNight() { + return Optional.ofNullable(temperature).map(TemperatureDailyBasic::getNight).orElse(null); } - /** - * Gets weather state. - * - * @return the weather state - */ - public List getWeatherStates() { - return weatherStates; + @Override + @JsonIgnore + public TemperatureValue getMin() { + return Optional.ofNullable(temperature).map(TemperatureDailyDetailed::getMin).orElse(null); } - /** - * Sets weather state. - * - * @param weatherStates the weather state - */ - public void setWeatherStates(List weatherStates) { - this.weatherStates = weatherStates; + @Override + @JsonIgnore + public TemperatureValue getMax() { + return Optional.ofNullable(temperature).map(TemperatureDailyDetailed::getMax).orElse(null); } - /** - * Gets temperature. - * - * @return the temperature - */ - public Temperature getTemperature() { - return temperature; + @Override + @JsonIgnore + public TemperatureValue getMorningFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getMorning).orElse(null); } - /** - * Sets temperature. - * - * @param temperature the temperature - */ - public void setTemperature(Temperature temperature) { - this.temperature = temperature; + @Override + @JsonIgnore + public TemperatureValue getDayFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getDay).orElse(null); } - /** - * Gets atmospheric pressure. - * - * @return the atmospheric pressure - */ - public AtmosphericPressure getAtmosphericPressure() { - return atmosphericPressure; + @Override + @JsonIgnore + public TemperatureValue getEveFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getEve).orElse(null); } - /** - * Sets atmospheric pressure. - * - * @param atmosphericPressure the atmospheric pressure - */ - public void setAtmosphericPressure(AtmosphericPressure atmosphericPressure) { - this.atmosphericPressure = atmosphericPressure; + @Override + @JsonIgnore + public TemperatureValue getNightFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getNight).orElse(null); } - /** - * Gets humidity. - * - * @return the humidity - */ + @Override + @JsonIgnore 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; + return this; } @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(sunriseTime, that.sunriseTime) && - Objects.equals(sunsetTime, that.sunsetTime) && - 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); + @JsonIgnore + public BaseAtmosphericPressure getAtmosphericPressure() { + return this; } @Override - public int hashCode() { - return Objects.hash(forecastTime, sunriseTime, sunsetTime, weatherStates, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds); + @JsonIgnore + public CloudCoverage getCloudCoverage() { + return new Clouds(this.clouds); } @Override - public String toString() { - final StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Timestamp: "); - stringBuilder.append(forecastTime); - if (weatherStates != null && weatherStates.size() > 0) { - stringBuilder.append(", Weather: "); - stringBuilder.append(weatherStates.get(0).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); - } - 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(); + @JsonIgnore + public PrecipitationValues getPrecipitation() { + return this; + } + + @Override + @JsonIgnore + public SunlightStages getSunlightStages() { + return this; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/WeatherForecastDay.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/WeatherForecastDay.java new file mode 100644 index 0000000..fd65998 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/WeatherForecastDay.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021-present 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.climatic; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationValues; +import com.github.prominence.openweathermap.api.model.generic.pressure.BaseAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.DailyTemperature; +import com.github.prominence.openweathermap.api.model.generic.wind.BasicWind; + +import java.util.List; + +/** + * Contains forecast information for one day of the 30 day long climatic forecasts. + */ +public interface WeatherForecastDay extends TimeAware { + /** + * The temperature forecast. + * + * @return temps + */ + @JsonIgnore + DailyTemperature getTemperature(); + + /** + * The humidity forecast. + * + * @return humidity + */ + @JsonIgnore + Humidity getHumidity(); + + /** + * The atmospheric pressure forecast. + * + * @return pressure + */ + @JsonIgnore + BaseAtmosphericPressure getAtmosphericPressure(); + + /** + * The forecasted wind conditions. + * + * @return wind + */ + @JsonIgnore + BasicWind getWind(); + + /** + * The expected weather states. + * + * @return weather states + */ + List getWeatherStates(); + + /** + * The forecasted cloud coverage. + * + * @return clouds + */ + @JsonIgnore + CloudCoverage getCloudCoverage(); + + /** + * The forecasted precipitation. + * + * @return precipitation + */ + @JsonIgnore + PrecipitationValues getPrecipitation(); + + /** + * Information about sunlight stages. + * + * @return sunlight + */ + @JsonIgnore + SunlightStages getSunlightStages(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Wind.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Wind.java deleted file mode 100644 index 4140c7f..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/climatic/Wind.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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.climatic; - -import java.util.Objects; - -/** - * The type Wind. - */ -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 speed - * @param unit the unitSystem - * @return 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 deleted file mode 100644 index f4e8b4d..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/AtmosphericPressure.java +++ /dev/null @@ -1,98 +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.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; - - protected 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/DailyWeather.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/DailyWeather.java new file mode 100644 index 0000000..8b3e9b6 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/DailyWeather.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonIgnore; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.BaseAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.DailyTemperature; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; + +import java.util.List; + +/** + * Interface for weather forecast data used by the SixteenDaysDailyForecast. + */ +public interface DailyWeather extends TimeAware { + + /** + * The temperature data, + * + * @return temp + */ + @JsonIgnore + DailyTemperature getTemperature(); + + /** + * The humidity. + * + * @return humidity + */ + @JsonIgnore + Humidity getHumidity(); + + /** + * The atmospheric pressure. + * + * @return pressure + */ + @JsonIgnore + BaseAtmosphericPressure getAtmosphericPressure(); + + /** + * The wind conditions. + * + * @return wind + */ + @JsonIgnore + DetailedWindInfo getWind(); + + /** + * The weather states. + * + * @return weather + */ + List getWeatherStates(); + + /** + * The cloud coverage. + * + * @return louds + */ + @JsonIgnore + CloudCoverage getCloudCoverage(); + + /** + * The precipitation. + * + * @return precipitation + */ + @JsonIgnore + PrecipitationForecast getPrecipitation(); + + /** + * The sunlight stages. + * + * @return sunlight + */ + @JsonIgnore + SunlightStages getSunlightStages(); +} 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 deleted file mode 100644 index 9841732..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Forecast.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 deleted file mode 100644 index 788473f..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Location.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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; - - protected 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 getCoordinates() { - return coordinates; - } - - /** - * Sets location coordinates. - * @param coordinates location coordinates - */ - public void setCoordinates(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 deleted file mode 100644 index 3358630..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Rain.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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; - - protected Rain(double level) { - this.level = level; - } - - /** - * Creates {@link Rain} object with correctness check. - * @param level rain level value - * @return rain object. - */ - public static Rain withValue(double level) { - if (level < 0) { - throw new IllegalArgumentException("Rain level value cannot be negative."); - } - return new Rain(level); - } - - /** - * Returns rain level value. - * @return rain level value - */ - public double getLevel() { - return level; - } - - /** - * Sets rain level value with correctness check. - * @param level 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 "Rain precipitation volume, mm: " + - level + ' ' + - getUnit(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/SixteenDaysDailyForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/SixteenDaysDailyForecast.java new file mode 100644 index 0000000..6af9d07 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/SixteenDaysDailyForecast.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonIgnore; +import com.github.prominence.openweathermap.api.model.generic.location.DetailedLocationInfo; + +import java.util.List; + +/** + * Represents the daily forecast for the next sixteen days + */ +public interface SixteenDaysDailyForecast { + /** + * Information about the location. + * + * @return location + */ + @JsonIgnore + DetailedLocationInfo getLocation(); + + /** + * The daily forecasts. + * + * @return forecasts + */ + @JsonIgnore + List getWeatherForecasts(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/SixteenDaysDailyForecastModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/SixteenDaysDailyForecastModel.java new file mode 100644 index 0000000..72a506d --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/SixteenDaysDailyForecastModel.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.prominence.openweathermap.api.model.generic.location.DetailedLocationInfo; +import com.github.prominence.openweathermap.api.model.generic.location.DetailedLocationModel; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Represents information about forecast for different timestamps. + */ +@Data +@JsonIgnoreProperties(value = {"cnt"}) +public class SixteenDaysDailyForecastModel implements SixteenDaysDailyForecast { + @JsonProperty("cod") + private long cod; + @JsonProperty("message") + private BigDecimal message; + @JsonProperty("city") + private DetailedLocationModel locationModel; + @JsonProperty("list") + private List forecasts; + + @Override + @JsonIgnore + public DetailedLocationInfo getLocation() { + return locationModel; + } + + @Override + @JsonIgnore + public List getWeatherForecasts() { + return forecasts.stream().map(DailyWeather.class::cast).collect(Collectors.toList()); + } + +} 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 deleted file mode 100644 index bfa6a37..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Snow.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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; - - protected Snow(double level) { - this.level = level; - } - - /** - * Creates {@link Snow} object with correctness check. - * @param threeHourLevel snow level value - * @return snow object. - */ - public static Snow withValue(double threeHourLevel) { - if (threeHourLevel < 0) { - throw new IllegalArgumentException("Snow level value cannot be negative."); - } - return new Snow(threeHourLevel); - } - - /** - * Returns snow level value. - * @return snow level value - */ - public double getLevel() { - return level; - } - - /** - * Sets snow level value with correctness check. - * @param level 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 "Snow volume, mm: " + - 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 deleted file mode 100644 index f7027bf..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/daily/Temperature.java +++ /dev/null @@ -1,263 +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.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 index a1e0648..9e9b645 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,284 +23,178 @@ 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 com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.deserializer.PercentageZeroToOneDeserializer; +import com.github.prominence.openweathermap.api.deserializer.RequiredPercentageDeserializer; +import com.github.prominence.openweathermap.api.deserializer.WindSpeedDeserializer; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.clouds.Clouds; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.BaseAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.DailyTemperature; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureDailyBasic; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureDailyDetailed; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; +import lombok.Data; -import java.time.LocalDateTime; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; +import java.util.Optional; /** * Represents weather forecast information for a particular timestamp. */ -public class WeatherForecast { - private LocalDateTime forecastTime; - private LocalDateTime sunriseTime; - private LocalDateTime sunsetTime; +@Data +public class WeatherForecast + implements DailyWeather, DailyTemperature, BaseAtmosphericPressure, DetailedWindInfo, Humidity, PrecipitationForecast, SunlightStages { + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime forecastTime; + @JsonProperty("temp") + private TemperatureDailyDetailed temperature; + @JsonProperty("feels_like") + private TemperatureDailyBasic feelsLike; + @JsonProperty("weather") + private List weatherStates = new ArrayList<>(); + @JsonDeserialize(using = RequiredPercentageDeserializer.class) + @JsonProperty("humidity") + private int humidityPercentage; + @JsonProperty("pressure") + private BigDecimal pressure; + @JsonDeserialize(using = RequiredPercentageDeserializer.class) + @JsonProperty("clouds") + private int clouds; + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("speed") + private WindSpeed speed; + @JsonProperty("deg") + private Integer directionDegrees; + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("gust") + private WindSpeed gust; + @JsonProperty("rain") + private BigDecimal rain; + @JsonProperty("snow") + private BigDecimal snow; + @JsonDeserialize(using = PercentageZeroToOneDeserializer.class) + @JsonProperty("pop") + private Integer probabilityOfPrecipitation; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunrise") + private OffsetDateTime sunriseTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunset") + private OffsetDateTime sunsetTime; - 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 Double probabilityOfPrecipitation; - - /** - * Gets forecast time. - * - * @return the forecast time - */ - public LocalDateTime getForecastTime() { - return forecastTime; + @Override + @JsonIgnore + public DailyTemperature getTemperature() { + return this; } - /** - * Sets forecast time. - * - * @param forecastTime the forecast time - */ - public void setForecastTime(LocalDateTime forecastTime) { - this.forecastTime = forecastTime; + @Override + @JsonIgnore + public DetailedWindInfo getWind() { + return this; } - public LocalDateTime getSunriseTime() { - return sunriseTime; + @Override + @JsonIgnore + public TemperatureValue getMorning() { + return Optional.ofNullable(temperature).map(TemperatureDailyBasic::getMorning).orElse(null); } - public void setSunriseTime(LocalDateTime sunriseTime) { - this.sunriseTime = sunriseTime; + @Override + @JsonIgnore + public TemperatureValue getDay() { + return Optional.ofNullable(temperature).map(TemperatureDailyBasic::getDay).orElse(null); } - public LocalDateTime getSunsetTime() { - return sunsetTime; + @Override + @JsonIgnore + public TemperatureValue getEve() { + return Optional.ofNullable(temperature).map(TemperatureDailyBasic::getEve).orElse(null); } - public void setSunsetTime(LocalDateTime sunsetTime) { - this.sunsetTime = sunsetTime; + @Override + @JsonIgnore + public TemperatureValue getNight() { + return Optional.ofNullable(temperature).map(TemperatureDailyBasic::getNight).orElse(null); } - /** - * Gets weather state. - * - * @return the weather state - */ - public List getWeatherStates() { - return weatherStates; + @Override + @JsonIgnore + public TemperatureValue getMin() { + return Optional.ofNullable(temperature).map(TemperatureDailyDetailed::getMin).orElse(null); } - /** - * Sets weather state. - * - * @param weatherStates the weather state - */ - public void setWeatherStates(List weatherStates) { - this.weatherStates = weatherStates; + @Override + @JsonIgnore + public TemperatureValue getMax() { + return Optional.ofNullable(temperature).map(TemperatureDailyDetailed::getMax).orElse(null); } - /** - * Gets temperature. - * - * @return the temperature - */ - public Temperature getTemperature() { - return temperature; + @Override + @JsonIgnore + public TemperatureValue getMorningFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getMorning).orElse(null); } - /** - * Sets temperature. - * - * @param temperature the temperature - */ - public void setTemperature(Temperature temperature) { - this.temperature = temperature; + @Override + @JsonIgnore + public TemperatureValue getDayFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getDay).orElse(null); } - /** - * Gets atmospheric pressure. - * - * @return the atmospheric pressure - */ - public AtmosphericPressure getAtmosphericPressure() { - return atmosphericPressure; + @Override + @JsonIgnore + public TemperatureValue getEveFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getEve).orElse(null); } - /** - * Sets atmospheric pressure. - * - * @param atmosphericPressure the atmospheric pressure - */ - public void setAtmosphericPressure(AtmosphericPressure atmosphericPressure) { - this.atmosphericPressure = atmosphericPressure; + @Override + @JsonIgnore + public TemperatureValue getNightFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getNight).orElse(null); } - /** - * Gets humidity. - * - * @return the humidity - */ + @Override + @JsonIgnore 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; - } - - public Double getProbabilityOfPrecipitation() { - return probabilityOfPrecipitation; - } - - public void setProbabilityOfPrecipitation(Double probabilityOfPrecipitation) { - this.probabilityOfPrecipitation = probabilityOfPrecipitation; + return this; } @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(sunriseTime, that.sunriseTime) && - Objects.equals(sunsetTime, that.sunsetTime) && - 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(probabilityOfPrecipitation, that.probabilityOfPrecipitation); + @JsonIgnore + public BaseAtmosphericPressure getAtmosphericPressure() { + return this; } @Override - public int hashCode() { - return Objects.hash(forecastTime, sunriseTime, sunsetTime, weatherStates, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, probabilityOfPrecipitation); + @JsonIgnore + public CloudCoverage getCloudCoverage() { + return new Clouds(this.clouds); } @Override - public String toString() { - final StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Timestamp: "); - stringBuilder.append(forecastTime); - if (weatherStates != null && weatherStates.size() > 0) { - stringBuilder.append(", Weather: "); - stringBuilder.append(weatherStates.get(0).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); - } - 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(); + @JsonIgnore + public PrecipitationForecast getPrecipitation() { + return this; + } + + @Override + @JsonIgnore + public SunlightStages getSunlightStages() { + return this; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/FiveDaysThreeHoursForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/FiveDaysThreeHoursForecast.java new file mode 100644 index 0000000..90ddd7d --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/FiveDaysThreeHoursForecast.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-present 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.free; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.github.prominence.openweathermap.api.model.generic.location.DetailedLocationInfo; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; + +import java.util.List; + +/** + * Represents the 3 hours forecast for the next five days + */ +public interface FiveDaysThreeHoursForecast { + /** + * Information about the location. + * + * @return location + */ + @JsonIgnore + DetailedLocationInfo getLocation(); + + /** + * The expected sunlight stages. + * + * @return sunlight + */ + @JsonIgnore + SunlightStages getSunlightStages(); + + /** + * The 3-hourly forecasts. + * + * @return forecasts + */ + @JsonIgnore + List getWeatherForecasts(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/FiveDaysThreeHoursForecastModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/FiveDaysThreeHoursForecastModel.java new file mode 100644 index 0000000..f752bcc --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/FiveDaysThreeHoursForecastModel.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021-present 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.free; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.prominence.openweathermap.api.model.generic.location.DetailedLocationInfo; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Represents information about forecast for different timestamps. + */ +@Data +@JsonIgnoreProperties(value = {"cnt"}) +public class FiveDaysThreeHoursForecastModel implements FiveDaysThreeHoursForecast { + + @JsonProperty("cod") + private long cod; + @JsonProperty("message") + private BigDecimal message; + @JsonProperty("city") + private LocationModel locationModel; + @JsonProperty("list") + private List forecasts; + + @Override + @JsonIgnore + public DetailedLocationInfo getLocation() { + return locationModel; + } + + @Override + @JsonIgnore + public SunlightStages getSunlightStages() { + return locationModel; + } + + @Override + @JsonIgnore + public List getWeatherForecasts() { + return forecasts.stream().map(ThreeHourWeather.class::cast).collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Forecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Forecast.java deleted file mode 100644 index 3c8a120..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Forecast.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.free; - -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/free/Location.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Location.java deleted file mode 100644 index 387cb1d..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Location.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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.free; - -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 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 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 getCoordinates() { - return coordinates; - } - - /** - * Sets location coordinates. - * @param coordinates location coordinates - */ - public void setCoordinates(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(sunriseTime, location.sunriseTime) && - Objects.equals(sunsetTime, location.sunsetTime) && - 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, sunriseTime, sunsetTime, zoneOffset, coordinates, population); - } - - @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(')'); - } - 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/free/LocationModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationModel.java new file mode 100644 index 0000000..7e4703c --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationModel.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021-present 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.free; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.model.generic.location.DetailedLocationInfo; +import com.github.prominence.openweathermap.api.model.generic.location.DetailedLocationModel; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.OffsetDateTime; + +/** + * Represents location information. + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class LocationModel extends DetailedLocationModel implements DetailedLocationInfo, SunlightStages { + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunrise") + private OffsetDateTime sunriseTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunset") + private OffsetDateTime sunsetTime; + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Precipitation.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Precipitation.java new file mode 100644 index 0000000..9abd260 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Precipitation.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-present 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.free; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * Represents snow/rain information. + */ +@Data +public class Precipitation { + @JsonProperty("3h") + private BigDecimal threeHourLevel; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Rain.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Rain.java deleted file mode 100644 index d35f4d0..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Rain.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.free; - -import java.util.Objects; - -/** - * Represents rain information. - */ -public class Rain { - private static final String DEFAULT_UNIT = "mm"; - - private double threeHourLevel; - - private Rain(double threeHourLevel) { - this.threeHourLevel = threeHourLevel; - } - - /** - * 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 getThreeHourLevel() { - return threeHourLevel; - } - - /** - * Sets 3-hour rain level value with correctness check. - * @param threeHourLevel 3-hour rain level value - */ - public void setThreeHourLevel(double threeHourLevel) { - if (threeHourLevel < 0) { - throw new IllegalArgumentException("Rain level value cannot be negative."); - } - this.threeHourLevel = threeHourLevel; - } - - /** - * 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.threeHourLevel, threeHourLevel) == 0; - } - - @Override - public int hashCode() { - return Objects.hash(threeHourLevel); - } - - @Override - public String toString() { - return "3-hour rain level: " + - threeHourLevel + ' ' + - getUnit(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Snow.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Snow.java deleted file mode 100644 index 3b16fdf..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/Snow.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.free; - -import java.util.Objects; - -/** - * Represents snow information. - */ -public class Snow { - private static final String DEFAULT_UNIT = "mm"; - - private double threeHourLevel; - - private Snow(double threeHourLevel) { - this.threeHourLevel = threeHourLevel; - } - - /** - * 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 getThreeHourLevel() { - return threeHourLevel; - } - - /** - * Sets 3-hour snow level value with correctness check. - * @param threeHourLevel 3-hour snow level value - */ - public void setThreeHourLevel(double threeHourLevel) { - if (threeHourLevel < 0) { - throw new IllegalArgumentException("Snow level value cannot be negative."); - } - this.threeHourLevel = threeHourLevel; - } - - /** - * 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.threeHourLevel, threeHourLevel) == 0; - } - - @Override - public int hashCode() { - return Objects.hash(threeHourLevel); - } - - @Override - public String toString() { - return "3-hour snow level: " + - threeHourLevel + ' ' + - getUnit(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/ThreeHourWeather.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/ThreeHourWeather.java new file mode 100644 index 0000000..f1e3043 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/ThreeHourWeather.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021-present 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.free; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.github.prominence.openweathermap.api.enums.DayTime; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.DetailedAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureWithRange; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; + +import java.util.List; + +/** + * Weather forecasts for 3 hours. + */ +public interface ThreeHourWeather extends TimeAware { + /** + * The temperature forecast. + * + * @return temperature + */ + @JsonIgnore + TemperatureWithRange getTemperature(); + + /** + * The humidity forecast. + * + * @return humidity + */ + @JsonIgnore + Humidity getHumidity(); + + /** + * The atmospheric pressure forecast. + * + * @return pressure + */ + @JsonIgnore + DetailedAtmosphericPressure getAtmosphericPressure(); + + /** + * The wind forecast. + * + * @return wind + */ + @JsonIgnore + DetailedWindInfo getWind(); + + /** + * The weather states. + * + * @return states + */ + List getWeatherStates(); + + /** + * The forecasted cloud cover. + * + * @return clouds + */ + CloudCoverage getClouds(); + + /** + * The precipitation forecast. + * + * @return precipitation + */ + @JsonIgnore + PrecipitationForecast getThreeHoursPrecipitation(); + + /** + * The visibility forecast. + * + * @return visibility + */ + Visibility getVisibility(); + + /** + * The part of day. + * + * @return part of day + */ + @JsonIgnore + DayTime getPartOfDay(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecast.java index 71ca3bb..3fb0674 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecast.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecast.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,310 +22,120 @@ package com.github.prominence.openweathermap.api.model.forecast.free; -import com.github.prominence.openweathermap.api.model.*; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.deserializer.PercentageZeroToOneDeserializer; +import com.github.prominence.openweathermap.api.deserializer.VisibilityDeserializer; +import com.github.prominence.openweathermap.api.enums.DayTime; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.forecast.MetaData; +import com.github.prominence.openweathermap.api.model.generic.MainMetrics; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.clouds.Clouds; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.DetailedAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureWithRange; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; +import com.github.prominence.openweathermap.api.model.generic.wind.WindModel; +import lombok.Data; -import java.time.LocalDateTime; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; +import java.util.Optional; /** * Represents weather forecast information for a particular timestamp. */ -public class WeatherForecast { - private LocalDateTime forecastTime; +@Data +@JsonIgnoreProperties(value = {"dt_txt"}) +public class WeatherForecast implements TimeAware, ThreeHourWeather, PrecipitationForecast { - private List weatherStates; - private Temperature temperature; - private AtmosphericPressure atmosphericPressure; - private Humidity humidity; - - private Wind wind; - private Rain rain; - private Snow snow; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime forecastTime; + @JsonProperty("main") + private MainMetrics mainMetrics; + @JsonProperty("weather") + private List weatherStates = new ArrayList<>(); + @JsonProperty("clouds") private Clouds clouds; + @JsonProperty("wind") + private WindModel windModel; + @JsonProperty("rain") + private Precipitation rainModel; + @JsonProperty("snow") + private Precipitation snowModel; + @JsonDeserialize(using = VisibilityDeserializer.class) + @JsonProperty("visibility") + private Visibility visibility; + @JsonDeserialize(using = PercentageZeroToOneDeserializer.class) + @JsonProperty("pop") + private Integer probabilityOfPrecipitation; + @JsonProperty("sys") + private MetaData sysMeta; - private String forecastTimeISO; - private DayTime dayTime; - - private Double visibilityInMetres; - private Double probabilityOfPrecipitation; - - /** - * Gets forecast time. - * - * @return the forecast time - */ - public LocalDateTime getForecastTime() { - return forecastTime; + @Override + @JsonIgnore + public TemperatureWithRange getTemperature() { + return mainMetrics; } - /** - * 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 - */ + @Override + @JsonIgnore public Humidity getHumidity() { - return humidity; + return mainMetrics; } - /** - * Sets humidity. - * - * @param humidity the humidity - */ - public void setHumidity(Humidity humidity) { - this.humidity = humidity; + @Override + @JsonIgnore + public DetailedAtmosphericPressure getAtmosphericPressure() { + return mainMetrics; } - /** - * Gets wind. - * - * @return the wind - */ - public Wind getWind() { - return wind; + @Override + @JsonIgnore + public DetailedWindInfo getWind() { + return windModel; } - /** - * Sets wind. - * - * @param wind the wind - */ - public void setWind(Wind wind) { - this.wind = wind; + @Override + @JsonIgnore + public DayTime getPartOfDay() { + return Optional.ofNullable(sysMeta).map(MetaData::getPartOfDay).orElse(null); } - /** - * Gets rain. - * - * @return the rain - */ - public Rain getRain() { - return rain; + @Override + @JsonIgnore + public PrecipitationForecast getThreeHoursPrecipitation() { + return this; } - /** - * Sets rain. - * - * @param rain the rain - */ - public void setRain(Rain rain) { - this.rain = rain; + @Override + @JsonIgnore + public BigDecimal getRain() { + return Optional.ofNullable(rainModel) + .map(Precipitation::getThreeHourLevel) + .orElse(null); } - /** - * Gets snow. - * - * @return the snow - */ - public Snow getSnow() { - return snow; + @Override + @JsonIgnore + public BigDecimal getSnow() { + return Optional.ofNullable(snowModel) + .map(Precipitation::getThreeHourLevel) + .orElse(null); } - /** - * Sets snow. - * - * @param snow the snow - */ - public void setSnow(Snow snow) { - this.snow = snow; - } - - /** - * Gets clouds. - * - * @return the clouds - */ - public Clouds getClouds() { + @Override + public CloudCoverage 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 Double getVisibilityInMetres() { - return visibilityInMetres; - } - - public void setVisibilityInMetres(Double visibilityInMetres) { - this.visibilityInMetres = visibilityInMetres; - } - - 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) && - Objects.equals(visibilityInMetres, that.visibilityInMetres) && - Objects.equals(probabilityOfPrecipitation, that.probabilityOfPrecipitation) && - dayTime == that.dayTime; - } - - @Override - public int hashCode() { - return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, forecastTimeISO, visibilityInMetres, probabilityOfPrecipitation, dayTime); - } - - @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.toString()); - } - if (rain != null) { - stringBuilder.append(", Rain: "); - stringBuilder.append(rain.getThreeHourLevel()); - stringBuilder.append(' '); - stringBuilder.append(rain.getUnit()); - } - if (snow != null) { - stringBuilder.append(", Snow: "); - stringBuilder.append(snow.getThreeHourLevel()); - stringBuilder.append(' '); - stringBuilder.append(snow.getUnit()); - } - return stringBuilder.toString(); - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/FourDaysHourlyForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/FourDaysHourlyForecast.java new file mode 100644 index 0000000..491a6ca --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/FourDaysHourlyForecast.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonIgnore; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; + +import java.util.List; + +/** + * Represents the hourly forecast for the next four days + */ +public interface FourDaysHourlyForecast { + + /** + * Information about the location. + * + * @return location + */ + @JsonIgnore + BaseLocation getLocation(); + + /** + * The expected sunlight stages. + * + * @return sunlight + */ + @JsonIgnore + SunlightStages getSunlightStages(); + + /** + * The hourly forecasts. + * + * @return hours + */ + @JsonIgnore + List getWeatherForecasts(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/FourDaysHourlyForecastModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/FourDaysHourlyForecastModel.java new file mode 100644 index 0000000..aadc548 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/FourDaysHourlyForecastModel.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Represents information about forecast for different timestamps. + */ +@Data +@JsonIgnoreProperties(value = {"cnt"}) +public class FourDaysHourlyForecastModel implements FourDaysHourlyForecast { + + @JsonProperty("cod") + private long cod; + @JsonProperty("message") + private BigDecimal message; + @JsonProperty("list") + private List forecasts; + @JsonProperty("city") + private LocationModel locationModel; + + @Override + @JsonIgnore + public BaseLocation getLocation() { + return locationModel; + } + + @Override + @JsonIgnore + public SunlightStages getSunlightStages() { + return locationModel; + } + + @Override + @JsonIgnore + public List getWeatherForecasts() { + return forecasts.stream().map(HourlyWeather.class::cast).collect(Collectors.toList()); + } + +} 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 deleted file mode 100644 index 4b54e3f..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyForecast.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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/HourlyWeather.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyWeather.java new file mode 100644 index 0000000..414fb54 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyWeather.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonIgnore; +import com.github.prominence.openweathermap.api.enums.DayTime; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.DetailedAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureWithRange; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; + +import java.util.List; + +/** + * Forecast details for a single hour. + */ +public interface HourlyWeather extends TimeAware { + /** + * The temperature forecast. + * + * @return temperature + */ + @JsonIgnore + TemperatureWithRange getTemperature(); + + /** + * The humidity forecast. + * + * @return humidity + */ + @JsonIgnore + Humidity getHumidity(); + + /** + * The atmospheric pressure forecast. + * + * @return pressure + */ + @JsonIgnore + DetailedAtmosphericPressure getAtmosphericPressure(); + + /** + * The wind forecast. + * + * @return wind + */ + DetailedWindInfo getWind(); + + /** + * The weather states. + * + * @return states + */ + List getWeatherStates(); + + /** + * The forecasted cloud cover. + * + * @return clouds + */ + CloudCoverage getClouds(); + + /** + * The precipitation forecast. + * + * @return precipitation + */ + @JsonIgnore + PrecipitationForecast getHourlyPrecipitation(); + + /** + * The visibility forecast. + * + * @return visibility + */ + Visibility getVisibility(); + + /** + * The part of day. + * + * @return part of day + */ + @JsonIgnore + DayTime getPartOfDay(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyWeatherForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyWeatherForecast.java new file mode 100644 index 0000000..612767a --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/HourlyWeatherForecast.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.deserializer.PercentageZeroToOneDeserializer; +import com.github.prominence.openweathermap.api.deserializer.VisibilityDeserializer; +import com.github.prominence.openweathermap.api.enums.DayTime; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.forecast.MetaData; +import com.github.prominence.openweathermap.api.model.generic.MainMetrics; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.clouds.Clouds; +import com.github.prominence.openweathermap.api.model.generic.precipitation.BasePrecipitation; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.DetailedAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureWithRange; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; +import com.github.prominence.openweathermap.api.model.generic.wind.WindModel; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Represents weather forecast information for a particular timestamp. + */ +@Data +@JsonIgnoreProperties(value = {"dt_txt"}) +public class HourlyWeatherForecast implements TimeAware, HourlyWeather, PrecipitationForecast { + + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime forecastTime; + @JsonProperty("main") + private MainMetrics mainMetrics; + @JsonProperty("weather") + private List weatherStates = new ArrayList<>(); + @JsonProperty("clouds") + private Clouds clouds; + @JsonProperty("wind") + private WindModel windModel; + @JsonProperty("rain") + private BasePrecipitation rainModel; + @JsonProperty("snow") + private BasePrecipitation snowModel; + @JsonDeserialize(using = VisibilityDeserializer.class) + @JsonProperty("visibility") + private Visibility visibility; + @JsonDeserialize(using = PercentageZeroToOneDeserializer.class) + @JsonProperty("pop") + private Integer probabilityOfPrecipitation; + @JsonProperty("sys") + private MetaData sysMeta; + + @Override + @JsonIgnore + public TemperatureWithRange getTemperature() { + return mainMetrics; + } + + @Override + @JsonIgnore + public Humidity getHumidity() { + return mainMetrics; + } + + @Override + @JsonIgnore + public DetailedAtmosphericPressure getAtmosphericPressure() { + return mainMetrics; + } + + @Override + @JsonIgnore + public DetailedWindInfo getWind() { + return windModel; + } + + @Override + @JsonIgnore + public PrecipitationForecast getHourlyPrecipitation() { + return this; + } + + @Override + @JsonIgnore + public BigDecimal getRain() { + return Optional.ofNullable(getRainModel()).map(BasePrecipitation::getOneHourLevel).orElse(null); + } + + @Override + @JsonIgnore + public BigDecimal getSnow() { + return Optional.ofNullable(getSnowModel()).map(BasePrecipitation::getOneHourLevel).orElse(null); + } + + @Override + public CloudCoverage getClouds() { + return clouds; + } + + @Override + @JsonIgnore + public DayTime getPartOfDay() { + return Optional.ofNullable(sysMeta).map(MetaData::getPartOfDay).orElse(null); + } +} 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 deleted file mode 100644 index a13f16e..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Location.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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 getCoordinates() { - return coordinates; - } - - /** - * Sets location coordinates. - * @param coordinates location coordinates - */ - public void setCoordinates(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/LocationModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/LocationModel.java new file mode 100644 index 0000000..94dcd84 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/LocationModel.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocationModel; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.OffsetDateTime; + +/** + * Represents location information. + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class LocationModel extends BaseLocationModel implements BaseLocation, SunlightStages { + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunrise") + private OffsetDateTime sunriseTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunset") + private OffsetDateTime sunsetTime; +} 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 deleted file mode 100644 index 6482f3f..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Rain.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 deleted file mode 100644 index 4451474..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/Snow.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 deleted file mode 100644 index 95d2ea6..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/hourly/WeatherForecast.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * 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 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/generic/MainMetrics.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/MainMetrics.java new file mode 100644 index 0000000..0317b95 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/MainMetrics.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.RequiredPercentageDeserializer; +import com.github.prominence.openweathermap.api.deserializer.TemperatureValueDeserializer; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.pressure.DetailedAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureWithRange; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * Contains Temperature and AtmosphericPressure. + */ +@Data +@JsonIgnoreProperties(value = {"temp_kf"}) +public class MainMetrics implements TemperatureWithRange, Humidity, DetailedAtmosphericPressure { + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("temp") + private TemperatureValue temperature; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("temp_max") + private TemperatureValue max; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("temp_min") + private TemperatureValue min; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("feels_like") + private TemperatureValue feelsLike; + @JsonDeserialize(using = RequiredPercentageDeserializer.class) + @JsonProperty("humidity") + private int humidityPercentage; + @JsonProperty("pressure") + private BigDecimal pressure; + @JsonProperty("sea_level") + private BigDecimal seaLevel; + @JsonProperty("grnd_level") + private BigDecimal groundLevel; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/TimeAware.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/TimeAware.java new file mode 100644 index 0000000..1803aa7 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/TimeAware.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import java.time.OffsetDateTime; + +/** + * Indicates that the implementation keeps track of the forecast time. + */ +public interface TimeAware { + /** + * Returns the time when the data was calculated. + * + * @return timestamp + */ + OffsetDateTime getForecastTime(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/clouds/CloudCoverage.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/clouds/CloudCoverage.java new file mode 100644 index 0000000..1779050 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/clouds/CloudCoverage.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021-present 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.generic.clouds; + +public interface CloudCoverage { + + Integer getCoveragePercentage(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/clouds/Clouds.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/clouds/Clouds.java new file mode 100644 index 0000000..28c66ee --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/clouds/Clouds.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-present 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.generic.clouds; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * The Clouds type represents cloudiness value percentage. + * Its value can only be an integer in [0, 100] range. + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Clouds implements CloudCoverage { + @JsonProperty("all") + private Integer coveragePercentage; + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/utils/JsonDeserializationUtils.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/BaseLocation.java similarity index 60% rename from src/main/java/com/github/prominence/openweathermap/api/utils/JsonDeserializationUtils.java rename to src/main/java/com/github/prominence/openweathermap/api/model/generic/location/BaseLocation.java index 519d862..a952ea3 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/utils/JsonDeserializationUtils.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/BaseLocation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,26 +20,41 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.utils; +package com.github.prominence.openweathermap.api.model.generic.location; -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()); - } +/** + * Contains basic location information. + */ +public interface BaseLocation extends CoordinateAware { - public static ZoneId parseZoneId(JsonNode zoneIdNode) { - return ZoneId.of(zoneIdNode.asText()); - } + /** + * The time zone of the location. + * + * @return time zone + */ + ZoneOffset getTimeZone(); + + /** + * The Id of the city. + * + * @return city Id + */ + long getCityId(); + + /** + * The name of the city. + * + * @return city name + */ + String getCityName(); + + /** + * The country code of the location. + * + * @return country code + */ + String getCountryCode(); - public static ZoneOffset parseZoneOffset(JsonNode zoneOffsetNode) { - return ZoneOffset.ofTotalSeconds(zoneOffsetNode.asInt()); - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/BaseLocationModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/BaseLocationModel.java new file mode 100644 index 0000000..50a47b0 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/BaseLocationModel.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021-present 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.generic.location; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.ZoneOffsetDeserializer; +import lombok.Data; + +import java.time.ZoneOffset; + +/** + * Represents location information. + */ +@Data +public class BaseLocationModel implements BaseLocation { + @JsonProperty("id") + private long cityId; + @JsonProperty("name") + private String cityName; + @JsonProperty("coord") + private Coordinates coordinates; + @JsonProperty("country") + private String countryCode; + @JsonDeserialize(using = ZoneOffsetDeserializer.class) + @JsonProperty("timezone") + private ZoneOffset timeZone; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/CoordinateAware.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/CoordinateAware.java new file mode 100644 index 0000000..f6a9f3b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/CoordinateAware.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021-present 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.generic.location; + +/** + * Indicates that the object can provide coordinate information. + */ +public interface CoordinateAware { + + /** + * The coordinates of the data source. + * + * @return coordinated + */ + Coordinates getCoordinates(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastRainDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/Coordinates.java similarity index 52% rename from src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastRainDeserializer.java rename to src/main/java/com/github/prominence/openweathermap/api/model/generic/location/Coordinates.java index a795487..4de1b23 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastRainDeserializer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/Coordinates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,25 +20,31 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.deserializer.forecast.free; +package com.github.prominence.openweathermap.api.model.generic.location; -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.free.Rain; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; -import java.io.IOException; +/** + * Represents some location by its latitude and longitude. + */ +@Data +public class Coordinates { + @JsonProperty("lat") + private final double latitude; + @JsonProperty("lon") + private final double longitude; -public class FreeForecastRainDeserializer 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("3h"); - if (oneHourNode != null) { - return Rain.withThreeHourLevelValue(oneHourNode.asDouble()); + @JsonCreator + public Coordinates(@JsonProperty("lat") double latitude, @JsonProperty("lon") double longitude) { + if (latitude < -90 || latitude > 90) { + throw new IllegalArgumentException("Latitude value must be in the next range: [-90.0; 90.0]."); } - return null; + if (longitude < -180 || longitude > 180) { + throw new IllegalArgumentException("Longitude value must be in the next range: [-180.0; 180.0]."); + } + this.latitude = latitude; + this.longitude = longitude; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangle.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/CoordinatesRectangle.java similarity index 98% rename from src/main/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangle.java rename to src/main/java/com/github/prominence/openweathermap/api/model/generic/location/CoordinatesRectangle.java index 5e70c55..1fb055e 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangle.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/CoordinatesRectangle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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; +package com.github.prominence.openweathermap.api.model.generic.location; import java.util.Objects; diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/DetailedLocationInfo.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/DetailedLocationInfo.java new file mode 100644 index 0000000..5ae38bb --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/DetailedLocationInfo.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021-present 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.generic.location; + +/** + * Location information containing additional details about population. + */ +public interface DetailedLocationInfo extends BaseLocation { + + /** + * The number of people living at this location. + * + * @return population + */ + Long getPopulation(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/DetailedLocationModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/DetailedLocationModel.java new file mode 100644 index 0000000..5ab7296 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/DetailedLocationModel.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-present 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.generic.location; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * Represents location information. + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DetailedLocationModel extends BaseLocationModel implements DetailedLocationInfo { + @JsonProperty("population") + private Long population; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailySnowDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/MoonlightStages.java similarity index 56% rename from src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailySnowDeserializer.java rename to src/main/java/com/github/prominence/openweathermap/api/model/generic/location/MoonlightStages.java index 01e81fb..b3a5069 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/onecall/OneCallDailySnowDeserializer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/MoonlightStages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,26 +20,35 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.deserializer.onecall; +package com.github.prominence.openweathermap.api.model.generic.location; -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 com.github.prominence.openweathermap.api.model.onecall.current.MoonPhase; -import java.io.IOException; +import java.time.OffsetDateTime; -public class OneCallDailySnowDeserializer extends JsonDeserializer { - @Override - public DailySnow deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { - final JsonNode rootNode = p.getCodec().readTree(p); +/** + * Represents the information about local moonlight stages. + */ +public interface MoonlightStages { - final JsonNode valueNode = rootNode.get("snow"); - if (valueNode != null) { - return DailySnow.withValue(valueNode.asDouble()); - } - return null; - } + /** + * The time when the moon rises. + * + * @return moonrise + */ + OffsetDateTime getMoonriseTime(); + + /** + * The time when the moon sets. + * + * @return moon-set + */ + OffsetDateTime getMoonsetTime(); + + /** + * The phase the moon is in. + * + * @return moon phase + */ + MoonPhase getMoonPhase(); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/SunlightStages.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/SunlightStages.java new file mode 100644 index 0000000..15296b2 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/location/SunlightStages.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-present 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.generic.location; + +import java.time.OffsetDateTime; + +/** + * Represents the information about local sunlight stages. + */ +public interface SunlightStages { + + /** + * The time when the sun rises. + * + * @return sunrise + */ + OffsetDateTime getSunriseTime(); + + /** + * The time when the sun sets. + * + * @return sunset + */ + OffsetDateTime getSunsetTime(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/BasePrecipitation.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/BasePrecipitation.java new file mode 100644 index 0000000..7aaecef --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/BasePrecipitation.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021-present 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.generic.precipitation; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BasePrecipitation { + @JsonProperty("1h") + private BigDecimal oneHourLevel; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/Humidity.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/Humidity.java new file mode 100644 index 0000000..d40c95d --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/Humidity.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021-present 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.generic.precipitation; + +/** + * The Humidity type represents humidity value percentage. + * Its value can only be an integer in [0, 100] range. + */ +public interface Humidity { + /** + * Returns humidity percentage value. + * + * @return humidity percentage. + */ + int getHumidityPercentage(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationForecast.java new file mode 100644 index 0000000..7e312c0 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationForecast.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021-present 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.generic.precipitation; + +/** + * Expected precipitation values including the probability of precipitation. + */ +public interface PrecipitationForecast extends PrecipitationValues { + + /** + * The probability of precipitation in percentage (on 0-100 scale). + * + * @return precipitation probability. + */ + Integer getProbabilityOfPrecipitation(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationIntensity.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationIntensity.java new file mode 100644 index 0000000..efc9847 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationIntensity.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021-present 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.generic.precipitation; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NonNull; +import lombok.ToString; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +@EqualsAndHashCode +@ToString +@AllArgsConstructor +public class PrecipitationIntensity { + + private static final BigDecimal MILLIMETER_PER_HOUR_TO_MILLIMETER_PER_MINUTE_SCALE = BigDecimal.valueOf(60.0); + private static final int DECIMAL_PLACES = 1; + @NonNull + private final BigDecimal value; + + @JsonIgnore + public BigDecimal asMillimetersPerHour() { + return value.setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + + @JsonIgnore + public BigDecimal asMillimetersPerMinute() { + return value.divide(MILLIMETER_PER_HOUR_TO_MILLIMETER_PER_MINUTE_SCALE, RoundingMode.HALF_EVEN) + .setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationValues.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationValues.java new file mode 100644 index 0000000..dd39a42 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationValues.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-present 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.generic.precipitation; + +import java.math.BigDecimal; + +/** + * Precipitation data representing forecasted values. + */ +public interface PrecipitationValues { + + /** + * The amount of rain expected in mm. + * + * @return rain mm + */ + BigDecimal getRain(); + + /** + * The amount of snow expected in mm. + * + * @return snow mm + */ + BigDecimal getSnow(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/BaseAtmosphericPressure.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/BaseAtmosphericPressure.java new file mode 100644 index 0000000..eaa09f5 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/BaseAtmosphericPressure.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021-present 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.generic.pressure; + +import java.math.BigDecimal; + +/** + * Base atmospheric pressure information. + */ +public interface BaseAtmosphericPressure { + + /** + * Generic pressure value. + * + * @return pressure + */ + BigDecimal getPressure(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/DetailedAtmosphericPressure.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/DetailedAtmosphericPressure.java new file mode 100644 index 0000000..9987058 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/DetailedAtmosphericPressure.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021-present 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.generic.pressure; + +import java.math.BigDecimal; + +/** + * Atmospheric pressure details. + */ +public interface DetailedAtmosphericPressure extends BaseAtmosphericPressure, SeaLevelAtmosphericPressure { + + /** + * Value at ground level. + * + * @return pressure + */ + BigDecimal getGroundLevel(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/SeaLevelAtmosphericPressure.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/SeaLevelAtmosphericPressure.java new file mode 100644 index 0000000..72a5eb5 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/pressure/SeaLevelAtmosphericPressure.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021-present 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.generic.pressure; + +import java.math.BigDecimal; + +/** + * Atmospheric pressure at sea level. + */ +public interface SeaLevelAtmosphericPressure { + + /** + * Value at sea level. + * + * @return pressure + */ + BigDecimal getSeaLevel(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/BaseTemperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/BaseTemperature.java new file mode 100644 index 0000000..c032b56 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/BaseTemperature.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-present 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.generic.temperature; + +/** + * Basic temperature representation. + */ +public interface BaseTemperature { + + /** + * The temperature (objective). + * @return temperature + */ + TemperatureValue getTemperature(); + + /** + * The temperature (as it feels like) + * @return feels like temp + */ + TemperatureValue getFeelsLike(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/DailyTemperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/DailyTemperature.java new file mode 100644 index 0000000..daa23bd --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/DailyTemperature.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021-present 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.generic.temperature; + +/** + * The type Daily temperature. + */ +public interface DailyTemperature { + /** + * Temperature (objective) in the morning. + * + * @return temp + */ + TemperatureValue getMorning(); + + /** + * Temperature (objective) for the day. + * + * @return temp + */ + TemperatureValue getDay(); + + /** + * Temperature (objective) for the evening. + * + * @return temp + */ + TemperatureValue getEve(); + + /** + * Temperature (objective) for the night. + * + * @return temp + */ + TemperatureValue getNight(); + + /** + * Minimum temperature (objective) during the whole day. + * + * @return min temp + */ + TemperatureValue getMin(); + + /** + * Maximum temperature (objective) during the whole day. + * + * @return max temp + */ + TemperatureValue getMax(); + + /** + * Temperature (as it feels like) in the morning. + * + * @return feels like temp + */ + TemperatureValue getMorningFeelsLike(); + + /** + * Temperature (as it feels like) for the day. + * + * @return feels like temp + */ + TemperatureValue getDayFeelsLike(); + + /** + * Temperature (as it feels like) for the evening. + * + * @return feels like temp + */ + TemperatureValue getEveFeelsLike(); + + /** + * Temperature (as it feels like) for the night. + * + * @return feels like temp + */ + TemperatureValue getNightFeelsLike(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/DewPointAwareTemperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/DewPointAwareTemperature.java new file mode 100644 index 0000000..3fa945b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/DewPointAwareTemperature.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021-present 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.generic.temperature; + +/** + * Temperature interface which can tell the dew point as well. + */ +public interface DewPointAwareTemperature extends BaseTemperature { + + /** + * The dew point. + * + * @return dew point + */ + TemperatureValue getDewPoint(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureDailyBasic.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureDailyBasic.java new file mode 100644 index 0000000..6cd9416 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureDailyBasic.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-present 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.generic.temperature; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.TemperatureValueDeserializer; +import lombok.Data; + +@Data +public class TemperatureDailyBasic { + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("morn") + private TemperatureValue morning; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("day") + private TemperatureValue day; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("eve") + private TemperatureValue eve; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("night") + private TemperatureValue night; + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureDailyDetailed.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureDailyDetailed.java new file mode 100644 index 0000000..fea1b43 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureDailyDetailed.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-present 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.generic.temperature; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.TemperatureValueDeserializer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TemperatureDailyDetailed extends TemperatureDailyBasic { + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("min") + private TemperatureValue min; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("max") + private TemperatureValue max; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureValue.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureValue.java new file mode 100644 index 0000000..e128c4a --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureValue.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021-present 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.generic.temperature; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NonNull; +import lombok.ToString; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +@EqualsAndHashCode +@ToString +@AllArgsConstructor +public class TemperatureValue { + + private static final BigDecimal KELVIN_TO_CELSIUS_OFFSET = BigDecimal.valueOf(273.15); + private static final BigDecimal CELSIUS_TO_FAHRENHEIT_OFFSET = BigDecimal.valueOf(32); + private static final BigDecimal CELSIUS_TO_FAHRENHEIT_SCALE = BigDecimal.valueOf(1.8); + private static final int DECIMAL_PLACES = 0; + @NonNull + private final BigDecimal value; + + @JsonIgnore + public BigDecimal asKelvin() { + return value.setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + + @JsonIgnore + public BigDecimal asCelsius() { + return value.subtract(KELVIN_TO_CELSIUS_OFFSET) + .setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + + @JsonIgnore + public BigDecimal asFahrenheit() { + return value.subtract(KELVIN_TO_CELSIUS_OFFSET) + .multiply(CELSIUS_TO_FAHRENHEIT_SCALE).add(CELSIUS_TO_FAHRENHEIT_OFFSET) + .setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureWithRange.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureWithRange.java new file mode 100644 index 0000000..3db0522 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureWithRange.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-present 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.generic.temperature; + +/** + * Temperature interface that can tell min and max temperatures + * expected over the forecast period. + */ +public interface TemperatureWithRange extends BaseTemperature { + + /** + * Minimum temperature. + * + * @return min tmep. + */ + TemperatureValue getMax(); + + /** + * Maximum temperature. + * + * @return max temp + */ + TemperatureValue getMin(); + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/visibility/Visibility.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/visibility/Visibility.java new file mode 100644 index 0000000..277ee7d --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/visibility/Visibility.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021-present 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.generic.visibility; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NonNull; +import lombok.ToString; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +@EqualsAndHashCode +@ToString +@AllArgsConstructor +public class Visibility { + + private static final BigDecimal METER_TO_MILES_SCALE = BigDecimal.ONE.setScale(8, RoundingMode.HALF_EVEN) + .divide(BigDecimal.valueOf(1609.34d), RoundingMode.HALF_EVEN); + private static final BigDecimal METER_TO_KILOMETER_SCALE = BigDecimal.valueOf(0.001); + private static final int DECIMAL_PLACES = 2; + @NonNull + private final BigDecimal value; + + @JsonIgnore + public BigDecimal asMeters() { + return value.setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + + @JsonIgnore + public BigDecimal asMiles() { + return value.multiply(METER_TO_MILES_SCALE) + .setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + + @JsonIgnore + public BigDecimal asKilometers() { + return value.multiply(METER_TO_KILOMETER_SCALE) + .setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/BasicWind.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/BasicWind.java new file mode 100644 index 0000000..e541b26 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/BasicWind.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-present 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.generic.wind; + +/** + * Basic information about wind measurements/forecast. + */ +public interface BasicWind { + + /** + * The wind speed. + * + * @return speed + */ + WindSpeed getSpeed(); + + /** + * The wind direction in degrees. + * + * @return direction + */ + Integer getDirectionDegrees(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/DetailedWindInfo.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/DetailedWindInfo.java new file mode 100644 index 0000000..580b28c --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/DetailedWindInfo.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021-present 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.generic.wind; + +/** + * Detailed information about wind. + */ +public interface DetailedWindInfo extends BasicWind { + + /** + * Wind speed for gust. + * + * @return gust + */ + WindSpeed getGust(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/WindModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/WindModel.java new file mode 100644 index 0000000..7db3107 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/WindModel.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-present 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.generic.wind; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.WindSpeedDeserializer; +import lombok.Data; + +/** + * The type Wind. + */ +@Data +public class WindModel implements DetailedWindInfo { + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("speed") + private WindSpeed speed; + @JsonProperty("deg") + private Integer directionDegrees; + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("gust") + private WindSpeed gust; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/WindSpeed.java b/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/WindSpeed.java new file mode 100644 index 0000000..7d0af42 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/generic/wind/WindSpeed.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021-present 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.generic.wind; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NonNull; +import lombok.ToString; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * Represents wind speed data using multiple supported measurement units. + */ +@EqualsAndHashCode +@ToString +@AllArgsConstructor +public class WindSpeed { + + private static final BigDecimal METER_PER_SECOND_TO_MILES_PER_HOUR_SCALE = BigDecimal.valueOf(2.236936d); + private static final BigDecimal METER_PER_SECOND_TO_KILOMETERS_PER_HOUR_SCALE = BigDecimal.valueOf(3.6); + private static final int DECIMAL_PLACES = 2; + @NonNull + private final BigDecimal value; + + /** + * Returns the value converted to m/s. + * + * @return speed m/s + */ + @JsonIgnore + public BigDecimal asMetersPerSecond() { + return value.setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + + /** + * Returns the value converted to mph. + * + * @return speed mph + */ + @JsonIgnore + public BigDecimal asMilesPerHour() { + return value.multiply(METER_PER_SECOND_TO_MILES_PER_HOUR_SCALE) + .setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + + /** + * Returns the value converted to kph. + * + * @return speed kph + */ + @JsonIgnore + public BigDecimal asKilometersPerHour() { + return value.multiply(METER_PER_SECOND_TO_KILOMETERS_PER_HOUR_SCALE) + .setScale(DECIMAL_PLACES, RoundingMode.HALF_EVEN); + } + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/BasicPlaceModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/BasicPlaceModel.java new file mode 100644 index 0000000..55bba71 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/BasicPlaceModel.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.prominence.openweathermap.api.model.generic.location.CoordinateAware; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import lombok.Data; + +@Data +public class BasicPlaceModel implements Place, CoordinateAware { + + @JsonProperty("name") + private String name; + @JsonProperty("lat") + private double latitude; + @JsonProperty("lon") + private double longitude; + @JsonProperty("country") + private String countryCode; + + @JsonIgnore + @Override + public Coordinates getCoordinates() { + return new Coordinates(latitude, longitude); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/Geocoding.java b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/Geocoding.java new file mode 100644 index 0000000..18beb38 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/Geocoding.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.generic.location.CoordinateAware; + +import java.util.Map; + +/** + * Interface for geocoding responses. + */ +public interface Geocoding extends Place, CoordinateAware { + + /** + * Local names of the place. + * + * @return names + */ + Map getLocalNames(); + + /** + * The name of the state. + * + * @return state + */ + String getStateName(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/GeocodingModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/GeocodingModel.java new file mode 100644 index 0000000..046d85d --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/GeocodingModel.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.Map; + +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class GeocodingModel extends BasicPlaceModel implements Geocoding { + + @JsonProperty("local_names") + private Map localNames; + @JsonProperty("state") + private String stateName; + +} 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 deleted file mode 100644 index ebaa064..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/GeocodingRecord.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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/Place.java b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/Place.java new file mode 100644 index 0000000..9ec6911 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/Place.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-present 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; + +/** + * Represents a place. + */ +public interface Place { + + /** + * The name of the place. + * + * @return name + */ + String getName(); + + /** + * The country code where the place is. + * + * @return country + */ + String getCountryCode(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocoding.java b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocoding.java new file mode 100644 index 0000000..734b344 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocoding.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-present 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.generic.location.CoordinateAware; + +/** + * Zip code aware representation of a place. + */ +public interface ZipCodeGeocoding extends Place, CoordinateAware { + /** + * The zip code of the place. + * + * @return zip + */ + String getZipCode(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocodingModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocodingModel.java new file mode 100644 index 0000000..c3b3818 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocodingModel.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-present 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.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ZipCodeGeocodingModel extends BasicPlaceModel implements ZipCodeGeocoding { + + @JsonProperty("zip") + private String zipCode; +} 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 deleted file mode 100644 index a003c43..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/geocoding/ZipCodeGeocodingRecord.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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/AtmosphericPressure.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/AtmosphericPressure.java deleted file mode 100644 index b36012d..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/AtmosphericPressure.java +++ /dev/null @@ -1,98 +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 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/onecall/BaseMeasurement.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/BaseMeasurement.java new file mode 100644 index 0000000..bc8c242 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/BaseMeasurement.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021-present 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 com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.deserializer.RequiredPercentageDeserializer; +import com.github.prominence.openweathermap.api.deserializer.TemperatureValueDeserializer; +import com.github.prominence.openweathermap.api.deserializer.VisibilityDeserializer; +import com.github.prominence.openweathermap.api.deserializer.WindSpeedDeserializer; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.BasePrecipitation; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationValues; +import com.github.prominence.openweathermap.api.model.generic.pressure.SeaLevelAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.DewPointAwareTemperature; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * The current weather measurements. + */ +@Data +public class BaseMeasurement + implements TimeAware, SunlightStages, DetailedWindInfo, CloudCoverage, Humidity, + PrecipitationValues, SeaLevelAtmosphericPressure, DewPointAwareTemperature, OneCallBaseMeasurementCore { + + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime forecastTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunrise") + private OffsetDateTime sunriseTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunset") + private OffsetDateTime sunsetTime; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("temp") + private TemperatureValue temperatureMeasured; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("feels_like") + private TemperatureValue feelsLike; + @JsonProperty("pressure") + private BigDecimal seaLevel; + @JsonDeserialize(using = RequiredPercentageDeserializer.class) + @JsonProperty("humidity") + private int humidityPercentage; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("dew_point") + private TemperatureValue dewPoint; + @JsonDeserialize(using = RequiredPercentageDeserializer.class) + @JsonProperty("clouds") + private Integer coveragePercentage; + @JsonProperty("uvi") + private BigDecimal uvIndex; + @JsonDeserialize(using = VisibilityDeserializer.class) + @JsonProperty("visibility") + private Visibility visibility; + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("wind_speed") + private WindSpeed speed; + @JsonProperty("wind_deg") + private Integer directionDegrees; + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("wind_gust") + private WindSpeed gust; + @JsonProperty("rain") + private BasePrecipitation rainModel; + @JsonProperty("snow") + private BasePrecipitation snowModel; + @JsonProperty("weather") + private List weatherStates = new ArrayList<>(); + + @Override + @JsonIgnore + public DetailedWindInfo getWind() { + return this; + } + + @Override + @JsonIgnore + public SunlightStages getSunlightStages() { + return this; + } + + @Override + @JsonIgnore + public CloudCoverage getClouds() { + return this; + } + + @Override + @JsonIgnore + public Humidity getHumidity() { + return this; + } + + @Override + public BigDecimal getUvIndex() { + return uvIndex; + } + + @Override + public Visibility getVisibility() { + return visibility; + } + + @Override + public List getWeatherStates() { + return weatherStates; + } + + @Override + @JsonIgnore + public DewPointAwareTemperature getTemperatures() { + return this; + } + + @Override + @JsonIgnore + public TemperatureValue getTemperature() { + return temperatureMeasured; + } + + @Override + @JsonIgnore + public BigDecimal getRain() { + return Optional.ofNullable(rainModel).map(BasePrecipitation::getOneHourLevel).orElse(null); + } + + @Override + @JsonIgnore + public BigDecimal getSnow() { + return Optional.ofNullable(snowModel).map(BasePrecipitation::getOneHourLevel).orElse(null); + } + + @Override + @JsonIgnore + public SeaLevelAtmosphericPressure getAtmosphericPressure() { + return this; + } + +} 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 deleted file mode 100644 index 0acbec9..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Current.java +++ /dev/null @@ -1,322 +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 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; - -/** - * The type Current. - */ -public class Current { - protected LocalDateTime forecastTime; - protected LocalDateTime sunriseTime; - protected LocalDateTime sunsetTime; - - protected List weatherStates; - protected Temperature temperature; - protected AtmosphericPressure atmosphericPressure; - protected Humidity humidity; - protected Clouds clouds; - protected Double uvIndex; - protected Double visibilityInMetres; - protected Wind wind; - protected Rain rain; - protected Snow snow; - - /** - * 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 sunrise time. - * - * @return the sunrise time - */ - public LocalDateTime getSunriseTime() { - return sunriseTime; - } - - /** - * Sets sunrise time. - * - * @param sunriseTime the sunrise time - */ - public void setSunriseTime(LocalDateTime sunriseTime) { - this.sunriseTime = sunriseTime; - } - - /** - * Gets sunset time. - * - * @return the sunset time - */ - public LocalDateTime getSunsetTime() { - return sunsetTime; - } - - /** - * Sets sunset time. - * - * @param sunsetTime the sunset time - */ - public void setSunsetTime(LocalDateTime sunsetTime) { - this.sunsetTime = sunsetTime; - } - - /** - * 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 clouds. - * - * @return the clouds - */ - public Clouds getClouds() { - return clouds; - } - - /** - * Sets clouds. - * - * @param clouds the clouds - */ - public void setClouds(Clouds clouds) { - this.clouds = clouds; - } - - /** - * Gets uv index. - * - * @return the uv index - */ - public Double getUvIndex() { - return uvIndex; - } - - /** - * Sets uv index. - * - * @param uvIndex the uv index - */ - public void setUvIndex(Double uvIndex) { - if (uvIndex != null && uvIndex < 0) { - throw new IllegalArgumentException("UV index must not be negative."); - } - this.uvIndex = uvIndex; - } - - /** - * Gets visibility in metres. - * - * @return the visibility in metres - */ - public Double getVisibilityInMetres() { - return visibilityInMetres; - } - - /** - * Sets visibility in metres. - * - * @param visibilityInMetres the visibility in metres - */ - public void setVisibilityInMetres(Double visibilityInMetres) { - if (visibilityInMetres != null && visibilityInMetres < 0) { - throw new IllegalArgumentException("Visibility must not be negative."); - } - this.visibilityInMetres = visibilityInMetres; - } - - /** - * 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; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Current current = (Current) o; - return Objects.equals(forecastTime, current.forecastTime) && - Objects.equals(sunriseTime, current.sunriseTime) && - Objects.equals(sunsetTime, current.sunsetTime) && - Objects.equals(weatherStates, current.weatherStates) && - Objects.equals(temperature, current.temperature) && - Objects.equals(atmosphericPressure, current.atmosphericPressure) && - Objects.equals(humidity, current.humidity) && - Objects.equals(clouds, current.clouds) && - Objects.equals(uvIndex, current.uvIndex) && - Objects.equals(visibilityInMetres, current.visibilityInMetres) && - Objects.equals(wind, current.wind) && - Objects.equals(rain, current.rain) && - Objects.equals(snow, current.snow); - } - - @Override - public int hashCode() { - return Objects.hash(forecastTime, sunriseTime, sunsetTime, weatherStates, temperature, atmosphericPressure, humidity, clouds, uvIndex, visibilityInMetres, wind, rain, snow); - } - - @Override - public String toString() { - return "Current weather information forecasted for " + forecastTime + "."; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Measurement.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Measurement.java new file mode 100644 index 0000000..1f03ab5 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Measurement.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-present 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 com.fasterxml.jackson.annotation.JsonIgnore; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationValues; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class Measurement extends BaseMeasurement implements OneCallMeasurement { + + @Override + @JsonIgnore + public PrecipitationValues getPrecipitation() { + return this; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/OneCallBaseMeasurementCore.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/OneCallBaseMeasurementCore.java new file mode 100644 index 0000000..c16c204 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/OneCallBaseMeasurementCore.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021-present 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 com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.pressure.SeaLevelAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.DewPointAwareTemperature; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; + +import java.math.BigDecimal; +import java.util.List; + +/** + * Core behaviour of One Call API forecast classes. + */ +public interface OneCallBaseMeasurementCore extends TimeAware { + + /** + * The sunlight stages. + * + * @return sunlight + */ + SunlightStages getSunlightStages(); + + /** + * The visibility. + * @return visibility + */ + Visibility getVisibility(); + + /** + * The weather states. + * + * @return weather + */ + List getWeatherStates(); + + /** + * The temperature values. + * + * @return temperature + */ + DewPointAwareTemperature getTemperatures(); + + /** + * The wind conditions. + * + * @return wind + */ + DetailedWindInfo getWind(); + + /** + * The expected humidity. + * + * @return humidity + */ + Humidity getHumidity(); + + /** + * The cloud coverage. + * + * @return clouds + */ + CloudCoverage getClouds(); + + /** + * The UV index. + * + * @return UV + */ + BigDecimal getUvIndex(); + + /** + * The atmospheric pressure forecast. + * + * @return pressure + */ + SeaLevelAtmosphericPressure getAtmosphericPressure(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/OneCallMeasurement.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/OneCallMeasurement.java new file mode 100644 index 0000000..900f641 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/OneCallMeasurement.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-present 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 com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationValues; + +/** + * Current weather of One Call API forecast classes. + */ +public interface OneCallMeasurement extends OneCallBaseMeasurementCore { + + + /** + * The precipitation forecast. + * + * @return precipitation + */ + PrecipitationValues getPrecipitation(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Rain.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Rain.java deleted file mode 100644 index cf93537..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Rain.java +++ /dev/null @@ -1,99 +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; - -/** - * Represents rain information. - */ -public class Rain { - private static final String DEFAULT_UNIT = "mm"; - - private double oneHourLevel; - - private Rain() { - } - - /** - * Creates {@link Rain} object with correctness check. - * - * @param oneHourLevel 1-hour rain level value - * @return rain object. - */ - public static Rain withOneHourLevelValue(double oneHourLevel) { - final Rain rain = new Rain(); - rain.setOneHourLevel(oneHourLevel); - return rain; - } - - /** - * Gets one hour rain level. - * - * @return the one hour rain level - */ - public double getOneHourLevel() { - return oneHourLevel; - } - - /** - * Sets one hour rain level. - * - * @param oneHourLevel the one hour rain level - */ - public void setOneHourLevel(double oneHourLevel) { - if (oneHourLevel < 0) { - throw new IllegalArgumentException("Rain level value cannot be negative."); - } - this.oneHourLevel = oneHourLevel; - } - - /** - * Gets unit. - * - * @return the unit - */ - public String getUnit() { - return DEFAULT_UNIT; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Rain)) return false; - Rain rain = (Rain) o; - return Objects.equals(oneHourLevel, rain.oneHourLevel); - } - - @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/onecall/Snow.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Snow.java deleted file mode 100644 index 5c7d766..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Snow.java +++ /dev/null @@ -1,99 +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; - -/** - * Represents snow information. - */ -public class Snow { - private static final String DEFAULT_UNIT = "mm"; - - private double oneHourLevel; - - private Snow() { - } - - /** - * Creates {@link Snow} object with correctness check. - * - * @param oneHourLevel 1-hour snow level value - * @return snow object. - */ - public static Snow withOneHourLevelValue(double oneHourLevel) { - final Snow snow = new Snow(); - snow.setOneHourLevel(oneHourLevel); - return snow; - } - - /** - * Gets one hour snow level. - * - * @return the one hour snow level - */ - public double getOneHourLevel() { - return oneHourLevel; - } - - /** - * Sets one hour snow level. - * - * @param oneHourLevel the one hour snow level - */ - public void setOneHourLevel(double oneHourLevel) { - if (oneHourLevel < 0) { - throw new IllegalArgumentException("Snow level value cannot be negative."); - } - this.oneHourLevel = oneHourLevel; - } - - /** - * Gets unit. - * - * @return the unit - */ - public String getUnit() { - return DEFAULT_UNIT; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Snow)) return false; - Snow snow = (Snow) o; - return Objects.equals(oneHourLevel, snow.oneHourLevel); - } - - @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/onecall/Temperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Temperature.java deleted file mode 100644 index d4295fc..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/Temperature.java +++ /dev/null @@ -1,143 +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; - -/** - * Represents temperature values and unit. - */ -public class Temperature { - private double value; - private Double feelsLike; - private Double dewPoint; - private String unit; - - private Temperature() { - } - - /** - * Creates {@link Temperature} object with correctness check. - * @param value temperature value - * @param unit temperature unit - * @return temperature object - */ - public static Temperature withValue(double value, String unit) { - final Temperature temperature = new Temperature(); - temperature.setValue(value); - temperature.setUnit(unit); - return temperature; - } - - /** - * Returns temperature value. - * @return value - */ - public double getValue() { - return value; - } - - /** - * Sets temperature value. - * @param value temperature - */ - public void setValue(double value) { - this.value = value; - } - - /** - * Returns 'feels like' temperature value. - * @return 'feels like' temperature value - */ - public Double getFeelsLike() { - return feelsLike; - } - - /** - * Sets 'feels like' temperature value. - * @param feelsLike 'feels like' temperature - */ - public void setFeelsLike(Double feelsLike) { - this.feelsLike = feelsLike; - } - - public Double getDewPoint() { - return dewPoint; - } - - public void setDewPoint(Double dewPoint) { - this.dewPoint = dewPoint; - } - - /** - * Returns temperature unit. - * @return unit - */ - public String getUnit() { - return unit; - } - - /** - * Sets temperature unit with correctness check. - * @param unit temperature unit - */ - 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 Temperature)) return false; - Temperature that = (Temperature) o; - return Double.compare(that.value, value) == 0 && - Objects.equals(feelsLike, that.feelsLike) && - Objects.equals(dewPoint, that.dewPoint) && - Objects.equals(unit, that.unit); - } - - @Override - public int hashCode() { - return Objects.hash(value, feelsLike, dewPoint, unit); - } - - @Override - public String toString() { - final StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Temperature: "); - stringBuilder.append(value); - stringBuilder.append(' '); - stringBuilder.append(unit); - if (feelsLike != null) { - stringBuilder.append(", Feels like: "); - stringBuilder.append(feelsLike); - stringBuilder.append(' '); - stringBuilder.append(unit); - } - - return stringBuilder.toString(); - } -} 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 3b5aa81..a505c1a 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,165 +22,32 @@ package com.github.prominence.openweathermap.api.model.onecall.current; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import lombok.Data; + +import java.time.OffsetDateTime; import java.util.List; -import java.util.Objects; /** * The type Alert. */ +@Data public class Alert { + + @JsonProperty("sender_name") private String senderName; + @JsonProperty("event") private String eventName; - private LocalDateTime startTime; - private LocalDateTime endTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("start") + private OffsetDateTime startTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("end") + private OffsetDateTime endTime; + @JsonProperty("description") private String description; - + @JsonProperty("tags") private List tags; - - /** - * Instantiates a new Alert. - */ - public Alert() { - } - - /** - * Instantiates a new Alert. - * - * @param senderName the sender name - * @param eventName the event name - * @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, List tags) { - this.senderName = senderName; - this.eventName = eventName; - this.startTime = startTime; - this.endTime = endTime; - this.description = description; - this.tags = tags; - } - - /** - * Gets sender name. - * - * @return the sender name - */ - public String getSenderName() { - return senderName; - } - - /** - * Sets sender name. - * - * @param senderName the sender name - */ - public void setSenderName(String senderName) { - this.senderName = senderName; - } - - /** - * Gets event name. - * - * @return the event name - */ - public String getEventName() { - return eventName; - } - - /** - * Sets event name. - * - * @param eventName the event name - */ - public void setEventName(String eventName) { - this.eventName = eventName; - } - - /** - * Gets start time. - * - * @return the start time - */ - public LocalDateTime getStartTime() { - return startTime; - } - - /** - * Sets start time. - * - * @param startTime the start time - */ - public void setStartTime(LocalDateTime startTime) { - this.startTime = startTime; - } - - /** - * Gets end time. - * - * @return the end time - */ - public LocalDateTime getEndTime() { - return endTime; - } - - /** - * Sets end time. - * - * @param endTime the end time - */ - public void setEndTime(LocalDateTime endTime) { - this.endTime = endTime; - } - - /** - * Gets description. - * - * @return the description - */ - public String getDescription() { - return description; - } - - /** - * Sets description. - * - * @param description the description - */ - public void setDescription(String description) { - 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; - if (o == null || getClass() != o.getClass()) return false; - Alert alert = (Alert) o; - return Objects.equals(senderName, alert.senderName) && - Objects.equals(eventName, alert.eventName) && - Objects.equals(startTime, alert.startTime) && - Objects.equals(endTime, alert.endTime) && - Objects.equals(description, alert.description) && - Objects.equals(tags, alert.tags); - } - - @Override - public int hashCode() { - return Objects.hash(senderName, eventName, startTime, endTime, description, tags); - } - - @Override - public String toString() { - return senderName + " - " + eventName + "(" + startTime + " - " + endTime + "): " + description; - } } 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 deleted file mode 100644 index a437ca4..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/CurrentWeatherData.java +++ /dev/null @@ -1,215 +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.current; - -import com.github.prominence.openweathermap.api.model.Coordinates; -import com.github.prominence.openweathermap.api.model.onecall.Current; - -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.util.List; -import java.util.Objects; - -/** - * The type Current weather data. - */ -public class CurrentWeatherData { - private Coordinates coordinates; - private ZoneId timezone; - private ZoneOffset timezoneOffset; - - private Current current; - private List minutelyList; - private List hourlyList; - private List dailyList; - private List alerts; - - /** - * Gets coordinate. - * - * @return the coordinate - */ - public Coordinates getCoordinates() { - return coordinates; - } - - /** - * Sets coordinate. - * - * @param coordinates the coordinate - */ - public void setCoordinates(Coordinates coordinates) { - this.coordinates = coordinates; - } - - /** - * Gets timezone. - * - * @return the timezone - */ - public ZoneId getTimezone() { - return timezone; - } - - /** - * Sets timezone. - * - * @param timezone the timezone - */ - public void setTimezone(ZoneId timezone) { - this.timezone = timezone; - } - - /** - * Gets timezone offset. - * - * @return the timezone offset - */ - public ZoneOffset getTimezoneOffset() { - return timezoneOffset; - } - - /** - * Sets timezone offset. - * - * @param timezoneOffset the timezone offset - */ - public void setTimezoneOffset(ZoneOffset timezoneOffset) { - this.timezoneOffset = timezoneOffset; - } - - /** - * Gets current. - * - * @return the current - */ - public Current getCurrent() { - return current; - } - - /** - * Sets current. - * - * @param current the current - */ - public void setCurrent(Current current) { - this.current = current; - } - - /** - * Gets minutely list. - * - * @return the minutely list - */ - public List getMinutelyList() { - return minutelyList; - } - - /** - * Sets minutely list. - * - * @param minutelyList the minutely list - */ - public void setMinutelyList(List minutelyList) { - this.minutelyList = minutelyList; - } - - /** - * Gets hourly list. - * - * @return the hourly list - */ - public List getHourlyList() { - return hourlyList; - } - - /** - * Sets hourly list. - * - * @param hourlyList the hourly list - */ - public void setHourlyList(List hourlyList) { - this.hourlyList = hourlyList; - } - - /** - * Gets daily list. - * - * @return the daily list - */ - public List getDailyList() { - return dailyList; - } - - /** - * Sets daily list. - * - * @param dailyList the daily list - */ - public void setDailyList(List dailyList) { - this.dailyList = dailyList; - } - - /** - * Gets alerts. - * - * @return the alerts - */ - public List getAlerts() { - return alerts; - } - - /** - * Sets alerts. - * - * @param alerts the alerts - */ - public void setAlerts(List alerts) { - this.alerts = alerts; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CurrentWeatherData that = (CurrentWeatherData) o; - return Objects.equals(coordinates, that.coordinates) && - Objects.equals(timezone, that.timezone) && - Objects.equals(timezoneOffset, that.timezoneOffset) && - Objects.equals(current, that.current) && - Objects.equals(minutelyList, that.minutelyList) && - Objects.equals(hourlyList, that.hourlyList) && - Objects.equals(dailyList, that.dailyList) && - Objects.equals(alerts, that.alerts); - } - - @Override - public int hashCode() { - return Objects.hash(coordinates, timezone, timezoneOffset, current, minutelyList, hourlyList, dailyList, alerts); - } - - @Override - public String toString() { - 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 e0de6fc..d872211 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,418 +22,200 @@ 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.AtmosphericPressure; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.deserializer.PercentageZeroToOneDeserializer; +import com.github.prominence.openweathermap.api.deserializer.RequiredPercentageDeserializer; +import com.github.prominence.openweathermap.api.deserializer.TemperatureValueDeserializer; +import com.github.prominence.openweathermap.api.deserializer.WindSpeedDeserializer; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.MoonlightStages; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.SeaLevelAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureDailyBasic; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureDailyDetailed; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; +import lombok.Data; -import java.time.LocalDateTime; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; +import java.util.Optional; /** - * The type Daily. + * The daily weather forecast type. */ -public class Daily { - private LocalDateTime forecastTime; - private LocalDateTime sunriseTime; - private LocalDateTime sunsetTime; +@Data +public class Daily + implements TimeAware, SunlightStages, MoonlightStages, DetailedWindInfo, OneCallDailyTemperature, PrecipitationForecast, + Humidity, SeaLevelAtmosphericPressure, CloudCoverage, OneCallDailyWeather { - private LocalDateTime moonriseTime; - private LocalDateTime moonsetTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime forecastTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunrise") + private OffsetDateTime sunriseTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunset") + private OffsetDateTime sunsetTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("moonrise") + private OffsetDateTime moonriseTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("moonset") + private OffsetDateTime moonsetTime; + @JsonProperty("moon_phase") private MoonPhase moonPhase; + @JsonProperty("temp") + private TemperatureDailyDetailed temperatureMeasured; + @JsonProperty("feels_like") + private TemperatureDailyBasic feelsLike; + @JsonProperty("pressure") + private BigDecimal seaLevel; + @JsonDeserialize(using = RequiredPercentageDeserializer.class) + @JsonProperty("humidity") + private int humidityPercentage; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("dew_point") + private TemperatureValue dewPoint; + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("wind_speed") + private WindSpeed speed; + @JsonProperty("wind_deg") + private Integer directionDegrees; + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("wind_gust") + private WindSpeed gust; + @JsonDeserialize(using = RequiredPercentageDeserializer.class) + @JsonProperty("clouds") + private Integer coveragePercentage; + @JsonProperty("uvi") + private BigDecimal uvIndex; + @JsonDeserialize(using = PercentageZeroToOneDeserializer.class) + @JsonProperty("pop") + private Integer probabilityOfPrecipitation; + @JsonProperty("rain") + private BigDecimal rain; + @JsonProperty("snow") + private BigDecimal snow; + @JsonProperty("weather") + private List weatherStates = new ArrayList<>(); - private List weatherStates; - private DailyTemperature temperature; - private AtmosphericPressure atmosphericPressure; - private Humidity humidity; - private Wind wind; - private Clouds clouds; - private Double uvIndex; - private Double probabilityOfPrecipitation; - private DailyRain rain; - private DailySnow snow; - - /** - * Gets forecast time. - * - * @return the forecast time - */ - public LocalDateTime getForecastTime() { - return forecastTime; + @Override + @JsonIgnore + public TemperatureValue getMorning() { + return Optional.ofNullable(temperatureMeasured).map(TemperatureDailyDetailed::getMorning).orElse(null); } - /** - * Sets forecast time. - * - * @param forecastTime the forecast time - */ - public void setForecastTime(LocalDateTime forecastTime) { - this.forecastTime = forecastTime; + @Override + @JsonIgnore + public TemperatureValue getDay() { + return Optional.ofNullable(temperatureMeasured).map(TemperatureDailyDetailed::getDay).orElse(null); } - /** - * Gets sunrise time. - * - * @return the sunrise time - */ - public LocalDateTime getSunriseTime() { - return sunriseTime; + @Override + @JsonIgnore + public TemperatureValue getEve() { + return Optional.ofNullable(temperatureMeasured).map(TemperatureDailyDetailed::getEve).orElse(null); } - /** - * Sets sunrise time. - * - * @param sunriseTime the sunrise time - */ - public void setSunriseTime(LocalDateTime sunriseTime) { - this.sunriseTime = sunriseTime; + @Override + @JsonIgnore + public TemperatureValue getNight() { + return Optional.ofNullable(temperatureMeasured).map(TemperatureDailyDetailed::getNight).orElse(null); } - /** - * Gets sunset time. - * - * @return the sunset time - */ - public LocalDateTime getSunsetTime() { - return sunsetTime; + @Override + @JsonIgnore + public TemperatureValue getMin() { + return Optional.ofNullable(temperatureMeasured).map(TemperatureDailyDetailed::getMin).orElse(null); } - /** - * Sets sunset time. - * - * @param sunsetTime the sunset time - */ - public void setSunsetTime(LocalDateTime sunsetTime) { - this.sunsetTime = sunsetTime; + @Override + @JsonIgnore + public TemperatureValue getMax() { + return Optional.ofNullable(temperatureMeasured).map(TemperatureDailyDetailed::getMax).orElse(null); } - /** - * Gets moonrise time. - * - * @return the moonrise time - */ - public LocalDateTime getMoonriseTime() { - return moonriseTime; + @Override + @JsonIgnore + public TemperatureValue getMorningFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getMorning).orElse(null); } - /** - * Sets moonrise time. - * - * @param moonriseTime the moonrise time - */ - public void setMoonriseTime(LocalDateTime moonriseTime) { - this.moonriseTime = moonriseTime; + @Override + @JsonIgnore + public TemperatureValue getDayFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getDay).orElse(null); } - /** - * Gets moonset time. - * - * @return the moonset time - */ - public LocalDateTime getMoonsetTime() { - return moonsetTime; + @Override + @JsonIgnore + public TemperatureValue getEveFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getEve).orElse(null); } - /** - * Sets moonset time. - * - * @param moonsetTime the moonset time - */ - public void setMoonsetTime(LocalDateTime moonsetTime) { - this.moonsetTime = moonsetTime; + @Override + @JsonIgnore + public TemperatureValue getNightFeelsLike() { + return Optional.ofNullable(feelsLike).map(TemperatureDailyBasic::getNight).orElse(null); } - /** - * Gets moon phase. - * - * @return the moon phase - */ - public MoonPhase getMoonPhase() { - return moonPhase; + @Override + @JsonIgnore + public SunlightStages getSunlightStages() { + return this; } - /** - * Sets moon phase. - * - * @param moonPhase the moon phase - */ - public void setMoonPhase(MoonPhase moonPhase) { - this.moonPhase = moonPhase; + @Override + @JsonIgnore + public MoonlightStages getMoonLightStages() { + return this; } - /** - * Gets weather state. - * - * @return the weather state - */ - public List getWeatherStates() { - return weatherStates; + @Override + @JsonIgnore + public DetailedWindInfo getWind() { + return this; } - /** - * Sets weather state. - * - * @param weatherStates the weather state - */ - public void setWeatherStates(List weatherStates) { - this.weatherStates = weatherStates; + @Override + @JsonIgnore + public OneCallDailyTemperature getTemperature() { + return this; } - /** - * Gets temperature. - * - * @return the temperature - */ - public DailyTemperature getTemperature() { - return temperature; + @Override + @JsonIgnore + public PrecipitationForecast getPrecipitation() { + return this; } - /** - * Sets temperature. - * - * @param temperature the temperature - */ - public void setTemperature(DailyTemperature 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 - */ + @Override + @JsonIgnore 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 clouds. - * - * @return the clouds - */ - public Clouds getClouds() { - return clouds; - } - - /** - * Sets clouds. - * - * @param clouds the clouds - */ - public void setClouds(Clouds clouds) { - this.clouds = clouds; - } - - /** - * Gets uv index. - * - * @return the uv index - */ - public Double getUvIndex() { - return uvIndex; - } - - /** - * Sets uv index. - * - * @param uvIndex the uv index - */ - public void setUvIndex(Double uvIndex) { - if (uvIndex != null && uvIndex < 0) { - throw new IllegalArgumentException("UV index must not be negative."); - } - this.uvIndex = uvIndex; - } - - /** - * Gets probability of precipitation. - * - * @return the probability of precipitation - */ - public Double getProbabilityOfPrecipitation() { - return probabilityOfPrecipitation; - } - - /** - * Sets probability of precipitation. - * - * @param probabilityOfPrecipitation the probability of precipitation - */ - public void setProbabilityOfPrecipitation(Double probabilityOfPrecipitation) { - if (probabilityOfPrecipitation != null && (probabilityOfPrecipitation < 0 || probabilityOfPrecipitation > 100)) { - throw new IllegalArgumentException("Probability of precipitation value must be in [0, 100] range."); - } - this.probabilityOfPrecipitation = probabilityOfPrecipitation; - } - - /** - * Gets probability of precipitation percentage. - * - * @return the probability of precipitation percentage - */ - public Byte getProbabilityOfPrecipitationPercentage() { - if (probabilityOfPrecipitation != null) { - return (byte)(probabilityOfPrecipitation * 100); - } - - return null; - } - - /** - * Gets rain. - * - * @return the rain - */ - public DailyRain getRain() { - return rain; - } - - /** - * Sets rain. - * - * @param rain the rain - */ - public void setRain(DailyRain rain) { - this.rain = rain; - } - - /** - * Gets snow. - * - * @return the snow - */ - public DailySnow getSnow() { - return snow; - } - - /** - * Sets snow. - * - * @param snow the snow - */ - public void setSnow(DailySnow snow) { - this.snow = snow; + return this; } @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Daily daily = (Daily) o; - return Objects.equals(forecastTime, daily.forecastTime) && - Objects.equals(sunriseTime, daily.sunriseTime) && - Objects.equals(sunsetTime, daily.sunsetTime) && - Objects.equals(moonriseTime, daily.moonriseTime) && - Objects.equals(moonsetTime, daily.moonsetTime) && - Objects.equals(moonPhase, daily.moonPhase) && - Objects.equals(weatherStates, daily.weatherStates) && - Objects.equals(temperature, daily.temperature) && - Objects.equals(atmosphericPressure, daily.atmosphericPressure) && - Objects.equals(humidity, daily.humidity) && - Objects.equals(wind, daily.wind) && - Objects.equals(clouds, daily.clouds) && - Objects.equals(uvIndex, daily.uvIndex) && - Objects.equals(probabilityOfPrecipitation, daily.probabilityOfPrecipitation) && - Objects.equals(rain, daily.rain) && - Objects.equals(snow, daily.snow); + @JsonIgnore + public SeaLevelAtmosphericPressure getAtmosphericPressure() { + return this; } @Override - public int hashCode() { - return Objects.hash(forecastTime, sunriseTime, sunsetTime, moonriseTime, moonsetTime, moonPhase, weatherStates, temperature, atmosphericPressure, humidity, wind, clouds, uvIndex, probabilityOfPrecipitation, rain, snow); - } - - @Override - public String toString() { - final StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Weather on "); - stringBuilder.append(forecastTime); - stringBuilder.append("."); - if (weatherStates != null && weatherStates.size() > 0) { - stringBuilder.append(" Weather: "); - stringBuilder.append(weatherStates.get(0).getDescription()); - stringBuilder.append('.'); - } - if (temperature != null) { - stringBuilder.append(" Temperature(day): "); - stringBuilder.append(temperature.getDay()); - stringBuilder.append(' '); - stringBuilder.append(temperature.getUnit()); - stringBuilder.append('.'); - } - if (atmosphericPressure != null) { - stringBuilder.append(" Atmospheric pressure: "); - stringBuilder.append(atmosphericPressure.getSeaLevelValue()); - stringBuilder.append(' '); - stringBuilder.append(atmosphericPressure.getUnit()); - stringBuilder.append('.'); - } - if (clouds != null) { - stringBuilder.append(" Clouds: "); - stringBuilder.append(clouds); - stringBuilder.append('.'); - } - if (rain != null) { - stringBuilder.append(" Rain: "); - stringBuilder.append(rain.getValue()); - stringBuilder.append(' '); - stringBuilder.append(rain.getUnit()); - stringBuilder.append('.'); - } - if (snow != null) { - stringBuilder.append(". Snow: "); - stringBuilder.append(snow.getValue()); - stringBuilder.append(' '); - stringBuilder.append(snow.getUnit()); - stringBuilder.append('.'); - } - return stringBuilder.toString(); + @JsonIgnore + public CloudCoverage getClouds() { + return this; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyRain.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyRain.java deleted file mode 100644 index 936aeb5..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyRain.java +++ /dev/null @@ -1,99 +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.current; - -import java.util.Objects; - -/** - * Represents rain information. - */ -public class DailyRain { - private static final String DEFAULT_UNIT = "mm"; - - private double value; - - private DailyRain() { - } - - /** - * Creates {@link DailyRain} object with correctness check. - * - * @param value 1-hour rain level value - * @return rain object. - */ - public static DailyRain withValue(double value) { - final DailyRain rain = new DailyRain(); - rain.setValue(value); - return rain; - } - - /** - * Gets one hour rain level. - * - * @return the one hour rain level - */ - public double getValue() { - return value; - } - - /** - * Sets one hour rain level. - * - * @param value the one hour rain level - */ - public void setValue(double value) { - if (value < 0) { - throw new IllegalArgumentException("Rain level value cannot be negative."); - } - this.value = value; - } - - /** - * Gets unit. - * - * @return the unit - */ - public String getUnit() { - return DEFAULT_UNIT; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof DailyRain)) return false; - DailyRain rain = (DailyRain) o; - return Objects.equals(value, rain.value); - } - - @Override - public int hashCode() { - return Objects.hash(value); - } - - @Override - public String toString() { - return "Rain level: " + - value + - getUnit(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailySnow.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailySnow.java deleted file mode 100644 index 40cd814..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailySnow.java +++ /dev/null @@ -1,99 +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.current; - -import java.util.Objects; - -/** - * Represents snow information. - */ -public class DailySnow { - private static final String DEFAULT_UNIT = "mm"; - - private double value; - - private DailySnow() { - } - - /** - * Creates {@link DailySnow} object with correctness check. - * - * @param value 1-hour snow level value - * @return snow object. - */ - public static DailySnow withValue(double value) { - final DailySnow snow = new DailySnow(); - snow.setValue(value); - return snow; - } - - /** - * Gets one hour snow level. - * - * @return the one hour snow level - */ - public double getValue() { - return value; - } - - /** - * Sets one hour snow level. - * - * @param value the one hour snow level - */ - public void setValue(double value) { - if (value < 0) { - throw new IllegalArgumentException("Snow level value cannot be negative."); - } - this.value = value; - } - - /** - * Gets unit. - * - * @return the unit - */ - public String getUnit() { - return DEFAULT_UNIT; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof DailySnow)) return false; - DailySnow snow = (DailySnow) o; - return Objects.equals(value, snow.value); - } - - @Override - public int hashCode() { - return Objects.hash(value); - } - - @Override - public String toString() { - return "Snow level: " + - value + - getUnit(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyTemperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyTemperature.java deleted file mode 100644 index f4dc382..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyTemperature.java +++ /dev/null @@ -1,283 +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.current; - -import java.util.Objects; - -/** - * The type Daily temperature. - */ -public class DailyTemperature { - 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 Double dewPoint; - 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 dew point temperature. - * - * @return the dew point temperature - */ - public Double getDewPoint() { - return dewPoint; - } - - /** - * Sets dew point temperature. - * - * @param dewPoint the dew point temperature - */ - public void setDewPoint(Double dewPoint) { - this.dewPoint = dewPoint; - } - - /** - * 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; - DailyTemperature that = (DailyTemperature) o; - return Objects.equals(that.dewPoint, dewPoint) && - 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, dewPoint, unit); - } -} 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 e9d617b..1771266 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,295 +22,28 @@ 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.AtmosphericPressure; -import com.github.prominence.openweathermap.api.model.onecall.Rain; -import com.github.prominence.openweathermap.api.model.onecall.Snow; -import com.github.prominence.openweathermap.api.model.onecall.Temperature; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.PercentageZeroToOneDeserializer; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.onecall.BaseMeasurement; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Objects; +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class Hourly extends BaseMeasurement implements OneCallHourlyWeather, PrecipitationForecast { -/** - * The type Hourly. - */ -public class Hourly { - private LocalDateTime forecastTime; - - private List weatherStates; - private Temperature temperature; - private AtmosphericPressure atmosphericPressure; - private Humidity humidity; - private Double uvIndex; - private Clouds clouds; - private Double visibilityInMetres; - private Wind wind; - private Double probabilityOfPrecipitation; - private Rain rain; - private Snow snow; - - /** - * 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 uv index. - * - * @return the uv index - */ - public Double getUvIndex() { - return uvIndex; - } - - /** - * Sets uv index. - * - * @param uvIndex the uv index - */ - public void setUvIndex(Double uvIndex) { - this.uvIndex = uvIndex; - } - - /** - * 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 visibility in metres. - * - * @return the visibility in metres - */ - public Double getVisibilityInMetres() { - return visibilityInMetres; - } - - /** - * Sets visibility in metres. - * - * @param visibilityInMetres the visibility in metres - */ - public void setVisibilityInMetres(Double visibilityInMetres) { - this.visibilityInMetres = visibilityInMetres; - } - - /** - * 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 probability of precipitation. - * - * @return the probability of precipitation - */ - public Double getProbabilityOfPrecipitation() { - return probabilityOfPrecipitation; - } - - /** - * Sets probability of precipitation. - * - * @param probabilityOfPrecipitation the probability of precipitation - */ - public void setProbabilityOfPrecipitation(Double probabilityOfPrecipitation) { - if (probabilityOfPrecipitation != null && (probabilityOfPrecipitation < 0 || probabilityOfPrecipitation > 100)) { - throw new IllegalArgumentException("Probability of precipitation value must be in [0, 100] range."); - } - this.probabilityOfPrecipitation = probabilityOfPrecipitation; - } - - /** - * Gets probability of precipitation percentage. - * - * @return the probability of precipitation percentage - */ - public Byte getProbabilityOfPrecipitationPercentage() { - if (probabilityOfPrecipitation != null) { - return (byte)(probabilityOfPrecipitation * 100); - } - - return null; - } - - /** - * 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; - } + @JsonDeserialize(using = PercentageZeroToOneDeserializer.class) + @JsonProperty("pop") + private Integer probabilityOfPrecipitation; @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Hourly hourly = (Hourly) o; - return Objects.equals(forecastTime, hourly.forecastTime) && - Objects.equals(weatherStates, hourly.weatherStates) && - Objects.equals(temperature, hourly.temperature) && - Objects.equals(atmosphericPressure, hourly.atmosphericPressure) && - Objects.equals(humidity, hourly.humidity) && - Objects.equals(uvIndex, hourly.uvIndex) && - Objects.equals(clouds, hourly.clouds) && - Objects.equals(visibilityInMetres, hourly.visibilityInMetres) && - Objects.equals(wind, hourly.wind) && - Objects.equals(probabilityOfPrecipitation, hourly.probabilityOfPrecipitation) && - Objects.equals(rain, hourly.rain) && - Objects.equals(snow, hourly.snow); - } - - @Override - public int hashCode() { - return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, uvIndex, clouds, visibilityInMetres, wind, probabilityOfPrecipitation, rain, snow); - } - - @Override - public String toString() { - return "Hourly weather information forecasted for " + forecastTime + "."; + @JsonIgnore + public PrecipitationForecast getPrecipitation() { + return this; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Minutely.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Minutely.java index 9e87dfc..b0766ca 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Minutely.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/Minutely.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,79 +22,22 @@ package com.github.prominence.openweathermap.api.model.onecall.current; -import java.time.LocalDateTime; -import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.OffsetDateTime; /** - * The type Minutely. + * The type for minutely forecasts. */ -public class Minutely { - private LocalDateTime forecastTime; - private double precipitationVolume; - - private Minutely() { - } - - /** - * With value minutely. - * - * @param forecastTime the forecast time - * @param precipitationVolume the precipitation volume - * @return the minutely - */ - public static Minutely withValue(LocalDateTime forecastTime, double precipitationVolume) { - final Minutely minutely = new Minutely(); - minutely.setForecastTime(forecastTime); - minutely.setPrecipitationVolume(precipitationVolume); - - return minutely; - } - - /** - * Gets forecast time. - * - * @return the forecast time - */ - public LocalDateTime getForecastTime() { - return forecastTime; - } - - private void setForecastTime(LocalDateTime forecastTime) { - Objects.requireNonNull(forecastTime); - this.forecastTime = forecastTime; - } - - /** - * Gets precipitation volume. - * - * @return the precipitation volume - */ - public double getPrecipitationVolume() { - return precipitationVolume; - } - - private void setPrecipitationVolume(double precipitationVolume) { - if (precipitationVolume < 0) { - throw new IllegalArgumentException("Precipitation volume cannot be negative."); - } - this.precipitationVolume = precipitationVolume; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Minutely minutely = (Minutely) o; - return Double.compare(minutely.precipitationVolume, precipitationVolume) == 0 && Objects.equals(forecastTime, minutely.forecastTime); - } - - @Override - public int hashCode() { - return Objects.hash(forecastTime, precipitationVolume); - } - - @Override - public String toString() { - return "Time: " + forecastTime + ", precipitation volume: " + precipitationVolume; - } +@Data +public class Minutely implements OneCallMinutelyWeather { + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime forecastTime; + @JsonProperty("precipitation") + private BigDecimal precipitationVolume; } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/MoonPhase.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/MoonPhase.java index 62a277f..0634ee3 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/MoonPhase.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/MoonPhase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,42 +22,31 @@ package com.github.prominence.openweathermap.api.model.onecall.current; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.github.prominence.openweathermap.api.enums.MoonType; +import lombok.EqualsAndHashCode; +import lombok.ToString; -import java.util.Objects; - +@EqualsAndHashCode +@ToString public class MoonPhase { private final double value; private final MoonType type; + @JsonCreator public MoonPhase(Double value) { this.value = value; this.type = MoonType.valueOf(value); } + @JsonIgnore public Double getValue() { return value; } + @JsonIgnore public MoonType getType() { return type; } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MoonPhase moonPhase = (MoonPhase) o; - return Double.compare(moonPhase.value, value) == 0 && type == moonPhase.type; - } - - @Override - public int hashCode() { - return Objects.hash(value, type); - } - - @Override - public String toString() { - return type.name() + "(" + value + ")"; - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallCurrentForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallCurrentForecast.java new file mode 100644 index 0000000..46a30be --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallCurrentForecast.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021-present 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.current; + +import com.github.prominence.openweathermap.api.model.generic.location.CoordinateAware; +import com.github.prominence.openweathermap.api.model.onecall.OneCallMeasurement; + +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.List; + +/** + * Represents forecasts returned by the current weather more of the One Call API. + */ +public interface OneCallCurrentForecast extends CoordinateAware { + + /** + * The time zone of the location. + * + * @return time zone + */ + ZoneId getTimezone(); + + /** + * The time zone offset of the location. + * + * @return zone offset + */ + ZoneOffset getTimezoneOffset(); + + /** + * The current weather. + * + * @return current + */ + OneCallMeasurement getCurrentWeather(); + + /** + * The minutely forecast. + * + * @return minutely + */ + List getMinutelyForecast(); + + /** + * The hourly forecast. + * + * @return hourly + */ + List getHourlyForecast(); + + /** + * The daily forecast. + * + * @return daily + */ + List getDailyForecast(); + + + /** + * The weather alerts. + * + * @return alerts + */ + List getAlerts(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallCurrentForecastModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallCurrentForecastModel.java new file mode 100644 index 0000000..1fded73 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallCurrentForecastModel.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2021-present 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.current; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.ZoneIdDeserializer; +import com.github.prominence.openweathermap.api.deserializer.ZoneOffsetDeserializer; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.onecall.Measurement; +import com.github.prominence.openweathermap.api.model.onecall.OneCallMeasurement; +import lombok.Data; + +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * The type Current weather data. + */ +@Data +public class OneCallCurrentForecastModel implements OneCallCurrentForecast { + @JsonProperty("lat") + private double latitude; + @JsonProperty("lon") + private double longitude; + @JsonDeserialize(using = ZoneIdDeserializer.class) + @JsonProperty("timezone") + private ZoneId timezone; + @JsonDeserialize(using = ZoneOffsetDeserializer.class) + @JsonProperty("timezone_offset") + private ZoneOffset timezoneOffset; + @JsonProperty("current") + private Measurement current; + @JsonProperty("minutely") + private List minutelyList; + @JsonProperty("hourly") + private List hourlyList; + @JsonProperty("daily") + private List dailyList; + @JsonProperty("alerts") + private List alerts; + + @Override + @JsonIgnore + public Coordinates getCoordinates() { + return new Coordinates(latitude, longitude); + } + + @Override + @JsonIgnore + public OneCallMeasurement getCurrentWeather() { + return current; + } + + @Override + @JsonIgnore + public List getMinutelyForecast() { + return Optional.ofNullable(minutelyList) + .map(List::stream) + .map(s -> s.map(OneCallMinutelyWeather.class::cast).collect(Collectors.toList())) + .orElse(Collections.emptyList()); + } + + @Override + @JsonIgnore + public List getHourlyForecast() { + return Optional.ofNullable(hourlyList) + .map(List::stream) + .map(s -> s.map(OneCallHourlyWeather.class::cast).collect(Collectors.toList())) + .orElse(Collections.emptyList()); + } + + @Override + @JsonIgnore + public List getDailyForecast() { + return Optional.ofNullable(dailyList) + .map(List::stream) + .map(s -> s.map(OneCallDailyWeather.class::cast).collect(Collectors.toList())) + .orElse(Collections.emptyList()); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallDailyTemperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallDailyTemperature.java new file mode 100644 index 0000000..93a2796 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallDailyTemperature.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021-present 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.current; + +import com.github.prominence.openweathermap.api.model.generic.temperature.DailyTemperature; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; + +/** + * Extended temperature information including dew point. + */ +public interface OneCallDailyTemperature extends DailyTemperature { + /** + * The dew point. + * + * @return dew point + */ + TemperatureValue getDewPoint(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallDailyWeather.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallDailyWeather.java new file mode 100644 index 0000000..902e7cd --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallDailyWeather.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021-present 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.current; + +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.MoonlightStages; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.SeaLevelAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; + +import java.math.BigDecimal; +import java.util.List; + +/** + * Represents daily weather forecast returned by the OneCall API. + */ +public interface OneCallDailyWeather extends TimeAware { + + /** + * The sunlight stages. + * + * @return sunlight + */ + SunlightStages getSunlightStages(); + + /** + * The moonlight stages. + * + * @return moonlight + */ + MoonlightStages getMoonLightStages(); + + /** + * The wind conditions. + * + * @return wind + */ + DetailedWindInfo getWind(); + + /** + * The weather states. + * + * @return weather + */ + List getWeatherStates(); + + /** + * The temperature forecast. + * + * @return temperature + */ + OneCallDailyTemperature getTemperature(); + + /** + * The precipitation forecast. + * + * @return precipitation + */ + PrecipitationForecast getPrecipitation(); + + /** + * The expected humidity. + * + * @return humidity + */ + Humidity getHumidity(); + + /** + * The cloud coverage. + * + * @return clouds + */ + CloudCoverage getClouds(); + + /** + * The UV index. + * + * @return UV + */ + BigDecimal getUvIndex(); + + /** + * The atmospheric pressure forecast. + * + * @return pressure + */ + SeaLevelAtmosphericPressure getAtmosphericPressure(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallHourlyWeather.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallHourlyWeather.java new file mode 100644 index 0000000..2ab5223 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallHourlyWeather.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-present 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.current; + +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.onecall.OneCallBaseMeasurementCore; + +/** + * Hourly forecast representation of One Call API. + */ +public interface OneCallHourlyWeather extends OneCallBaseMeasurementCore { + + /** + * The precipitation forecast. + * + * @return precipitation + */ + PrecipitationForecast getPrecipitation(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallMinutelyWeather.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallMinutelyWeather.java new file mode 100644 index 0000000..e9963c6 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/current/OneCallMinutelyWeather.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-present 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.current; + +import com.github.prominence.openweathermap.api.model.generic.TimeAware; + +import java.math.BigDecimal; + +/** + * Minutely forecast representation for One Call API. + */ +public interface OneCallMinutelyWeather extends TimeAware { + /** + * The expected volume of precipitation. + * + * @return precipitation + */ + BigDecimal getPrecipitationVolume(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeather.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeather.java index caab8a4..5eace10 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeather.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeather.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,14 +22,57 @@ package com.github.prominence.openweathermap.api.model.onecall.historical; -import com.github.prominence.openweathermap.api.model.onecall.Current; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.ZoneIdDeserializer; +import com.github.prominence.openweathermap.api.deserializer.ZoneOffsetDeserializer; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.onecall.Measurement; +import com.github.prominence.openweathermap.api.model.onecall.OneCallMeasurement; +import lombok.Data; + +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; /** - * The type Historical weather. + * The type Current weather data. */ -public class HistoricalWeather extends Current { +@Data +public class HistoricalWeather implements OneCallHistoricalWeather { + @JsonProperty("lat") + private double latitude; + @JsonProperty("lon") + private double longitude; + @JsonDeserialize(using = ZoneIdDeserializer.class) + @JsonProperty("timezone") + private ZoneId timezone; + @JsonDeserialize(using = ZoneOffsetDeserializer.class) + @JsonProperty("timezone_offset") + private ZoneOffset timezoneOffset; + @JsonProperty("data") + private List data; + + /** + * Gets coordinate. + * + * @return the coordinate + */ + @JsonIgnore + public Coordinates getCoordinates() { + return new Coordinates(latitude, longitude); + } + @Override - public String toString() { - return "Historical weather information forecasted for " + forecastTime + "."; + @JsonIgnore + public List getDataPoints() { + return Optional.ofNullable(data) + .map(List::stream) + .map(s -> s.map(OneCallMeasurement.class::cast).collect(Collectors.toList())) + .orElse(Collections.emptyList()); } } 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 deleted file mode 100644 index f89c8eb..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HistoricalWeatherData.java +++ /dev/null @@ -1,154 +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.historical; - -import com.github.prominence.openweathermap.api.model.Coordinates; - -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.util.List; -import java.util.Objects; - -/** - * The type Historical weather data. - */ -public class HistoricalWeatherData { - private Coordinates coordinates; - private ZoneId timezone; - private ZoneOffset timezoneOffset; - - private HistoricalWeather historicalWeather; - private List hourlyList; - - /** - * Gets coordinate. - * - * @return the coordinate - */ - public Coordinates getCoordinates() { - return coordinates; - } - - /** - * Sets coordinate. - * - * @param coordinates the coordinate - */ - public void setCoordinates(Coordinates coordinates) { - this.coordinates = coordinates; - } - - /** - * Gets timezone. - * - * @return the timezone - */ - public ZoneId getTimezone() { - return timezone; - } - - /** - * Sets timezone. - * - * @param timezone the timezone - */ - public void setTimezone(ZoneId timezone) { - this.timezone = timezone; - } - - /** - * Gets timezone offset. - * - * @return the timezone offset - */ - public ZoneOffset getTimezoneOffset() { - return timezoneOffset; - } - - /** - * Sets timezone offset. - * - * @param timezoneOffset the timezone offset - */ - public void setTimezoneOffset(ZoneOffset timezoneOffset) { - this.timezoneOffset = timezoneOffset; - } - - /** - * Gets historical weather. - * - * @return the historical weather - */ - public HistoricalWeather getHistoricalWeather() { - return historicalWeather; - } - - /** - * Sets historical weather. - * - * @param historicalWeather the historical weather - */ - public void setHistoricalWeather(HistoricalWeather historicalWeather) { - this.historicalWeather = historicalWeather; - } - - /** - * Gets hourly list. - * - * @return the hourly list - */ - public List getHourlyList() { - return hourlyList; - } - - /** - * Sets hourly list. - * - * @param hourlyList the hourly list - */ - public void setHourlyList(List hourlyList) { - this.hourlyList = hourlyList; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - HistoricalWeatherData that = (HistoricalWeatherData) o; - return Objects.equals(coordinates, that.coordinates) && - Objects.equals(timezone, that.timezone) && - Objects.equals(timezoneOffset, that.timezoneOffset) && - Objects.equals(historicalWeather, that.historicalWeather) && - Objects.equals(hourlyList, that.hourlyList); - } - - @Override - public int hashCode() { - return Objects.hash(coordinates, timezone, timezoneOffset, historicalWeather, hourlyList); - } - - @Override - public String toString() { - 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 deleted file mode 100644 index d62c7f8..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistorical.java +++ /dev/null @@ -1,260 +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.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.AtmosphericPressure; -import com.github.prominence.openweathermap.api.model.onecall.Rain; -import com.github.prominence.openweathermap.api.model.onecall.Snow; -import com.github.prominence.openweathermap.api.model.onecall.Temperature; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Objects; - -/** - * The type Hourly historical. - */ -public class HourlyHistorical { - private LocalDateTime forecastTime; - - private List weatherStates; - private Temperature temperature; - private AtmosphericPressure atmosphericPressure; - private Humidity humidity; - private Clouds clouds; - private Double visibilityInMetres; - private Wind wind; - private Rain rain; - private Snow snow; - - /** - * 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 clouds. - * - * @return the clouds - */ - public Clouds getClouds() { - return clouds; - } - - /** - * Sets clouds. - * - * @param clouds the clouds - */ - public void setClouds(Clouds clouds) { - this.clouds = clouds; - } - - /** - * Gets visibility in metres. - * - * @return the visibility in metres - */ - public Double getVisibilityInMetres() { - return visibilityInMetres; - } - - /** - * Sets visibility in metres. - * - * @param visibilityInMetres the visibility in metres - */ - public void setVisibilityInMetres(Double visibilityInMetres) { - this.visibilityInMetres = visibilityInMetres; - } - - /** - * 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; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - HourlyHistorical that = (HourlyHistorical) 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(clouds, that.clouds) && - Objects.equals(visibilityInMetres, that.visibilityInMetres) && - Objects.equals(wind, that.wind) && - Objects.equals(rain, that.rain) && - Objects.equals(snow, that.snow); - } - - @Override - public int hashCode() { - return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, clouds, visibilityInMetres, wind, rain, snow); - } - - @Override - public String toString() { - return "Historical hourly information forecasted for " + forecastTime + "."; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/OneCallHistoricalWeather.java b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/OneCallHistoricalWeather.java new file mode 100644 index 0000000..e24a8ff --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/onecall/historical/OneCallHistoricalWeather.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-present 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.historical; + +import com.github.prominence.openweathermap.api.model.generic.location.CoordinateAware; +import com.github.prominence.openweathermap.api.model.onecall.OneCallMeasurement; + +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.List; + +/** + * Represents historical weather results returned by One Call API. + */ +public interface OneCallHistoricalWeather extends CoordinateAware { + + /** + * The time zone of the location. + * + * @return time zone + */ + ZoneId getTimezone(); + + /** + * The time zone offset of the location. + * + * @return zone offset + */ + ZoneOffset getTimezoneOffset(); + + /** + * The data points returned. + * + * @return data + */ + List getDataPoints(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiation.java b/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiation.java index c5b907f..48f4c28 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiation.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiation.java @@ -1,48 +1,40 @@ +/* + * Copyright (c) 2021-present 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.radiation; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.CoordinateAware; import java.util.List; -import java.util.Objects; -public class SolarRadiation { - private Coordinates coordinates; - List solarRadiationRecords; +/** + * Represents the solar radiation response. + */ +public interface SolarRadiation extends CoordinateAware { - public Coordinates getCoordinates() { - return coordinates; - } - - public void setCoordinates(Coordinates coordinates) { - this.coordinates = coordinates; - } - - public List getSolarRadiationRecords() { - return solarRadiationRecords; - } - - public void setSolarRadiationRecords(List solarRadiationRecords) { - this.solarRadiationRecords = solarRadiationRecords; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - SolarRadiation that = (SolarRadiation) o; - return Objects.equals(coordinates, that.coordinates) && Objects.equals(solarRadiationRecords, that.solarRadiationRecords); - } - - @Override - public int hashCode() { - return Objects.hash(coordinates, solarRadiationRecords); - } - - @Override - public String toString() { - return "SolarRadiation{" + - "coordinates=" + coordinates + - ", solarRadiationRecords=" + solarRadiationRecords + - '}'; - } + /** + * The solar radiation records. + * + * @return radiation + */ + List getSolarRadiationRecords(); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationEntry.java b/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationEntry.java new file mode 100644 index 0000000..67fd85c --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationEntry.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-present 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.radiation; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import lombok.Data; + +import java.time.OffsetDateTime; + +@Data +public class SolarRadiationEntry { + + @JsonProperty("radiation") + private SolarRadiationMeasurement solarRadiationMeasurement; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime measurementTime; + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationMeasurement.java b/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationMeasurement.java new file mode 100644 index 0000000..a5faf90 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationMeasurement.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-present 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.radiation; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class SolarRadiationMeasurement { + + @JsonProperty("ghi") + private Double globalHorizontalIrradiance; + @JsonProperty("dni") + private Double directNormalIrradiance; + @JsonProperty("dhi") + private Double diffuseHorizontalIrradiance; + @JsonProperty("ghi_cs") + private Double globalHorizontalIrradianceClearSky; + @JsonProperty("dni_cs") + private Double directNormalIrradianceClearSky; + @JsonProperty("dhi_cs") + private Double diffuseHorizontalIrradianceClearSky; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationModel.java new file mode 100644 index 0000000..50de9cc --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationModel.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-present 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.radiation; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import lombok.Data; + +import java.util.List; + +@Data +public class SolarRadiationModel implements SolarRadiation { + + @JsonProperty("coord") + private Coordinates coordinates; + @JsonProperty("list") + private List solarRadiationRecords; + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationRecord.java b/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationRecord.java deleted file mode 100644 index dd6c71a..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/radiation/SolarRadiationRecord.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.github.prominence.openweathermap.api.model.radiation; - -import java.time.LocalDateTime; -import java.util.Objects; - -public class SolarRadiationRecord { - private LocalDateTime measurementTime; - - private Double ghi; - private Double dni; - private Double dhi; - - private Double ghi_cs; - private Double dni_cs; - private Double dhi_cs; - - public LocalDateTime getMeasurementTime() { - return measurementTime; - } - - public void setMeasurementTime(LocalDateTime measurementTime) { - this.measurementTime = measurementTime; - } - - public Double getCloudSkyGlobalHorizontalIrradiance() { - return ghi; - } - - public void setCloudSkyGlobalHorizontalIrradiance(Double ghi) { - this.ghi = ghi; - } - - public Double getCloudSkyDirectNormalIrradiance() { - return dni; - } - - public void setCloudSkyDirectNormalIrradiance(Double dni) { - this.dni = dni; - } - - public Double getCloudSkyDiffuseHorizontalIrradiance() { - return dhi; - } - - public void setCloudSkyDiffuseHorizontalIrradiance(Double dhi) { - this.dhi = dhi; - } - - public Double getClearSkyGlobalHorizontalIrradiance() { - return ghi_cs; - } - - public void setClearSkyGlobalHorizontalIrradiance(Double ghi_cs) { - this.ghi_cs = ghi_cs; - } - - public Double getClearSkyDirectNormalIrradiance() { - return dni_cs; - } - - public void setClearSkyDirectNormalIrradiance(Double dni_cs) { - this.dni_cs = dni_cs; - } - - public Double getClearSkyDiffuseHorizontalIrradiance() { - return dhi_cs; - } - - public void setClearSkyDiffuseHorizontalIrradiance(Double dhi_cs) { - this.dhi_cs = dhi_cs; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - SolarRadiationRecord that = (SolarRadiationRecord) o; - return Objects.equals(measurementTime, that.measurementTime) && Objects.equals(ghi, that.ghi) && Objects.equals(dni, that.dni) && Objects.equals(dhi, that.dhi) && Objects.equals(ghi_cs, that.ghi_cs) && Objects.equals(dni_cs, that.dni_cs) && Objects.equals(dhi_cs, that.dhi_cs); - } - - @Override - public int hashCode() { - return Objects.hash(measurementTime, ghi, dni, dhi, ghi_cs, dni_cs, dhi_cs); - } - - @Override - public String toString() { - return "SolarRadiationRecord{" + - "measurementTime=" + measurementTime + - ", ghi=" + ghi + - ", dni=" + dni + - ", dhi=" + dhi + - ", ghi_cs=" + ghi_cs + - ", dni_cs=" + dni_cs + - ", dhi_cs=" + dhi_cs + - '}'; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Alert.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Alert.java index 056fd37..4d2c471 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Alert.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Alert.java @@ -1,57 +1,37 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; +import com.fasterxml.jackson.annotation.JsonProperty; import com.github.prominence.openweathermap.api.enums.EventLevel; +import lombok.Data; -import java.util.Objects; - +@Data public class Alert { + @JsonProperty("sender_name") private String senderName; + @JsonProperty("event") private String event; + @JsonProperty("event_level") private EventLevel eventLevel; - - public String getSenderName() { - return senderName; - } - - public void setSenderName(String senderName) { - this.senderName = senderName; - } - - public String getEvent() { - return event; - } - - public void setEvent(String event) { - this.event = event; - } - - public EventLevel getEventLevel() { - return eventLevel; - } - - public void setEventLevel(EventLevel eventLevel) { - this.eventLevel = eventLevel; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Alert alert = (Alert) o; - return Objects.equals(senderName, alert.senderName) && Objects.equals(event, alert.event) && eventLevel == alert.eventLevel; - } - - @Override - public int hashCode() { - return Objects.hash(senderName, event, eventLevel); - } - - @Override - public String toString() { - return "Alert{" + - "senderName='" + senderName + '\'' + - ", event='" + event + '\'' + - ", eventLevel=" + eventLevel + - '}'; - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadDetails.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadDetails.java index 8b6618b..40b8f9a 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadDetails.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadDetails.java @@ -1,47 +1,39 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.TemperatureValueDeserializer; import com.github.prominence.openweathermap.api.enums.RoadState; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import lombok.Data; -import java.util.Objects; - +@Data public class RoadDetails { + @JsonProperty("state") private RoadState roadState; - private Double surfaceTemperature; - - public RoadState getRoadState() { - return roadState; - } - - public void setRoadState(RoadState roadState) { - this.roadState = roadState; - } - - public Double getSurfaceTemperature() { - return surfaceTemperature; - } - - public void setSurfaceTemperature(Double surfaceTemperature) { - this.surfaceTemperature = surfaceTemperature; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RoadDetails that = (RoadDetails) o; - return roadState == that.roadState && Objects.equals(surfaceTemperature, that.surfaceTemperature); - } - - @Override - public int hashCode() { - return Objects.hash(roadState, surfaceTemperature); - } - - @Override - public String toString() { - return "RoadDetails{" + - "roadState=" + roadState + - ", surfaceTemperature=" + surfaceTemperature + - '}'; - } + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("temp") + private TemperatureValue surfaceTemperature; } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRisk.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRisk.java new file mode 100644 index 0000000..6849813 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRisk.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; + +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.location.CoordinateAware; + +import java.util.List; + +/** + * Represents information about road risks. + */ +public interface RoadRisk extends CoordinateAware, TimeAware { + + /** + * The weather data returned. + * + * @return weather + */ + WeatherModel getWeather(); + + /** + * The road details (only in case of U.S.). + * + * @return details + */ + RoadDetails getRoadDetails(); + + /** + * Any alerts which are in effect related to the query. + * + * @return alert collection + */ + List getAlerts(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskModel.java new file mode 100644 index 0000000..c01246e --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskModel.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import lombok.Data; + +import java.time.OffsetDateTime; +import java.util.List; +import java.util.Optional; + +@Data +public class RoadRiskModel implements RoadRisk { + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime forecastTime; + @JsonProperty("coord") + private List coord; + @JsonProperty("weather") + private WeatherModel weather; + @JsonProperty("road") + private RoadDetails roadDetails; + @JsonProperty("alerts") + private List alerts; + + @JsonIgnore + @Override + public Coordinates getCoordinates() { + return Optional.ofNullable(coord) + .map(c -> new Coordinates(c.get(0), c.get(1))) + .orElse(null); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskRecord.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskRecord.java deleted file mode 100644 index c94a11b..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskRecord.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.github.prominence.openweathermap.api.model.roadrisk; - -import com.github.prominence.openweathermap.api.model.Coordinates; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Objects; - -public class RoadRiskRecord { - private LocalDateTime forecastTime; - private Coordinates coordinates; - - private Weather weather; - private RoadDetails roadDetails; - - private List alerts; - - public LocalDateTime getForecastTime() { - return forecastTime; - } - - public void setForecastTime(LocalDateTime forecastTime) { - this.forecastTime = forecastTime; - } - - public Coordinates getCoordinates() { - return coordinates; - } - - public void setCoordinates(Coordinates coordinates) { - this.coordinates = coordinates; - } - - public Weather getWeather() { - return weather; - } - - public void setWeather(Weather weather) { - this.weather = weather; - } - - public RoadDetails getRoadDetails() { - return roadDetails; - } - - public void setRoadDetails(RoadDetails roadDetails) { - this.roadDetails = roadDetails; - } - - public List getAlerts() { - return alerts; - } - - public void setAlerts(List alerts) { - this.alerts = alerts; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RoadRiskRecord record = (RoadRiskRecord) o; - return Objects.equals(forecastTime, record.forecastTime) && Objects.equals(coordinates, record.coordinates) && Objects.equals(weather, record.weather) && Objects.equals(roadDetails, record.roadDetails) && Objects.equals(alerts, record.alerts); - } - - @Override - public int hashCode() { - return Objects.hash(forecastTime, coordinates, weather, roadDetails, alerts); - } - - @Override - public String toString() { - return "RoadRiskRecord{" + - "forecastTime=" + forecastTime + - ", coordinates=" + coordinates + - ", weather=" + weather + - ", roadDetails=" + roadDetails + - ", alerts=" + alerts + - '}'; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/TrackPoint.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/TrackPoint.java index 22de4dd..8dbe6be 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/TrackPoint.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/TrackPoint.java @@ -1,48 +1,48 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.serializer.EpochSecondsSerializer; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; -import java.time.LocalDateTime; -import java.util.Objects; +import java.time.OffsetDateTime; -public class TrackPoint { - private Coordinates coordinates; - private LocalDateTime requestedTime; +@Getter +@Setter +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TrackPoint extends Coordinates { + @JsonSerialize(using = EpochSecondsSerializer.class) + @JsonProperty("dt") + private OffsetDateTime requestedTime; - public Coordinates getCoordinates() { - return coordinates; - } - - public void setCoordinates(Coordinates coordinates) { - this.coordinates = coordinates; - } - - public LocalDateTime getRequestedTime() { - return requestedTime; - } - - public void setRequestedTime(LocalDateTime requestedTime) { - this.requestedTime = requestedTime; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TrackPoint that = (TrackPoint) o; - return Objects.equals(coordinates, that.coordinates) && Objects.equals(requestedTime, that.requestedTime); - } - - @Override - public int hashCode() { - return Objects.hash(coordinates, requestedTime); - } - - @Override - public String toString() { - return "TrackPoint{" + - "coordinates=" + coordinates + - ", requestedTime=" + requestedTime + - '}'; + public TrackPoint(double latitude, double longitude) { + super(latitude, longitude); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Weather.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Weather.java deleted file mode 100644 index 5d3d4db..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Weather.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.github.prominence.openweathermap.api.model.roadrisk; - -import java.util.Objects; - -public class Weather { - - private Double temperature; - private Double windSpeed; - private Double windDegrees; - private Double precipitationIntensity; - private Double visibilityInMetres; - private Double dewPoint; - - public Double getTemperature() { - return temperature; - } - - public void setTemperature(Double temperature) { - this.temperature = temperature; - } - - public Double getWindSpeed() { - return windSpeed; - } - - public void setWindSpeed(Double windSpeed) { - this.windSpeed = windSpeed; - } - - public Double getWindDegrees() { - return windDegrees; - } - - public void setWindDegrees(Double windDegrees) { - this.windDegrees = windDegrees; - } - - public Double getPrecipitationIntensity() { - return precipitationIntensity; - } - - public void setPrecipitationIntensity(Double precipitationIntensity) { - this.precipitationIntensity = precipitationIntensity; - } - - public Double getVisibilityInMetres() { - return visibilityInMetres; - } - - public void setVisibilityInMetres(Double visibilityInMetres) { - this.visibilityInMetres = visibilityInMetres; - } - - public Double getDewPoint() { - return dewPoint; - } - - public void setDewPoint(Double dewPoint) { - this.dewPoint = dewPoint; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Weather weather = (Weather) o; - return Objects.equals(temperature, weather.temperature) && Objects.equals(windSpeed, weather.windSpeed) && Objects.equals(windDegrees, weather.windDegrees) && Objects.equals(precipitationIntensity, weather.precipitationIntensity) && Objects.equals(visibilityInMetres, weather.visibilityInMetres) && Objects.equals(dewPoint, weather.dewPoint); - } - - @Override - public int hashCode() { - return Objects.hash(temperature, windSpeed, windDegrees, precipitationIntensity, visibilityInMetres, dewPoint); - } - - @Override - public String toString() { - return "Weather{" + - "temperature=" + temperature + - ", windSpeed=" + windSpeed + - ", windDegrees=" + windDegrees + - ", precipitationIntensity=" + precipitationIntensity + - ", visibilityInMetres=" + visibilityInMetres + - ", dewPoint=" + dewPoint + - '}'; - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/WeatherModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/WeatherModel.java new file mode 100644 index 0000000..0301b3d --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/WeatherModel.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.PrecipitationIntensityDeserializer; +import com.github.prominence.openweathermap.api.deserializer.TemperatureValueDeserializer; +import com.github.prominence.openweathermap.api.deserializer.VisibilityDeserializer; +import com.github.prominence.openweathermap.api.deserializer.WindSpeedDeserializer; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationIntensity; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; +import lombok.Data; + +@Data +public class WeatherModel { + + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("temp") + private TemperatureValue temperature; + @JsonDeserialize(using = WindSpeedDeserializer.class) + @JsonProperty("wind_speed") + private WindSpeed windSpeed; + @JsonProperty("wind_deg") + private Integer windDegrees; + @JsonDeserialize(using = PrecipitationIntensityDeserializer.class) + @JsonProperty("precipitation_intensity") + private PrecipitationIntensity precipitationIntensity; + @JsonDeserialize(using = VisibilityDeserializer.class) + @JsonProperty("visibility") + private Visibility visibility; + @JsonDeserialize(using = TemperatureValueDeserializer.class) + @JsonProperty("dew_point") + private TemperatureValue dewPoint; + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/weather/City.java b/src/main/java/com/github/prominence/openweathermap/api/model/weather/City.java new file mode 100644 index 0000000..c8dcb13 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/weather/City.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-present 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.weather; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.OffsetDateTime; + +/** + * Represents location information. + */ +@Data +public class City { + + @JsonProperty("type") + private int type; + @JsonProperty("id") + private int id; + @JsonProperty("message") + private BigDecimal message; + @JsonProperty("country") + private String countryCode; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunrise") + private OffsetDateTime sunriseTime; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("sunset") + private OffsetDateTime sunsetTime; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/weather/CurrentWeather.java b/src/main/java/com/github/prominence/openweathermap/api/model/weather/CurrentWeather.java new file mode 100644 index 0000000..0696069 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/weather/CurrentWeather.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021-present 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.weather; + +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.pressure.DetailedAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureWithRange; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; + +import java.util.List; + +/** + * Current weather forecast response. + */ +public interface CurrentWeather extends TimeAware { + + /** + * The location of the forecast. + * + * @return location + */ + BaseLocation getLocation(); + + /** + * The sunlight stages. + * + * @return sunlight + */ + SunlightStages getSunlightStages(); + + /** + * The wind conditions. + * + * @return wind + */ + DetailedWindInfo getWind(); + + /** + * The weather states. + * + * @return weather + */ + List getWeatherStates(); + + /** + * The temperature forecast. + * + * @return temperature + */ + TemperatureWithRange getTemperature(); + + /** + * The precipitation forecast. + * + * @return precipitation + */ + PrecipitationDetails getPrecipitation(); + + /** + * The expected humidity. + * + * @return humidity + */ + Humidity getHumidity(); + + /** + * The cloud coverage. + * + * @return clouds + */ + CloudCoverage getClouds(); + + /** + * The atmospheric pressure forecast. + * + * @return pressure + */ + DetailedAtmosphericPressure getAtmosphericPressure(); + + /** + * The visibility information. + * + * @return visibility + */ + Visibility getVisibility(); + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/weather/CurrentWeatherModel.java b/src/main/java/com/github/prominence/openweathermap/api/model/weather/CurrentWeatherModel.java new file mode 100644 index 0000000..4bf06a8 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/weather/CurrentWeatherModel.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2021-present 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.weather; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.github.prominence.openweathermap.api.deserializer.EpochSecondsDeserializer; +import com.github.prominence.openweathermap.api.deserializer.VisibilityDeserializer; +import com.github.prominence.openweathermap.api.deserializer.ZoneOffsetDeserializer; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.MainMetrics; +import com.github.prominence.openweathermap.api.model.generic.TimeAware; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.clouds.Clouds; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.pressure.DetailedAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureWithRange; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; +import com.github.prominence.openweathermap.api.model.generic.wind.WindModel; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Represents weather information. + */ +@Data +public class CurrentWeatherModel implements TimeAware, BaseLocation, SunlightStages, CurrentWeather, PrecipitationDetails { + + @JsonProperty("coord") + private Coordinates coordinates; + @JsonProperty("weather") + private List weatherStates = new ArrayList<>(); + @JsonProperty("base") + private String base; + @JsonProperty("main") + private MainMetrics main; + @JsonDeserialize(using = VisibilityDeserializer.class) + @JsonProperty("visibility") + private Visibility visibility; + @JsonProperty("wind") + private WindModel windModel; + @JsonProperty("clouds") + private Clouds cloudsModel; + @JsonProperty("rain") + private Precipitation rain; + @JsonProperty("snow") + private Precipitation snow; + @JsonDeserialize(using = EpochSecondsDeserializer.class) + @JsonProperty("dt") + private OffsetDateTime forecastTime; + @JsonProperty("sys") + private City city; + @JsonDeserialize(using = ZoneOffsetDeserializer.class) + @JsonProperty("timezone") + private ZoneOffset timeZone; + @JsonProperty("id") + private long cityId; + @JsonProperty("name") + private String cityName; + @JsonProperty("cod") + private long cod; + + @Override + @JsonIgnore + public TemperatureWithRange getTemperature() { + return main; + } + + @Override + @JsonIgnore + public Humidity getHumidity() { + return main; + } + + @Override + @JsonIgnore + public DetailedAtmosphericPressure getAtmosphericPressure() { + return main; + } + + @Override + @JsonIgnore + public BaseLocation getLocation() { + return this; + } + + @JsonIgnore + public DetailedWindInfo getWind() { + return windModel; + } + + @Override + @JsonIgnore + public PrecipitationDetails getPrecipitation() { + return this; + } + + @Override + @JsonIgnore + public String getCountryCode() { + return Optional.ofNullable(city).map(City::getCountryCode).orElse(null); + } + + @Override + @JsonIgnore + public OffsetDateTime getSunriseTime() { + return Optional.ofNullable(city).map(City::getSunriseTime).orElse(null); + } + + @Override + @JsonIgnore + public OffsetDateTime getSunsetTime() { + return Optional.ofNullable(city).map(City::getSunsetTime).orElse(null); + } + + @Override + @JsonIgnore + public SunlightStages getSunlightStages() { + return this; + } + + @Override + @JsonIgnore + public BigDecimal getOneHourRainLevel() { + return Optional.ofNullable(rain).map(Precipitation::getOneHourLevel).orElse(null); + } + + @Override + @JsonIgnore + public BigDecimal getThreeHoursRainLevel() { + return Optional.ofNullable(rain).map(Precipitation::getThreeHourLevel).orElse(null); + } + + @Override + @JsonIgnore + public BigDecimal getOneHourSnowLevel() { + return Optional.ofNullable(snow).map(Precipitation::getOneHourLevel).orElse(null); + } + + @Override + @JsonIgnore + public BigDecimal getThreeHoursSnowLevel() { + return Optional.ofNullable(snow).map(Precipitation::getThreeHourLevel).orElse(null); + } + + @Override + @JsonIgnore + public CloudCoverage getClouds() { + return cloudsModel; + } +} 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 deleted file mode 100644 index ef63e2f..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Location.java +++ /dev/null @@ -1,227 +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.weather; - -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 getCoordinates() { - return coordinates; - } - - /** - * Sets location coordinates. - * - * @param coordinates location coordinates - */ - public void setCoordinates(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/weather/Precipitation.java b/src/main/java/com/github/prominence/openweathermap/api/model/weather/Precipitation.java new file mode 100644 index 0000000..3a2b01b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/weather/Precipitation.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021-present 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.weather; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.prominence.openweathermap.api.model.generic.precipitation.BasePrecipitation; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; + +/** + * Represents snow/rain information. + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class Precipitation extends BasePrecipitation { + @JsonProperty("3h") + private BigDecimal threeHourLevel; +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/weather/PrecipitationDetails.java b/src/main/java/com/github/prominence/openweathermap/api/model/weather/PrecipitationDetails.java new file mode 100644 index 0000000..94a52a2 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/weather/PrecipitationDetails.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021-present 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.weather; + +import java.math.BigDecimal; + +/** + * Precipitation details. + */ +public interface PrecipitationDetails { + + /** + * The rain amount under one hour. + * + * @return rain 1h + */ + BigDecimal getOneHourRainLevel(); + + /** + * The rain amount under three hours. + * + * @return rain 3h + */ + BigDecimal getThreeHoursRainLevel(); + + /** + * The snow amount under one hour. + * + * @return snow 1h + */ + BigDecimal getOneHourSnowLevel(); + + /** + * The snow amount under three hours. + * + * @return snow 3h + */ + BigDecimal getThreeHoursSnowLevel(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Rain.java b/src/main/java/com/github/prominence/openweathermap/api/model/weather/Rain.java deleted file mode 100644 index a350b0c..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Rain.java +++ /dev/null @@ -1,160 +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.weather; - -import java.util.Objects; - -/** - * Represents rain information. - */ -public class Rain { - private static final String DEFAULT_UNIT = "mm"; - - private Double oneHourLevel; - private Double threeHourLevel; - - private Rain() { - } - - /** - * Creates {@link Rain} object with correctness check. - * - * @param oneHourLevel 1-hour rain level value - * @return rain object. - */ - public static Rain withOneHourLevelValue(double oneHourLevel) { - final Rain rain = new Rain(); - rain.setOneHourLevel(oneHourLevel); - return rain; - } - - /** - * Creates {@link Rain} object with correctness check. - * - * @param threeHourLevel 3-hour rain level value - * @return rain object. - */ - public static Rain withThreeHourLevelValue(double threeHourLevel) { - final Rain rain = new Rain(); - rain.setThreeHourLevel(threeHourLevel); - return rain; - } - - /** - * Creates {@link Rain} object with correctness check. - * - * @param oneHourLevel the one hour rain level - * @param threeHourLevel the three hour rain level - * @return the rain - */ - public static Rain withValues(double oneHourLevel, double threeHourLevel) { - final Rain rain = new Rain(); - rain.setOneHourLevel(oneHourLevel); - rain.setThreeHourLevel(threeHourLevel); - return rain; - } - - /** - * Gets one hour rain level. - * - * @return the one hour rain level - */ - public Double getOneHourLevel() { - return oneHourLevel; - } - - /** - * Sets one hour rain level. - * - * @param oneHourLevel the one hour rain level - */ - public void setOneHourLevel(double oneHourLevel) { - if (oneHourLevel < 0) { - throw new IllegalArgumentException("Rain level value cannot be negative."); - } - this.oneHourLevel = oneHourLevel; - } - - /** - * Gets three hour rain level. - * - * @return the three hour rain level - */ - public Double getThreeHourLevel() { - return threeHourLevel; - } - - /** - * Sets three hour rain level. - * - * @param threeHourLevel the three hour rain level - */ - public void setThreeHourLevel(double threeHourLevel) { - if (threeHourLevel < 0) { - throw new IllegalArgumentException("Rain level value cannot be negative."); - } - this.threeHourLevel = threeHourLevel; - } - - /** - * Gets unit. - * - * @return the unit - */ - public String getUnit() { - return DEFAULT_UNIT; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Rain)) return false; - Rain rain = (Rain) o; - return Objects.equals(oneHourLevel, rain.oneHourLevel) && - Objects.equals(threeHourLevel, rain.threeHourLevel); - } - - @Override - public int hashCode() { - return Objects.hash(oneHourLevel, threeHourLevel); - } - - @Override - public String toString() { - final StringBuilder snowString = new StringBuilder(); - if (oneHourLevel != null) { - snowString.append("1-hour rain level: "); - snowString.append(oneHourLevel); - snowString.append(getUnit()); - } - if (threeHourLevel != null) { - if (oneHourLevel != null) { - snowString.append(", "); - } - snowString.append("3-hours rain level: "); - snowString.append(threeHourLevel); - snowString.append(getUnit()); - } - return snowString.toString(); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Snow.java b/src/main/java/com/github/prominence/openweathermap/api/model/weather/Snow.java deleted file mode 100644 index 305dcd2..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Snow.java +++ /dev/null @@ -1,160 +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.weather; - -import java.util.Objects; - -/** - * Represents snow information. - */ -public class Snow { - private static final String DEFAULT_UNIT = "mm"; - - private Double oneHourLevel; - private Double threeHourLevel; - - private Snow() { - } - - /** - * Creates {@link Snow} object with correctness check. - * - * @param oneHourLevel 1-hour snow level value - * @return snow object. - */ - public static Snow withOneHourLevelValue(double oneHourLevel) { - final Snow snow = new Snow(); - snow.setOneHourLevel(oneHourLevel); - return snow; - } - - /** - * Creates {@link Snow} object with correctness check. - * - * @param threeHourLevel 3-hour snow level value - * @return snow object. - */ - public static Snow withThreeHourLevelValue(double threeHourLevel) { - final Snow snow = new Snow(); - snow.setThreeHourLevel(threeHourLevel); - return snow; - } - - /** - * Creates {@link Snow} object with correctness check. - * - * @param oneHourLevel the one hour snow level - * @param threeHourLevel the three hour snow level - * @return the snow - */ - public static Snow withValues(double oneHourLevel, double threeHourLevel) { - final Snow snow = new Snow(); - snow.setOneHourLevel(oneHourLevel); - snow.setThreeHourLevel(threeHourLevel); - return snow; - } - - /** - * Gets one hour snow level. - * - * @return the one hour snow level - */ - public Double getOneHourLevel() { - return oneHourLevel; - } - - /** - * Sets one hour snow level. - * - * @param oneHourLevel the one hour snow level - */ - public void setOneHourLevel(double oneHourLevel) { - if (oneHourLevel < 0) { - throw new IllegalArgumentException("Snow level value cannot be negative."); - } - this.oneHourLevel = oneHourLevel; - } - - /** - * Gets three hour snow level. - * - * @return the three hour snow level - */ - public Double getThreeHourLevel() { - return threeHourLevel; - } - - /** - * Sets three hour snow level. - * - * @param threeHourLevel the three hour snow level - */ - public void setThreeHourLevel(double threeHourLevel) { - if (threeHourLevel < 0) { - throw new IllegalArgumentException("Snow level value cannot be negative."); - } - this.threeHourLevel = threeHourLevel; - } - - /** - * Gets unit. - * - * @return the unit - */ - public String getUnit() { - return DEFAULT_UNIT; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Snow)) return false; - Snow snow = (Snow) o; - return Objects.equals(oneHourLevel, snow.oneHourLevel) && - Objects.equals(threeHourLevel, snow.threeHourLevel); - } - - @Override - public int hashCode() { - return Objects.hash(oneHourLevel, threeHourLevel); - } - - @Override - public String toString() { - final StringBuilder snowString = new StringBuilder(); - if (oneHourLevel != null) { - snowString.append("1-hour snow level: "); - snowString.append(oneHourLevel); - snowString.append(getUnit()); - } - if (threeHourLevel != null) { - if (oneHourLevel != null) { - snowString.append(", "); - } - snowString.append("3-hours snow level: "); - snowString.append(threeHourLevel); - snowString.append(getUnit()); - } - return snowString.toString(); - } -} 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 deleted file mode 100644 index 7503b2c..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/model/weather/Weather.java +++ /dev/null @@ -1,309 +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.weather; - -import com.github.prominence.openweathermap.api.model.*; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Objects; - -/** - * Represents weather information. - */ -public class Weather { - private LocalDateTime calculationTime; - - 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 Location location; - - private String base; - - /** - * Gets calculated on. - * - * @return the calculated on - */ - public LocalDateTime getCalculationTime() { - return calculationTime; - } - - /** - * Sets calculated on. - * - * @param calculationTime the calculated on - */ - public void setCalculationTime(LocalDateTime calculationTime) { - this.calculationTime = calculationTime; - } - - /** - * 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 location. - * - * @return the location - */ - public Location getLocation() { - return location; - } - - /** - * Sets location. - * - * @param location the location - */ - public void setLocation(Location location) { - 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 weather)) return false; - return Objects.equals(calculationTime, weather.calculationTime) && - Objects.equals(weatherStates, weather.weatherStates) && - Objects.equals(temperature, weather.temperature) && - Objects.equals(atmosphericPressure, weather.atmosphericPressure) && - Objects.equals(humidity, weather.humidity) && - Objects.equals(wind, weather.wind) && - Objects.equals(rain, weather.rain) && - Objects.equals(snow, weather.snow) && - Objects.equals(clouds, weather.clouds) && - Objects.equals(location, weather.location) && - Objects.equals(base, weather.base); - } - - @Override - public int hashCode() { - return Objects.hash(calculationTime, weatherStates, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, location, base); - } - - @Override - public String toString() { - final StringBuilder stringBuilder = new StringBuilder(); - if (location != null) { - stringBuilder.append("Location: "); - stringBuilder.append(location.getName()); - - final String countryCode = location.getCountryCode(); - if (countryCode != null) { - stringBuilder.append('('); - stringBuilder.append(countryCode); - stringBuilder.append(')'); - } - } - 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 && rain.getOneHourLevel() != null) { - stringBuilder.append(", Rain: "); - stringBuilder.append(rain.getOneHourLevel()); - stringBuilder.append(' '); - stringBuilder.append(rain.getUnit()); - } - if (snow != null && snow.getOneHourLevel() != null) { - stringBuilder.append(", Snow: "); - stringBuilder.append(snow.getOneHourLevel()); - stringBuilder.append(' '); - stringBuilder.append(snow.getUnit()); - } - return stringBuilder.toString(); - } -} 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 6264ba7..9fe48a9 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,71 +22,55 @@ package com.github.prominence.openweathermap.api.request; -import com.fasterxml.jackson.databind.JsonSerializer; import com.github.prominence.openweathermap.api.conf.TimeoutSettings; -import com.github.prominence.openweathermap.api.core.net.HttpClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; import com.github.prominence.openweathermap.api.enums.Language; import com.github.prominence.openweathermap.api.enums.ResponseType; import com.github.prominence.openweathermap.api.enums.UnitSystem; +import lombok.NonNull; import java.util.HashMap; import java.util.Map; public class RequestSettings { - private static final String LANG_PARAM = "lang"; - private static final String UNITS_PARAM = "units"; - private static final String MODE_PARAM = "mode"; - private static final String API_KEY_PARAM_NAME = "appid"; + public static final String LANG_PARAM = "lang"; + public static final String UNITS_PARAM = "units"; + public static final String MODE_PARAM = "mode"; + public static final String API_KEY_PARAM_NAME = "appid"; + public static final String LATITUDE_PARAM = "lat"; + public static final String LONGITUDE_PARAM = "lon"; + public static final String START_PARAM = "start"; + public static final String END_PARAM = "end"; + public static final String DATE_TIME_PARAM = "dt"; + public static final String QUERY_VALUE_PARAM = "q"; + public static final String ZIP_PARAM = "zip"; + public static final String COUNT_PARAM = "cnt"; - private final TimeoutSettings timeoutSettings; + private TimeoutSettings timeoutSettings; private final Map requestParameters = new HashMap<>(8); private final StringBuilder urlAppenderBuilder = new StringBuilder(); - - private Object payloadObject; - private Class payloadClass; - private JsonSerializer payloadSerializer; - - private HttpClient httpClient; - - private final boolean useInsecureConnection; - - private String subdomain = "api"; + private final ApiConfiguration apiConfiguration; private Language language = Language.ENGLISH; private UnitSystem unitSystem = UnitSystem.STANDARD; + private Object requestPayload; - public RequestSettings(String apiKey, TimeoutSettings timeoutSettings, boolean useInsecureConnection) { - this.putRequestParameter(API_KEY_PARAM_NAME, apiKey); + public RequestSettings(ApiConfiguration apiConfiguration) { + this.apiConfiguration = apiConfiguration; + this.putRequestParameter(API_KEY_PARAM_NAME, apiConfiguration.getApiKey()); // make a copy - this.timeoutSettings = new TimeoutSettings(timeoutSettings); - this.useInsecureConnection = useInsecureConnection; + this.timeoutSettings = new TimeoutSettings(apiConfiguration.getDefaultTimeoutSettings()); } public TimeoutSettings getTimeoutSettings() { return timeoutSettings; } - public HttpClient getHttpClient() { - return httpClient; - } - - public void setHttpClient(HttpClient httpClient) { - this.httpClient = httpClient; - } - - public boolean isUseInsecureConnection() { - return useInsecureConnection; - } - - public String getSubdomain() { - return subdomain; - } - - public void setSubdomain(String subdomain) { - this.subdomain = subdomain; + public void setTimeoutSettings(@NonNull TimeoutSettings timeoutSettings) { + this.timeoutSettings = timeoutSettings; } public UnitSystem getUnitSystem() { @@ -131,27 +115,15 @@ public class RequestSettings { return urlAppenderBuilder; } - public void setPayloadObject(Object payloadObject) { - this.payloadObject = payloadObject; + public ApiConfiguration getApiConfiguration() { + return apiConfiguration; } public Object getPayloadObject() { - return payloadObject; + return requestPayload; } - public Class getPayloadClass() { - return payloadClass; - } - - public void setPayloadClass(Class payloadClass) { - this.payloadClass = payloadClass; - } - - public JsonSerializer getPayloadSerializer() { - return payloadSerializer; - } - - public void setPayloadSerializer(JsonSerializer payloadSerializer) { - this.payloadSerializer = payloadSerializer; + public void setPayloadObject(Object payload) { + this.requestPayload = payload; } } 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 d1fcfc6..4036a96 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 @@ -1,41 +1,39 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.air.pollution; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.mapper.AirPollutionResponseMapper; import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails; +import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetailsModel; import com.github.prominence.openweathermap.api.request.RequestSettings; - -import java.util.concurrent.CompletableFuture; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; /** * The type Air pollution async request terminator. */ -public class AirPollutionAsyncRequestTerminator { - private final RequestSettings requestSettings; +public class AirPollutionAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements JsonAsyncApiTerminator { /** * Instantiates a new Air pollution async request terminator. @@ -43,18 +41,8 @@ public class AirPollutionAsyncRequestTerminator { * @param requestSettings request settings object. */ AirPollutionAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(new AirPollutionRequestTerminator(requestSettings)); } - public CompletableFuture asJava() { - return CompletableFuture.supplyAsync(() -> new AirPollutionResponseMapper().mapToAirPollution(getRawResponse())); - } - public CompletableFuture asJSON() { - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); - } } 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 1f63687..e6356eb 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 @@ -1,30 +1,31 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.air.pollution; +import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; /** * The Air Pollution request customizer. @@ -41,11 +42,11 @@ public class AirPollutionRequestCustomizer { this.requestSettings = requestSettings; } - public AirPollutionRequestTerminator retrieve() { + public JsonApiTerminator retrieve() { return new AirPollutionRequestTerminator(requestSettings); } - public AirPollutionAsyncRequestTerminator retrieveAsync() { + public JsonAsyncApiTerminator retrieveAsync() { return new AirPollutionAsyncRequestTerminator(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 9dc7b95..a05818b 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 @@ -1,39 +1,42 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.air.pollution; import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.mapper.AirPollutionResponseMapper; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails; +import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetailsModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; /** * The type Air pollution request terminator. */ -public class AirPollutionRequestTerminator { - private final RequestSettings requestSettings; +public class AirPollutionRequestTerminator + extends GenericRequestTerminator + implements JsonApiTerminator { /** * Instantiates a new Air pollution request terminator. @@ -41,18 +44,27 @@ public class AirPollutionRequestTerminator { * @param requestSettings request settings object. */ AirPollutionRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); } - public AirPollutionDetails asJava() { - return new AirPollutionResponseMapper().mapToAirPollution(getRawResponse()); + @Override + public String asXML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("XML format not supported for this API."); } - public String asJSON() { - return getRawResponse(); + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); } - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + protected String getRawResponse() { + return new RequestExecutor(requestSettings).getResponse(ApiVariant.BASE); + } + + @Override + protected Class getValueType() { + return AirPollutionDetailsModel.class; } } 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 6ded2cf..36b41cb 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 @@ -1,44 +1,41 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.air.pollution; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; /** * The type Air pollution requester. */ -public class AirPollutionRequester { - private final RequestSettings requestSettings; - +public class AirPollutionRequester extends GenericRequester { /** * Instantiates a new Air pollution requester. * * @param requestSettings request settings object. */ public AirPollutionRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); requestSettings.appendToURL("data/2.5/air_pollution"); } 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 1ee503e..c0755f7 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,9 +22,12 @@ package com.github.prominence.openweathermap.api.request.air.pollution; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; + /** * The type Current air pollution requester. */ @@ -41,8 +44,8 @@ public class CurrentAirPollutionRequester { } public AirPollutionRequestCustomizer byCoordinates(Coordinates coordinates) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, 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 46449ca..81485e1 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,9 +22,12 @@ package com.github.prominence.openweathermap.api.request.air.pollution; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; + /** * The type Forecast air pollution requester. */ @@ -41,8 +44,8 @@ public class ForecastAirPollutionRequester { } public AirPollutionRequestCustomizer byCoordinates(Coordinates coordinates) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, 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 8856cdf..a342ac6 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,9 +22,14 @@ package com.github.prominence.openweathermap.api.request.air.pollution; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.END_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.START_PARAM; + /** * The type Historical air pollution requester. */ @@ -41,10 +46,10 @@ public class HistoricalAirPollutionRequester { } 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)); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(START_PARAM, String.valueOf(startUnixTime)); + requestSettings.putRequestParameter(END_PARAM, String.valueOf(endUnixTime)); return new AirPollutionRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastAsyncRequestTerminator.java index 8fc0b6e..fbaa966 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastAsyncRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,35 +22,18 @@ package com.github.prominence.openweathermap.api.request.forecast.climatic; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.ClimaticForecastResponseMapper; -import com.github.prominence.openweathermap.api.model.forecast.climatic.Forecast; +import com.github.prominence.openweathermap.api.model.forecast.climatic.ThirtyDaysDailyForecast; +import com.github.prominence.openweathermap.api.model.forecast.climatic.ThirtyDaysDailyForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlAsyncApiTerminator; -import java.util.concurrent.CompletableFuture; - -class ClimaticForecastAsyncRequestTerminator { - private final RequestSettings requestSettings; +class ClimaticForecastAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements JsonXmlAsyncApiTerminator { ClimaticForecastAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(new ClimaticForecastRequestTerminator(requestSettings)); } - public CompletableFuture asJava() { - return CompletableFuture.supplyAsync(() -> new ClimaticForecastResponseMapper(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 new RequestExecutor(requestSettings).getResponse(); - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestCustomizer.java index 34e16ac..e8e194a 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestCustomizer.java @@ -1,11 +1,37 @@ +/* + * Copyright (c) 2021-present 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.climatic; import com.github.prominence.openweathermap.api.enums.Language; -import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.climatic.ThirtyDaysDailyForecast; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlAsyncApiTerminator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static com.github.prominence.openweathermap.api.request.RequestSettings.COUNT_PARAM; + public class ClimaticForecastRequestCustomizer { private static final Logger logger = LoggerFactory.getLogger(ClimaticForecastRequestCustomizer.class); @@ -20,26 +46,21 @@ public class ClimaticForecastRequestCustomizer { return this; } - public ClimaticForecastRequestCustomizer unitSystem(UnitSystem unitSystem) { - requestSettings.setUnitSystem(unitSystem); - return this; - } - public ClimaticForecastRequestCustomizer numberOfDays(int numberOfDays) { int days = numberOfDays; if (days > 30) { logger.warn("Cannot use more than 30 days for this API request. Please, specify 30 or less days. !!! Requesting information for 30 days..."); days = 30; } - requestSettings.putRequestParameter("cnt", Integer.toString(days)); + requestSettings.putRequestParameter(COUNT_PARAM, Integer.toString(days)); return this; } - public ClimaticForecastRequestTerminator retrieve() { + public JsonXmlApiTerminator retrieve() { return new ClimaticForecastRequestTerminator(requestSettings); } - public ClimaticForecastAsyncRequestTerminator retrieveAsync() { + public JsonXmlAsyncApiTerminator retrieveAsync() { return new ClimaticForecastAsyncRequestTerminator(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestTerminator.java index 1076676..91d7557 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,32 +23,34 @@ package com.github.prominence.openweathermap.api.request.forecast.climatic; import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.ClimaticForecastResponseMapper; -import com.github.prominence.openweathermap.api.model.forecast.climatic.Forecast; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.climatic.ThirtyDaysDailyForecast; +import com.github.prominence.openweathermap.api.model.forecast.climatic.ThirtyDaysDailyForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlApiTerminator; -class ClimaticForecastRequestTerminator { - private final RequestSettings requestSettings; +class ClimaticForecastRequestTerminator + extends GenericRequestTerminator + implements JsonXmlApiTerminator { - ClimaticForecastRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + ClimaticForecastRequestTerminator(RequestSettings requestSettings) { + super(requestSettings); } - public Forecast asJava() { - return new ClimaticForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse()); + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); } - public String asJSON() { - return getRawResponse(); + protected String getRawResponse() { + return new RequestExecutor(requestSettings).getResponse(ApiVariant.PRO); } - public String asXML() { - requestSettings.setResponseType(ResponseType.XML); - return getRawResponse(); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + @Override + protected Class getValueType() { + return ThirtyDaysDailyForecastModel.class; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequester.java index a937c13..f3ac230 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequester.java @@ -1,20 +1,44 @@ +/* + * Copyright (c) 2021-present 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.climatic; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; -public class ClimaticForecastRequester { - private final RequestSettings requestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; + +public class ClimaticForecastRequester extends GenericRequester { public ClimaticForecastRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - this.requestSettings.setSubdomain("pro"); + super(requestSettings); this.requestSettings.appendToURL("data/2.5/forecast/climate"); } public ClimaticForecastRequestCustomizer byCoordinates(Coordinates coordinates) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, String.valueOf(coordinates.getLongitude())); return new ClimaticForecastRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminator.java index da2b56f..515db1e 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,35 +22,17 @@ package com.github.prominence.openweathermap.api.request.forecast.daily; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.DailyForecastResponseMapper; -import com.github.prominence.openweathermap.api.model.forecast.daily.Forecast; +import com.github.prominence.openweathermap.api.model.forecast.daily.SixteenDaysDailyForecast; +import com.github.prominence.openweathermap.api.model.forecast.daily.SixteenDaysDailyForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlAsyncApiTerminator; -import java.util.concurrent.CompletableFuture; - -class DailyForecastAsyncRequestTerminator { - private final RequestSettings requestSettings; +class DailyForecastAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements JsonXmlAsyncApiTerminator { DailyForecastAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - } - - public CompletableFuture asJava() { - return CompletableFuture.supplyAsync(() -> new DailyForecastResponseMapper(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 new RequestExecutor(requestSettings).getResponse(); + super(new DailyForecastRequestTerminator(requestSettings)); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestCustomizer.java index 03b307d..bd423b8 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,11 +23,15 @@ 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.model.forecast.daily.SixteenDaysDailyForecast; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlAsyncApiTerminator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static com.github.prominence.openweathermap.api.request.RequestSettings.COUNT_PARAM; + class DailyForecastRequestCustomizer { private static final Logger logger = LoggerFactory.getLogger(DailyForecastRequestCustomizer.class); @@ -42,26 +46,21 @@ class DailyForecastRequestCustomizer { return this; } - public DailyForecastRequestCustomizer unitSystem(UnitSystem unitSystem) { - requestSettings.setUnitSystem(unitSystem); - return this; - } - 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)); + requestSettings.putRequestParameter(COUNT_PARAM, Integer.toString(days)); return this; } - public DailyForecastRequestTerminator retrieve() { + public JsonXmlApiTerminator retrieve() { return new DailyForecastRequestTerminator(requestSettings); } - public DailyForecastAsyncRequestTerminator retrieveAsync() { + public JsonXmlAsyncApiTerminator retrieveAsync() { return new DailyForecastAsyncRequestTerminator(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminator.java index 8c53237..fbf15d2 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,32 +23,34 @@ package com.github.prominence.openweathermap.api.request.forecast.daily; import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.DailyForecastResponseMapper; -import com.github.prominence.openweathermap.api.model.forecast.daily.Forecast; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.daily.SixteenDaysDailyForecast; +import com.github.prominence.openweathermap.api.model.forecast.daily.SixteenDaysDailyForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlApiTerminator; -class DailyForecastRequestTerminator { - private final RequestSettings requestSettings; +class DailyForecastRequestTerminator + extends GenericRequestTerminator + implements JsonXmlApiTerminator { - DailyForecastRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + DailyForecastRequestTerminator(RequestSettings requestSettings) { + super(requestSettings); } - public Forecast asJava() { - return new DailyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse()); + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); } - public String asJSON() { - return getRawResponse(); + protected String getRawResponse() { + return new RequestExecutor(requestSettings).getResponse(ApiVariant.BASE); } - public String asXML() { - requestSettings.setResponseType(ResponseType.XML); - return getRawResponse(); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + @Override + protected Class getValueType() { + return SixteenDaysDailyForecastModel.class; } } 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 index fe9ab50..7629f7c 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,20 +22,23 @@ package com.github.prominence.openweathermap.api.request.forecast.daily; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; -public class DailyForecastRequester { - private final RequestSettings requestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; + +public class DailyForecastRequester extends GenericRequester { public DailyForecastRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); this.requestSettings.appendToURL("data/2.5/forecast/daily"); } public DailyForecastRequestCustomizer byCoordinates(Coordinates coordinates) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, 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 75e49b0..70aa166 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,19 +22,18 @@ package com.github.prominence.openweathermap.api.request.forecast.free; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.FiveDayThreeHourStepForecastResponseMapper; -import com.github.prominence.openweathermap.api.model.forecast.free.Forecast; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecast; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; - -import java.util.concurrent.CompletableFuture; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlAsyncApiTerminator; /** * Async request terminator. */ -class FiveDayThreeHourStepForecastAsyncRequestTerminator { - private final RequestSettings requestSettings; +class FiveDayThreeHourStepForecastAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements JsonXmlAsyncApiTerminator { /** * Instantiates a new async request terminator. @@ -42,23 +41,6 @@ class FiveDayThreeHourStepForecastAsyncRequestTerminator { * @param requestSettings request settings object. */ FiveDayThreeHourStepForecastAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - } - - public CompletableFuture asJava() { - return CompletableFuture.supplyAsync(() -> new FiveDayThreeHourStepForecastResponseMapper(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 new RequestExecutor(requestSettings).getResponse(); + super(new FiveDayThreeHourStepForecastRequestTerminator(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 925319e..a84a56b 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,8 +23,12 @@ package com.github.prominence.openweathermap.api.request.forecast.free; import com.github.prominence.openweathermap.api.enums.Language; -import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecast; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlAsyncApiTerminator; + +import static com.github.prominence.openweathermap.api.request.RequestSettings.COUNT_PARAM; /** * The forecast request customizer. @@ -46,21 +50,16 @@ class FiveDayThreeHourStepForecastRequestCustomizer { return this; } - public FiveDayThreeHourStepForecastRequestCustomizer unitSystem(UnitSystem unitSystem) { - requestSettings.setUnitSystem(unitSystem); - return this; - } - public FiveDayThreeHourStepForecastRequestCustomizer count(int numberOfTimestamps) { - requestSettings.putRequestParameter("cnt", Integer.toString(numberOfTimestamps)); + requestSettings.putRequestParameter(COUNT_PARAM, Integer.toString(numberOfTimestamps)); return this; } - public FiveDayThreeHourStepForecastRequestTerminator retrieve() { + public JsonXmlApiTerminator retrieve() { return new FiveDayThreeHourStepForecastRequestTerminator(requestSettings); } - public FiveDayThreeHourStepForecastAsyncRequestTerminator retrieveAsync() { + public JsonXmlAsyncApiTerminator retrieveAsync() { return new FiveDayThreeHourStepForecastAsyncRequestTerminator(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 20ccb5b..fa29616 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,16 +23,20 @@ package com.github.prominence.openweathermap.api.request.forecast.free; import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.FiveDayThreeHourStepForecastResponseMapper; -import com.github.prominence.openweathermap.api.model.forecast.free.Forecast; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecast; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlApiTerminator; /** * The forecast request terminator. */ -class FiveDayThreeHourStepForecastRequestTerminator { - private final RequestSettings requestSettings; +class FiveDayThreeHourStepForecastRequestTerminator + extends GenericRequestTerminator + implements JsonXmlApiTerminator { /** * Instantiates a new forecast request terminator. @@ -40,23 +44,21 @@ class FiveDayThreeHourStepForecastRequestTerminator { * @param requestSettings request settings object. */ FiveDayThreeHourStepForecastRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); } - public Forecast asJava() { - return new FiveDayThreeHourStepForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse()); + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); } - public String asJSON() { - return getRawResponse(); + protected String getRawResponse() { + return new RequestExecutor(requestSettings).getResponse(ApiVariant.BASE); } - public String asXML() { - requestSettings.setResponseType(ResponseType.XML); - return getRawResponse(); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + @Override + protected Class getValueType() { + return FiveDaysThreeHoursForecastModel.class; } } 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 b87df1d..20a5eb5 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,14 +22,18 @@ package com.github.prominence.openweathermap.api.request.forecast.free; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; + +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.QUERY_VALUE_PARAM; /** * The forecast requester. */ -public class FiveDayThreeHourStepForecastRequester { - private final RequestSettings requestSettings; +public class FiveDayThreeHourStepForecastRequester extends GenericRequester { /** * Instantiates a new forecast requester. @@ -37,48 +41,18 @@ public class FiveDayThreeHourStepForecastRequester { * @param requestSettings request settings object. */ public FiveDayThreeHourStepForecastRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); this.requestSettings.appendToURL("data/2.5/forecast"); } public FiveDayThreeHourStepForecastRequestCustomizer byCityName(String cityName) { - requestSettings.putRequestParameter("q", cityName); - return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings); - } - - @Deprecated - public FiveDayThreeHourStepForecastRequestCustomizer byCityName(String cityName, String stateCode) { - requestSettings.putRequestParameter("q", cityName + "," + stateCode); - return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings); - } - - @Deprecated - public FiveDayThreeHourStepForecastRequestCustomizer byCityName(String cityName, String stateCode, String countryCode) { - requestSettings.putRequestParameter("q", cityName + "," + stateCode + "," + countryCode); - return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings); - } - - @Deprecated - public FiveDayThreeHourStepForecastRequestCustomizer byCityId(long cityId) { - requestSettings.putRequestParameter("id", Long.toString(cityId)); + requestSettings.putRequestParameter(QUERY_VALUE_PARAM, cityName); return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings); } public FiveDayThreeHourStepForecastRequestCustomizer byCoordinates(Coordinates coordinates) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); - return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings); - } - - @Deprecated - public FiveDayThreeHourStepForecastRequestCustomizer byZipCodeAndCountry(String zipCode, String countryCode) { - requestSettings.putRequestParameter("zip", zipCode + "," + countryCode); - return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings); - } - - @Deprecated - public FiveDayThreeHourStepForecastRequestCustomizer byZipCodeInUSA(String zipCode) { - requestSettings.putRequestParameter("zip", zipCode); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, String.valueOf(coordinates.getLongitude())); return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminator.java index 6b98031..118611e 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,35 +22,17 @@ package com.github.prominence.openweathermap.api.request.forecast.hourly; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -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.model.forecast.hourly.FourDaysHourlyForecast; +import com.github.prominence.openweathermap.api.model.forecast.hourly.FourDaysHourlyForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlAsyncApiTerminator; -import java.util.concurrent.CompletableFuture; - -class FourDaysHourlyForecastAsyncRequestTerminator { - private final RequestSettings requestSettings; +class FourDaysHourlyForecastAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements JsonXmlAsyncApiTerminator { FourDaysHourlyForecastAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - } - - 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 new RequestExecutor(requestSettings).getResponse(); + super(new FourDaysHourlyForecastRequestTerminator(requestSettings)); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestCustomizer.java index 8a1133a..beea983 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,7 +23,12 @@ package com.github.prominence.openweathermap.api.request.forecast.hourly; import com.github.prominence.openweathermap.api.enums.Language; +import com.github.prominence.openweathermap.api.model.forecast.hourly.FourDaysHourlyForecast; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlAsyncApiTerminator; + +import static com.github.prominence.openweathermap.api.request.RequestSettings.COUNT_PARAM; class FourDaysHourlyForecastRequestCustomizer { private final RequestSettings requestSettings; @@ -38,15 +43,15 @@ class FourDaysHourlyForecastRequestCustomizer { } public FourDaysHourlyForecastRequestCustomizer count(int numberOfTimestamps) { - requestSettings.putRequestParameter("cnt", Integer.toString(numberOfTimestamps)); + requestSettings.putRequestParameter(COUNT_PARAM, Integer.toString(numberOfTimestamps)); return this; } - public FourDaysHourlyForecastRequestTerminator retrieve() { + public JsonXmlApiTerminator retrieve() { return new FourDaysHourlyForecastRequestTerminator(requestSettings); } - public FourDaysHourlyForecastAsyncRequestTerminator retrieveAsync() { + public JsonXmlAsyncApiTerminator retrieveAsync() { return new FourDaysHourlyForecastAsyncRequestTerminator(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminator.java index 7e13fa4..8b87d52 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,32 +23,34 @@ package com.github.prominence.openweathermap.api.request.forecast.hourly; import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -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.enums.ApiVariant; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.hourly.FourDaysHourlyForecast; +import com.github.prominence.openweathermap.api.model.forecast.hourly.FourDaysHourlyForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonXmlApiTerminator; -class FourDaysHourlyForecastRequestTerminator { - private final RequestSettings requestSettings; - - FourDaysHourlyForecastRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; +class FourDaysHourlyForecastRequestTerminator + extends GenericRequestTerminator + implements JsonXmlApiTerminator { + FourDaysHourlyForecastRequestTerminator(RequestSettings requestSettings) { + super(requestSettings); } - public HourlyForecast asJava() { - return new HourlyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse()); + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); } - public String asJSON() { - return getRawResponse(); + @Override + protected String getRawResponse() { + return new RequestExecutor(requestSettings).getResponse(ApiVariant.PRO); } - public String asXML() { - requestSettings.setResponseType(ResponseType.XML); - return getRawResponse(); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + @Override + protected Class getValueType() { + return FourDaysHourlyForecastModel.class; } } 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 index d93965e..f98ac80 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,21 +22,22 @@ package com.github.prominence.openweathermap.api.request.forecast.hourly; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; -public class FourDaysHourlyForecastRequester { - private final RequestSettings requestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; +public class FourDaysHourlyForecastRequester extends GenericRequester { public FourDaysHourlyForecastRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(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())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, String.valueOf(coordinates.getLongitude())); return new FourDaysHourlyForecastRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericAsyncRequestTerminator.java new file mode 100644 index 0000000..aeff55a --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericAsyncRequestTerminator.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import lombok.NonNull; + +import java.util.concurrent.CompletableFuture; + +public class GenericAsyncRequestTerminator { + protected final GenericRequestTerminator sync; + + public GenericAsyncRequestTerminator(@NonNull GenericRequestTerminator sync) { + this.sync = sync; + } + + public CompletableFuture asJava() { + return CompletableFuture.supplyAsync(sync::asJava); + } + + public CompletableFuture asJSON(final UnitSystem unitSystem) { + return CompletableFuture.supplyAsync(() -> sync.asJSON(unitSystem)); + } + + public CompletableFuture asXML(final UnitSystem unitSystem) { + return CompletableFuture.supplyAsync(() -> sync.asXML(unitSystem)); + } + + public CompletableFuture asHTML(final UnitSystem unitSystem) { + return CompletableFuture.supplyAsync(() -> sync.asHTML(unitSystem)); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericListAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericListAsyncRequestTerminator.java new file mode 100644 index 0000000..6c8ea66 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericListAsyncRequestTerminator.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import lombok.NonNull; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public class GenericListAsyncRequestTerminator { + protected final GenericListRequestTerminator sync; + + public GenericListAsyncRequestTerminator(@NonNull GenericListRequestTerminator sync) { + this.sync = sync; + } + + public CompletableFuture> asJava() { + return CompletableFuture.supplyAsync(sync::asJava); + } + + public CompletableFuture asJSON(final UnitSystem unitSystem) { + return CompletableFuture.supplyAsync(() -> sync.asJSON(unitSystem)); + } + + public CompletableFuture asXML(final UnitSystem unitSystem) { + return CompletableFuture.supplyAsync(() -> sync.asXML(unitSystem)); + } + + public CompletableFuture asHTML(final UnitSystem unitSystem) { + return CompletableFuture.supplyAsync(() -> sync.asHTML(unitSystem)); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericListRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericListRequestTerminator.java new file mode 100644 index 0000000..73b5423 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericListRequestTerminator.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.type.CollectionType; +import com.github.prominence.openweathermap.api.enums.ResponseType; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.exception.ApiPayloadParseException; +import com.github.prominence.openweathermap.api.request.RequestSettings; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Generic implementation of the request termination logic. + * + * @param Type of the response object + * @param Type of the internal type we map the raw response to + */ +public abstract class GenericListRequestTerminator { + protected final RequestSettings requestSettings; + + public GenericListRequestTerminator(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + public List asJava() { + requestSettings.setUnitSystem(UnitSystem.STANDARD); + requestSettings.setResponseType(ResponseType.JSON); + return castInternalToModel(mapToObject(getRawResponse())); + } + + public String asJSON(final UnitSystem unitSystem) { + requestSettings.setUnitSystem(Optional.ofNullable(unitSystem).orElse(UnitSystem.STANDARD)); + requestSettings.setResponseType(ResponseType.JSON); + return getRawResponse(); + } + + public String asXML(final UnitSystem unitSystem) { + requestSettings.setUnitSystem(Optional.ofNullable(unitSystem).orElse(UnitSystem.STANDARD)); + requestSettings.setResponseType(ResponseType.XML); + return getRawResponse(); + } + + public String asHTML(final UnitSystem unitSystem) { + requestSettings.setUnitSystem(Optional.ofNullable(unitSystem).orElse(UnitSystem.STANDARD)); + requestSettings.setResponseType(ResponseType.HTML); + return getRawResponse(); + } + + protected List castInternalToModel(List internal) { + return internal.stream() + .map(getValueType()::cast) + .collect(Collectors.toList()); + } + + protected abstract String getRawResponse(); + + protected abstract Class getValueType(); + + protected abstract Class getInnerType(); + + private List mapToObject(String json) { + try { + final ObjectReader objectReader = requestSettings.getApiConfiguration().getObjectReader(); + final CollectionType listType = objectReader.getTypeFactory().constructCollectionType(ArrayList.class, getInnerType()); + return objectReader.forType(listType).readValue(json); + } catch (IOException e) { + throw new ApiPayloadParseException("Cannot parse Weather response", e); + } + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericRequestTerminator.java new file mode 100644 index 0000000..644b3e6 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericRequestTerminator.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.core.net.RequestExecutor; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import com.github.prominence.openweathermap.api.enums.ResponseType; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.exception.ApiPayloadParseException; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import lombok.extern.slf4j.Slf4j; + +import java.util.Optional; + +/** + * Generic implementation of the request termination logic. + * + * @param Type of the response object + * @param Type of the internal type we map the raw response to + */ +@Slf4j +public abstract class GenericRequestTerminator { + protected final RequestSettings requestSettings; + + public GenericRequestTerminator(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + public T asJava() { + requestSettings.setUnitSystem(UnitSystem.STANDARD); + requestSettings.setResponseType(ResponseType.JSON); + return mapToObject(getRawResponse()); + } + + public String asJSON(final UnitSystem unitSystem) { + requestSettings.setUnitSystem(Optional.ofNullable(unitSystem).orElse(UnitSystem.STANDARD)); + requestSettings.setResponseType(ResponseType.JSON); + return getRawResponse(); + } + + public String asXML(final UnitSystem unitSystem) { + requestSettings.setUnitSystem(Optional.ofNullable(unitSystem).orElse(UnitSystem.STANDARD)); + requestSettings.setResponseType(ResponseType.XML); + return getRawResponse(); + } + + public String asHTML(final UnitSystem unitSystem) { + requestSettings.setUnitSystem(Optional.ofNullable(unitSystem).orElse(UnitSystem.STANDARD)); + requestSettings.setResponseType(ResponseType.HTML); + return getRawResponse(); + } + + protected String getRawResponse() { + return new RequestExecutor(requestSettings).getResponse(ApiVariant.BASE); + } + + private I mapToObject(String json) { + try { + return requestSettings.getApiConfiguration().getObjectReader().readValue(json, getValueType()); + } catch (Exception e) { + log.error("Failed to map JSON: {}", json, e); + throw new ApiPayloadParseException("Cannot parse Weather response", e); + } + } + + protected abstract Class getValueType(); +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericRequester.java new file mode 100644 index 0000000..b1321c1 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/GenericRequester.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.conf.TimeoutSettings; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import lombok.NonNull; + +public abstract class GenericRequester> { + + protected final RequestSettings requestSettings; + + public GenericRequester(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + @SuppressWarnings("unchecked") + public T withTimeoutSettings(@NonNull TimeoutSettings timeoutSettings) { + requestSettings.setTimeoutSettings(timeoutSettings); + return (T) this; + } + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/HtmlApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/HtmlApiTerminator.java new file mode 100644 index 0000000..1dd0106 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/HtmlApiTerminator.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; + +public interface HtmlApiTerminator { + + /** + * Terminates the chain of request configuration calls by setting the final parameter and fetches the response as HTML text. + * + * @param unitSystem The final parameter, defining whether we want to use standard, metric or imperial measurement units. + * Uses {@link UnitSystem#STANDARD} when null. + * @return HTML + */ + String asHTML(UnitSystem unitSystem); + + /** + * Shorthand to {@link #asHTML(UnitSystem) using {@link UnitSystem#STANDARD}}. + * @return HTML + */ + default String asHTML() { + return asHTML(UnitSystem.STANDARD); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/HtmlAsyncApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/HtmlAsyncApiTerminator.java new file mode 100644 index 0000000..a3afc39 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/HtmlAsyncApiTerminator.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; + +import java.util.concurrent.CompletableFuture; + +public interface HtmlAsyncApiTerminator { + + /** + * Terminates the chain of request configuration calls by setting the final parameter and fetches the response as HTML text. + * + * @param unitSystem The final parameter, defining whether we want to use standard, metric or imperial measurement units. + * Uses {@link UnitSystem#STANDARD} when null. + * @return HTML + */ + CompletableFuture asHTML(UnitSystem unitSystem); + + /** + * Shorthand to {@link #asHTML(UnitSystem) using {@link UnitSystem#STANDARD}}. + * @return HTML + */ + default CompletableFuture asHTML() { + return asHTML(UnitSystem.STANDARD); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonApiTerminator.java new file mode 100644 index 0000000..c9e1692 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonApiTerminator.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; + +public interface JsonApiTerminator { + + /** + * Terminates the chain of request configuration calls and fetches the response as JSON, then maps it to Java Objects. + * + * @return deserialized the forecast data + */ + T asJava(); + + /** + * Terminates the chain of request configuration calls by setting the final parameter and fetches the response as JSON text. + * + * @param unitSystem The final parameter, defining whether we want to use standard, metric or imperial measurement units. + * Uses {@link UnitSystem#STANDARD} when null. + * @return JSON + */ + String asJSON(UnitSystem unitSystem); + + /** + * Shorthand to {@link #asJSON(UnitSystem) using {@link UnitSystem#STANDARD}}. + * @return JSON + */ + default String asJSON() { + return asJSON(UnitSystem.STANDARD); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonAsyncApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonAsyncApiTerminator.java new file mode 100644 index 0000000..61fc05f --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonAsyncApiTerminator.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; + +import java.util.concurrent.CompletableFuture; + +public interface JsonAsyncApiTerminator { + + /** + * Terminates the chain of request configuration calls and fetches the response as JSON, then maps it to Java Objects. + * + * @return deserialized the forecast data + */ + CompletableFuture asJava(); + + + /** + * Terminates the chain of request configuration calls by setting the final parameter and fetches the response as JSON text. + * + * @param unitSystem The final parameter, defining whether we want to use standard, metric or imperial measurement units. + * Uses {@link UnitSystem#STANDARD} when null. + * @return JSON + */ + CompletableFuture asJSON(UnitSystem unitSystem); + + /** + * Shorthand to {@link #asJSON(UnitSystem) using {@link UnitSystem#STANDARD}}. + * @return JSON + */ + default CompletableFuture asJSON() { + return asJSON(UnitSystem.STANDARD); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonXmlApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonXmlApiTerminator.java new file mode 100644 index 0000000..dbbed6e --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonXmlApiTerminator.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021-present 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.generic; + +public interface JsonXmlApiTerminator extends JsonApiTerminator, XmlApiTerminator { + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonXmlAsyncApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonXmlAsyncApiTerminator.java new file mode 100644 index 0000000..7fcfa55 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/JsonXmlAsyncApiTerminator.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021-present 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.generic; + +public interface JsonXmlAsyncApiTerminator extends JsonAsyncApiTerminator, XmlAsyncApiTerminator { + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/UniversalFormatApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/UniversalFormatApiTerminator.java new file mode 100644 index 0000000..e2a5a91 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/UniversalFormatApiTerminator.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021-present 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.generic; + +public interface UniversalFormatApiTerminator extends JsonApiTerminator, XmlApiTerminator, HtmlApiTerminator { + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/UniversalFormatAsyncApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/UniversalFormatAsyncApiTerminator.java new file mode 100644 index 0000000..8e2e439 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/UniversalFormatAsyncApiTerminator.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021-present 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.generic; + +public interface UniversalFormatAsyncApiTerminator extends JsonAsyncApiTerminator, XmlAsyncApiTerminator, HtmlAsyncApiTerminator { + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/XmlApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/XmlApiTerminator.java new file mode 100644 index 0000000..8af1475 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/XmlApiTerminator.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; + +public interface XmlApiTerminator { + + /** + * Terminates the chain of request configuration calls by setting the final parameter and fetches the response as XML text. + * + * @param unitSystem The final parameter, defining whether we want to use standard, metric or imperial measurement units. + * Uses {@link UnitSystem#STANDARD} when null. + * @return XML + */ + String asXML(UnitSystem unitSystem); + + /** + * Shorthand to {@link #asXML(UnitSystem) using {@link UnitSystem#STANDARD}}. + * @return XML + */ + default String asXML() { + return asXML(UnitSystem.STANDARD); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/generic/XmlAsyncApiTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/generic/XmlAsyncApiTerminator.java new file mode 100644 index 0000000..d03c669 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/generic/XmlAsyncApiTerminator.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.enums.UnitSystem; + +import java.util.concurrent.CompletableFuture; + +public interface XmlAsyncApiTerminator { + + /** + * Terminates the chain of request configuration calls by setting the final parameter and fetches the response as XML text. + * + * @param unitSystem The final parameter, defining whether we want to use standard, metric or imperial measurement units. + * Uses {@link UnitSystem#STANDARD} when null. + * @return XML + */ + CompletableFuture asXML(UnitSystem unitSystem); + + /** + * Shorthand to {@link #asXML(UnitSystem) using {@link UnitSystem#STANDARD}}. + * @return XML + */ + default CompletableFuture asXML() { + return asXML(UnitSystem.STANDARD); + } +} 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 index ffbe819..b858773 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,14 +23,14 @@ package com.github.prominence.openweathermap.api.request.geocoding; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; 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 class GeocodingRequester extends GenericRequester { public GeocodingRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); this.requestSettings.appendToURL("geo/1.0"); } 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/DirectGeocodingAsyncRequestTerminator.java similarity index 56% rename from src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestAsyncTerminator.java rename to src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingAsyncRequestTerminator.java index b346738..6dabc44 100644 --- 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/DirectGeocodingAsyncRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,18 @@ package com.github.prominence.openweathermap.api.request.geocoding.direct; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; +import com.github.prominence.openweathermap.api.model.geocoding.Geocoding; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericListAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; +import java.util.List; -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 new RequestExecutor(requestSettings).getResponse(); +public class DirectGeocodingAsyncRequestTerminator + extends GenericListAsyncRequestTerminator + implements JsonAsyncApiTerminator> { + DirectGeocodingAsyncRequestTerminator(RequestSettings requestSettings) { + super(new DirectGeocodingRequestTerminator(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 index 5ddb9c6..f637c25 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,29 +22,30 @@ package com.github.prominence.openweathermap.api.request.geocoding.direct; +import com.github.prominence.openweathermap.api.model.geocoding.Geocoding; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; -import java.util.function.Function; +import java.util.List; -public class DirectGeocodingRequestCustomizer { +public class DirectGeocodingRequestCustomizer { private final RequestSettings requestSettings; - private final Function mapperFunction; - DirectGeocodingRequestCustomizer(RequestSettings requestSettings, Function mapperFunction) { + DirectGeocodingRequestCustomizer(RequestSettings requestSettings) { this.requestSettings = requestSettings; - this.mapperFunction = mapperFunction; } - public DirectGeocodingRequestCustomizer limit(int locationsNumber) { + public DirectGeocodingRequestCustomizer limit(int locationsNumber) { requestSettings.putRequestParameter("limit", Integer.toString(locationsNumber)); return this; } - public DirectGeocodingRequestTerminator retrieve() { - return new DirectGeocodingRequestTerminator(requestSettings, mapperFunction); + public JsonApiTerminator> retrieve() { + return new DirectGeocodingRequestTerminator(requestSettings); } - public DirectGeocodingRequestAsyncTerminator retrieveAsync() { - return new DirectGeocodingRequestAsyncTerminator(requestSettings, mapperFunction); + public JsonAsyncApiTerminator> retrieveAsync() { + return new DirectGeocodingAsyncRequestTerminator(requestSettings); } } 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 index e74e052..b0d6375 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,28 +23,46 @@ package com.github.prominence.openweathermap.api.request.geocoding.direct; import com.github.prominence.openweathermap.api.core.net.RequestExecutor; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.geocoding.Geocoding; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericListRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; -import java.util.function.Function; +import java.util.List; -public class DirectGeocodingRequestTerminator { - private final RequestSettings requestSettings; - private final Function mapperFunction; - - DirectGeocodingRequestTerminator(RequestSettings requestSettings, Function mapperFunction) { - this.requestSettings = requestSettings; - this.mapperFunction = mapperFunction; +public class DirectGeocodingRequestTerminator + extends GenericListRequestTerminator + implements JsonApiTerminator> { + DirectGeocodingRequestTerminator(RequestSettings requestSettings) { + super(requestSettings); } - public R asJava() { - return mapperFunction.apply(asJSON()); + protected String getRawResponse() { + return new RequestExecutor(requestSettings).getResponse(ApiVariant.BASE); } - public String asJSON() { - return getRawResponse(); + @Override + public String asXML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("XML format not supported for this API."); } - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); + } + + @Override + protected Class getValueType() { + return Geocoding.class; + } + + @Override + protected Class getInnerType() { + return GeocodingModel.class; } } 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 index 4285c7b..025bdbd 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,12 +22,10 @@ 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; +import static com.github.prominence.openweathermap.api.request.RequestSettings.QUERY_VALUE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.ZIP_PARAM; public class DirectGeocodingRequester { private final RequestSettings requestSettings; @@ -36,15 +34,15 @@ public class DirectGeocodingRequester { this.requestSettings = requestSettings; } - public DirectGeocodingRequestCustomizer> byLocationName(String cityName, String stateCode, String countryCode) { + 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)); + requestSettings.putRequestParameter(QUERY_VALUE_PARAM, cityName + "," + stateCode + "," + countryCode); + return new DirectGeocodingRequestCustomizer(requestSettings); } - public DirectGeocodingRequestCustomizer byZipCode(String zipCode, String countryCode) { + public ZipCodeGeocodingRequestCustomizer byZipCode(String zipCode, String countryCode) { requestSettings.appendToURL("zip"); - requestSettings.putRequestParameter("zip", zipCode + "," + countryCode); - return new DirectGeocodingRequestCustomizer<>(requestSettings, (String json) -> new GeocodingResponseMapper().mapZipCodeGeocodingResponse(json)); + requestSettings.putRequestParameter(ZIP_PARAM, zipCode + "," + countryCode); + return new ZipCodeGeocodingRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingAsyncRequestTerminator.java new file mode 100644 index 0000000..803429f --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingAsyncRequestTerminator.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-present 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.model.geocoding.ZipCodeGeocoding; +import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; + +public class ZipCodeGeocodingAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements JsonAsyncApiTerminator { + ZipCodeGeocodingAsyncRequestTerminator(RequestSettings requestSettings) { + super(new ZipCodeGeocodingRequestTerminator(requestSettings)); + } +} 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/direct/ZipCodeGeocodingRequestCustomizer.java similarity index 63% rename from src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestAsyncTerminator.java rename to src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingRequestCustomizer.java index 7f0b7ff..eb2512a 100644 --- 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/direct/ZipCodeGeocodingRequestCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,32 +20,30 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.request.geocoding.reverse; +package com.github.prominence.openweathermap.api.request.geocoding.direct; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -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.ZipCodeGeocoding; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -public class ReverseGeocodingRequestAsyncTerminator { +public class ZipCodeGeocodingRequestCustomizer { private final RequestSettings requestSettings; - ReverseGeocodingRequestAsyncTerminator(RequestSettings requestSettings) { + ZipCodeGeocodingRequestCustomizer(RequestSettings requestSettings) { this.requestSettings = requestSettings; } - public CompletableFuture> asJava() { - return CompletableFuture.supplyAsync(() -> new GeocodingResponseMapper().mapGeocodingResponse(getRawResponse())); + public ZipCodeGeocodingRequestCustomizer limit(int locationsNumber) { + requestSettings.putRequestParameter("limit", Integer.toString(locationsNumber)); + return this; } - public CompletableFuture asJSON() { - return CompletableFuture.supplyAsync(this::getRawResponse); + public JsonApiTerminator retrieve() { + return new ZipCodeGeocodingRequestTerminator(requestSettings); } - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + public JsonAsyncApiTerminator retrieveAsync() { + return new ZipCodeGeocodingAsyncRequestTerminator(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingRequestTerminator.java new file mode 100644 index 0000000..84d6724 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingRequestTerminator.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021-present 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.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocoding; +import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; + +public class ZipCodeGeocodingRequestTerminator + extends GenericRequestTerminator + implements JsonApiTerminator { + ZipCodeGeocodingRequestTerminator(RequestSettings requestSettings) { + super(requestSettings); + } + + @Override + public String asXML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("XML format not supported for this API."); + } + + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); + } + + @Override + protected Class getValueType() { + return ZipCodeGeocodingModel.class; + } + +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingAsyncRequestTerminator.java new file mode 100644 index 0000000..876bdcd --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingAsyncRequestTerminator.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-present 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.geocoding.Geocoding; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericListAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; + +import java.util.List; + +public class ReverseGeocodingAsyncRequestTerminator + extends GenericListAsyncRequestTerminator + implements JsonAsyncApiTerminator> { + ReverseGeocodingAsyncRequestTerminator(RequestSettings requestSettings) { + super(new ReverseGeocodingRequestTerminator(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 index acd240b..5e8b942 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,7 +22,12 @@ package com.github.prominence.openweathermap.api.request.geocoding.reverse; +import com.github.prominence.openweathermap.api.model.geocoding.Geocoding; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; + +import java.util.List; public class ReverseGeocodingRequestCustomizer { private final RequestSettings requestSettings; @@ -36,11 +41,11 @@ public class ReverseGeocodingRequestCustomizer { return this; } - public ReverseGeocodingRequestTerminator retrieve() { + public JsonApiTerminator> retrieve() { return new ReverseGeocodingRequestTerminator(requestSettings); } - public ReverseGeocodingRequestAsyncTerminator retrieveAsync() { - return new ReverseGeocodingRequestAsyncTerminator(requestSettings); + public JsonAsyncApiTerminator> retrieveAsync() { + return new ReverseGeocodingAsyncRequestTerminator(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 index e692a24..5412ada 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,28 +23,46 @@ package com.github.prominence.openweathermap.api.request.geocoding.reverse; import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.mapper.GeocodingResponseMapper; -import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.geocoding.Geocoding; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericListRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; import java.util.List; -public class ReverseGeocodingRequestTerminator { - private final RequestSettings requestSettings; - +public class ReverseGeocodingRequestTerminator + extends GenericListRequestTerminator + implements JsonApiTerminator> { ReverseGeocodingRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); } - public List asJava() { - return new GeocodingResponseMapper().mapGeocodingResponse(asJSON()); + protected String getRawResponse() { + return new RequestExecutor(requestSettings).getResponse(ApiVariant.BASE); } - public String asJSON() { - return getRawResponse(); + @Override + public String asXML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("XML format not supported for this API."); } - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); + } + + @Override + protected Class getValueType() { + return Geocoding.class; + } + + @Override + protected Class getInnerType() { + return GeocodingModel.class; } } 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 index 2db7d9c..1a8ef6a 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,9 +22,12 @@ package com.github.prominence.openweathermap.api.request.geocoding.reverse; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; + public class ReverseGeocodingRequester { private final RequestSettings requestSettings; @@ -34,8 +37,8 @@ public class ReverseGeocodingRequester { } public ReverseGeocodingRequestCustomizer byCoordinates(Coordinates coordinates) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, 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 007bb53..edc7d8c 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,14 +23,14 @@ package com.github.prominence.openweathermap.api.request.onecall; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; import com.github.prominence.openweathermap.api.request.onecall.current.OneCallCurrentWeatherRequester; import com.github.prominence.openweathermap.api.request.onecall.historical.OneCallHistoricalWeatherRequester; /** * The type One call weather requester. */ -public class OneCallWeatherRequester { - private final RequestSettings requestSettings; +public class OneCallWeatherRequester extends GenericRequester { /** * Instantiates a new One call weather requester. @@ -38,8 +38,8 @@ public class OneCallWeatherRequester { * @param requestSettings request settings object. */ public OneCallWeatherRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - this.requestSettings.appendToURL("data/2.5/onecall"); + super(requestSettings); + this.requestSettings.appendToURL("data/3.0/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 30edf24..03c06b5 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,18 +22,18 @@ package com.github.prominence.openweathermap.api.request.onecall.current; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.mapper.OneCallWeatherResponseMapper; -import com.github.prominence.openweathermap.api.model.onecall.current.CurrentWeatherData; +import com.github.prominence.openweathermap.api.model.onecall.current.OneCallCurrentForecast; +import com.github.prominence.openweathermap.api.model.onecall.current.OneCallCurrentForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; - -import java.util.concurrent.CompletableFuture; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; /** * The type One call current weather async request terminator. */ -class OneCallCurrentWeatherAsyncRequestTerminator { - private final RequestSettings requestSettings; +class OneCallCurrentWeatherAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements JsonAsyncApiTerminator { /** * Instantiates a new One call current weather async request terminator. @@ -41,18 +41,6 @@ class OneCallCurrentWeatherAsyncRequestTerminator { * @param requestSettings request settings object. */ OneCallCurrentWeatherAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - } - - public CompletableFuture asJava() { - return CompletableFuture.supplyAsync(() -> new OneCallWeatherResponseMapper(requestSettings.getUnitSystem()).mapToCurrent(getRawResponse())); - } - - public CompletableFuture asJSON() { - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + super(new OneCallCurrentWeatherRequestTerminator(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 ccccaf2..b64fd80 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -24,8 +24,10 @@ package com.github.prominence.openweathermap.api.request.onecall.current; 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.model.onecall.current.OneCallCurrentForecast; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -50,11 +52,6 @@ class OneCallCurrentWeatherRequestCustomizer { return this; } - public OneCallCurrentWeatherRequestCustomizer unitSystem(UnitSystem unitSystem) { - this.requestSettings.setUnitSystem(unitSystem); - return this; - } - public OneCallCurrentWeatherRequestCustomizer exclude(OneCallResultOptions... excludeOptions) { if (excludeOptions != null && excludeOptions.length > 0) { requestSettings.putRequestParameter("exclude", Stream.of(excludeOptions).map(OneCallResultOptions::getValue).collect(Collectors.joining(","))); @@ -64,11 +61,11 @@ class OneCallCurrentWeatherRequestCustomizer { return this; } - public OneCallCurrentWeatherRequestTerminator retrieve() { + public JsonApiTerminator retrieve() { return new OneCallCurrentWeatherRequestTerminator(requestSettings); } - public OneCallCurrentWeatherAsyncRequestTerminator retrieveAsync() { + public JsonAsyncApiTerminator retrieveAsync() { return new OneCallCurrentWeatherAsyncRequestTerminator(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 60d8df9..cd2f7f3 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,16 +22,19 @@ package com.github.prominence.openweathermap.api.request.onecall.current; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.mapper.OneCallWeatherResponseMapper; -import com.github.prominence.openweathermap.api.model.onecall.current.CurrentWeatherData; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.onecall.current.OneCallCurrentForecast; +import com.github.prominence.openweathermap.api.model.onecall.current.OneCallCurrentForecastModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; /** * The type One call current weather request terminator. */ -class OneCallCurrentWeatherRequestTerminator { - private final RequestSettings requestSettings; +class OneCallCurrentWeatherRequestTerminator + extends GenericRequestTerminator + implements JsonApiTerminator { /** * Instantiates a new One call current weather request terminator. @@ -39,18 +42,24 @@ class OneCallCurrentWeatherRequestTerminator { * @param requestSettings request settings object. */ OneCallCurrentWeatherRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); } - public CurrentWeatherData asJava() { - return new OneCallWeatherResponseMapper(requestSettings.getUnitSystem()).mapToCurrent(getRawResponse()); + @Override + public String asXML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("XML format not supported for this API."); } - public String asJSON() { - return getRawResponse(); + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); } - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + @Override + protected Class getValueType() { + return OneCallCurrentForecastModel.class; } + } 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 621a487..03e743a 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,9 +22,12 @@ package com.github.prominence.openweathermap.api.request.onecall.current; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; + /** * The type One call current weather requester. */ @@ -41,8 +44,8 @@ public class OneCallCurrentWeatherRequester { } public OneCallCurrentWeatherRequestCustomizer byCoordinates(Coordinates coordinates) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, 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 0a5041e..485b0e6 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,18 +22,18 @@ package com.github.prominence.openweathermap.api.request.onecall.historical; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.mapper.OneCallWeatherResponseMapper; -import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeatherData; +import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeather; +import com.github.prominence.openweathermap.api.model.onecall.historical.OneCallHistoricalWeather; import com.github.prominence.openweathermap.api.request.RequestSettings; - -import java.util.concurrent.CompletableFuture; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; /** * The type One call historical weather async request terminator. */ -class OneCallHistoricalWeatherAsyncRequestTerminator { - private final RequestSettings requestSettings; +class OneCallHistoricalWeatherAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements JsonAsyncApiTerminator { /** * Instantiates a new One call historical weather async request terminator. @@ -41,18 +41,7 @@ class OneCallHistoricalWeatherAsyncRequestTerminator { * @param requestSettings request settings object. */ public OneCallHistoricalWeatherAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(new OneCallHistoricalWeatherRequestTerminator(requestSettings)); } - public CompletableFuture asJava() { - return CompletableFuture.supplyAsync(() -> new OneCallWeatherResponseMapper(requestSettings.getUnitSystem()).mapToHistorical(getRawResponse())); - } - - public CompletableFuture asJSON() { - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); - } } 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 b34b744..2476ea5 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,8 +23,10 @@ package com.github.prominence.openweathermap.api.request.onecall.historical; import com.github.prominence.openweathermap.api.enums.Language; -import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.onecall.historical.OneCallHistoricalWeather; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonAsyncApiTerminator; /** * The type One call historical weather request customizer. @@ -46,16 +48,11 @@ class OneCallHistoricalWeatherRequestCustomizer { return this; } - public OneCallHistoricalWeatherRequestCustomizer unitSystem(UnitSystem unitSystem) { - requestSettings.setUnitSystem(unitSystem); - return this; - } - - public OneCallHistoricalWeatherRequestTerminator retrieve() { + public JsonApiTerminator retrieve() { return new OneCallHistoricalWeatherRequestTerminator(requestSettings); } - public OneCallHistoricalWeatherAsyncRequestTerminator retrieveAsync() { + public JsonAsyncApiTerminator retrieveAsync() { return new OneCallHistoricalWeatherAsyncRequestTerminator(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 45381d8..7a2cbc0 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,35 +22,44 @@ package com.github.prominence.openweathermap.api.request.onecall.historical; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.mapper.OneCallWeatherResponseMapper; -import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeatherData; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeather; +import com.github.prominence.openweathermap.api.model.onecall.historical.OneCallHistoricalWeather; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.JsonApiTerminator; /** * The type One call historical weather request terminator. */ -class OneCallHistoricalWeatherRequestTerminator { - private final RequestSettings requestSettings; +class OneCallHistoricalWeatherRequestTerminator + extends GenericRequestTerminator + implements JsonApiTerminator { /** * Instantiates a new One call historical weather request terminator. * * @param requestSettings request settings object. */ - public OneCallHistoricalWeatherRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + OneCallHistoricalWeatherRequestTerminator(RequestSettings requestSettings) { + super(requestSettings); } - public HistoricalWeatherData asJava() { - return new OneCallWeatherResponseMapper(requestSettings.getUnitSystem()).mapToHistorical(getRawResponse()); + @Override + public String asXML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("XML format not supported for this API."); } - public String asJSON() { - return getRawResponse(); + @Override + public String asHTML(final UnitSystem unitSystem) { + //Method meant to be hidden as only JsonApiTerminator is exposed + throw new UnsupportedOperationException("HTML format not supported for this API."); } - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + @Override + protected Class getValueType() { + return HistoricalWeather.class; } + } 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 3d04dc3..2124ff7 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,9 +22,13 @@ package com.github.prominence.openweathermap.api.request.onecall.historical; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.DATE_TIME_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; + /** * The type One call historical weather requester. */ @@ -42,9 +46,9 @@ public class OneCallHistoricalWeatherRequester { } 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)); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(DATE_TIME_PARAM, Long.toString(unixTime)); return new OneCallHistoricalWeatherRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/CurrentSolarRadiationRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/CurrentSolarRadiationRequester.java index b45fc1f..117230c 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/CurrentSolarRadiationRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/CurrentSolarRadiationRequester.java @@ -1,8 +1,33 @@ +/* + * Copyright (c) 2021-present 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.radiation; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; + public class CurrentSolarRadiationRequester { private final RequestSettings requestSettings; @@ -11,8 +36,8 @@ public class CurrentSolarRadiationRequester { } public SolarRadiationRequestCustomizer byCoordinates(Coordinates coordinates) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, String.valueOf(coordinates.getLongitude())); return new SolarRadiationRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/ForecastSolarRadiationRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/ForecastSolarRadiationRequester.java index e7c37d8..2cdadb5 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/ForecastSolarRadiationRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/ForecastSolarRadiationRequester.java @@ -1,8 +1,33 @@ +/* + * Copyright (c) 2021-present 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.radiation; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; + public class ForecastSolarRadiationRequester { private final RequestSettings requestSettings; @@ -11,8 +36,8 @@ public class ForecastSolarRadiationRequester { } public SolarRadiationRequestCustomizer byCoordinates(Coordinates coordinates) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, String.valueOf(coordinates.getLongitude())); return new SolarRadiationRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/HistoricalSolarRadiationRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/HistoricalSolarRadiationRequester.java index e01412f..bf6898c 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/HistoricalSolarRadiationRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/HistoricalSolarRadiationRequester.java @@ -1,10 +1,34 @@ +/* + * Copyright (c) 2021-present 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.radiation; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; -import java.time.LocalDateTime; -import java.time.ZoneId; +import static com.github.prominence.openweathermap.api.request.RequestSettings.END_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.START_PARAM; public class HistoricalSolarRadiationRequester { private final RequestSettings requestSettings; @@ -13,11 +37,11 @@ public class HistoricalSolarRadiationRequester { this.requestSettings = requestSettings; } - public SolarRadiationRequestCustomizer byCoordinates(Coordinates coordinates, LocalDateTime startDate, LocalDateTime endDate) { - requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude())); - requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude())); - requestSettings.putRequestParameter("start", String.valueOf(startDate.atZone(ZoneId.systemDefault()).toEpochSecond())); - requestSettings.putRequestParameter("end", String.valueOf(endDate.atZone(ZoneId.systemDefault()).toEpochSecond())); + public SolarRadiationRequestCustomizer byCoordinateAndPeriod(Coordinates coordinates, int startUnixTime, int endUnixTime) { + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, String.valueOf(coordinates.getLongitude())); + requestSettings.putRequestParameter(START_PARAM, String.valueOf(startUnixTime)); + requestSettings.putRequestParameter(END_PARAM, String.valueOf(endUnixTime)); return new SolarRadiationRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationAsyncRequestTerminator.java index 5210338..74c884f 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationAsyncRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,29 +22,16 @@ package com.github.prominence.openweathermap.api.request.radiation; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.mapper.SolarRadiationResponseMapper; import com.github.prominence.openweathermap.api.model.radiation.SolarRadiation; +import com.github.prominence.openweathermap.api.model.radiation.SolarRadiationModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatAsyncApiTerminator; -import java.util.concurrent.CompletableFuture; - -class SolarRadiationAsyncRequestTerminator { - private final RequestSettings requestSettings; - +class SolarRadiationAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements UniversalFormatAsyncApiTerminator { public SolarRadiationAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - } - - public CompletableFuture asJava() { - return CompletableFuture.supplyAsync(() -> new SolarRadiationResponseMapper().mapToObject(getRawResponse())); - } - - public CompletableFuture asJSON() { - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + super(new SolarRadiationRequestTerminator(requestSettings)); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestCustomizer.java index aafb978..4e353ad 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestCustomizer.java @@ -1,6 +1,31 @@ +/* + * Copyright (c) 2021-present 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.radiation; +import com.github.prominence.openweathermap.api.model.radiation.SolarRadiation; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatAsyncApiTerminator; public class SolarRadiationRequestCustomizer { private final RequestSettings requestSettings; @@ -9,11 +34,11 @@ public class SolarRadiationRequestCustomizer { this.requestSettings = requestSettings; } - public SolarRadiationRequestTerminator retrieve() { + public UniversalFormatApiTerminator retrieve() { return new SolarRadiationRequestTerminator(requestSettings); } - public SolarRadiationAsyncRequestTerminator retrieveAsync() { + public UniversalFormatAsyncApiTerminator retrieveAsync() { return new SolarRadiationAsyncRequestTerminator(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestTerminator.java index ab28ce5..adfd584 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,27 +22,23 @@ package com.github.prominence.openweathermap.api.request.radiation; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.mapper.SolarRadiationResponseMapper; import com.github.prominence.openweathermap.api.model.radiation.SolarRadiation; +import com.github.prominence.openweathermap.api.model.radiation.SolarRadiationModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatApiTerminator; -class SolarRadiationRequestTerminator { - private final RequestSettings requestSettings; +class SolarRadiationRequestTerminator + extends GenericRequestTerminator + implements UniversalFormatApiTerminator { public SolarRadiationRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); } - public SolarRadiation asJava() { - return new SolarRadiationResponseMapper().mapToObject(getRawResponse()); + @Override + protected Class getValueType() { + return SolarRadiationModel.class; } - public String asJSON() { - return getRawResponse(); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequester.java index d47652d..f5eaaa9 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequester.java @@ -1,12 +1,34 @@ +/* + * Copyright (c) 2021-present 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.radiation; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; -public class SolarRadiationRequester { - private final RequestSettings requestSettings; +public class SolarRadiationRequester extends GenericRequester { public SolarRadiationRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); this.requestSettings.appendToURL("data/2.5/solar_radiation"); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskAsyncRequestTerminator.java index 55bb327..390e512 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskAsyncRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,20 +22,20 @@ package com.github.prominence.openweathermap.api.request.roadrisk; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.RoadRiskResponseMapper; -import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskRecord; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRisk; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericListAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatAsyncApiTerminator; import java.util.List; -import java.util.concurrent.CompletableFuture; /** * The type Single result current weather async request terminator. */ -public class RoadRiskAsyncRequestTerminator { - private final RequestSettings requestSettings; +public class RoadRiskAsyncRequestTerminator + extends GenericListAsyncRequestTerminator + implements UniversalFormatAsyncApiTerminator> { /** * Instantiates a new Single result current weather async request terminator. @@ -43,28 +43,7 @@ public class RoadRiskAsyncRequestTerminator { * @param requestSettings request settings object. */ RoadRiskAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(new RoadRiskRequestTerminator(requestSettings)); } - public CompletableFuture> asJava() { - return CompletableFuture.supplyAsync(() -> new RoadRiskResponseMapper().mapToObjects(getRawResponse())); - } - - public CompletableFuture asJSON() { - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - public CompletableFuture asXML() { - requestSettings.setResponseType(ResponseType.XML); - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - public CompletableFuture asHTML() { - requestSettings.setResponseType(ResponseType.HTML); - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestCustomizer.java index 8bfca40..8bcc436 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestCustomizer.java @@ -1,6 +1,33 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRisk; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatAsyncApiTerminator; + +import java.util.List; public class RoadRiskRequestCustomizer { private final RequestSettings requestSettings; @@ -9,11 +36,11 @@ public class RoadRiskRequestCustomizer { this.requestSettings = requestSettings; } - public RoadRiskRequestTerminator retrieve() { + public UniversalFormatApiTerminator> retrieve() { return new RoadRiskRequestTerminator(requestSettings); } - public RoadRiskAsyncRequestTerminator retrieveAsync() { + public UniversalFormatAsyncApiTerminator> retrieveAsync() { return new RoadRiskAsyncRequestTerminator(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestTerminator.java index 2394c63..ff251cb 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,39 +23,34 @@ package com.github.prominence.openweathermap.api.request.roadrisk; import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.RoadRiskResponseMapper; -import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskRecord; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRisk; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericListRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatApiTerminator; import java.util.List; -public class RoadRiskRequestTerminator { - private final RequestSettings requestSettings; - +public class RoadRiskRequestTerminator + extends GenericListRequestTerminator + implements UniversalFormatApiTerminator> { RoadRiskRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); } - public List asJava() { - return new RoadRiskResponseMapper().mapToObjects(asJSON()); + @Override + protected String getRawResponse() { + return new RequestExecutor(requestSettings).getResponse(ApiVariant.BASE, RequestExecutor.Method.POST); } - public String asJSON() { - return getRawResponse(); + @Override + protected Class getValueType() { + return RoadRisk.class; } - public String asXML() { - requestSettings.setResponseType(ResponseType.XML); - return getRawResponse(); - } - - public String asHTML() { - requestSettings.setResponseType(ResponseType.HTML); - return getRawResponse(); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(RequestExecutor.Method.POST); + @Override + protected Class getInnerType() { + return RoadRiskModel.class; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequester.java index 29a28ca..f671821 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequester.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequester.java @@ -1,24 +1,43 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; import com.github.prominence.openweathermap.api.model.roadrisk.TrackPoint; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; import com.github.prominence.openweathermap.api.request.roadrisk.model.RoadRiskRequestPayload; -import com.github.prominence.openweathermap.api.serializer.RoadRiskRequestSerializer; import java.util.List; -public class RoadRiskRequester { - private final RequestSettings requestSettings; +public class RoadRiskRequester extends GenericRequester { public RoadRiskRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); this.requestSettings.appendToURL("data/2.5/roadrisk"); } public RoadRiskRequestCustomizer byTrackPoints(List trackPoints) { requestSettings.setPayloadObject(new RoadRiskRequestPayload(trackPoints)); - requestSettings.setPayloadClass(RoadRiskRequestPayload.class); - requestSettings.setPayloadSerializer(new RoadRiskRequestSerializer()); return new RoadRiskRequestCustomizer(requestSettings); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/model/RoadRiskRequestPayload.java b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/model/RoadRiskRequestPayload.java index 77093c2..b8ba2a8 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/model/RoadRiskRequestPayload.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/model/RoadRiskRequestPayload.java @@ -1,17 +1,37 @@ +/* + * Copyright (c) 2021-present 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.roadrisk.model; +import com.fasterxml.jackson.annotation.JsonProperty; import com.github.prominence.openweathermap.api.model.roadrisk.TrackPoint; +import lombok.Data; +import lombok.NonNull; import java.util.List; +@Data public class RoadRiskRequestPayload { + @NonNull + @JsonProperty("track") private final List payload; - - public RoadRiskRequestPayload(List payload) { - this.payload = payload; - } - - public List getPayload() { - return payload; - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherAsyncRequestTerminator.java index 694de21..643a2c1 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherAsyncRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,19 +22,18 @@ package com.github.prominence.openweathermap.api.request.weather; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper; -import com.github.prominence.openweathermap.api.model.weather.Weather; +import com.github.prominence.openweathermap.api.model.weather.CurrentWeather; +import com.github.prominence.openweathermap.api.model.weather.CurrentWeatherModel; import com.github.prominence.openweathermap.api.request.RequestSettings; - -import java.util.concurrent.CompletableFuture; +import com.github.prominence.openweathermap.api.request.generic.GenericAsyncRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatAsyncApiTerminator; /** * The type Single result current weather async request terminator. */ -public class CurrentWeatherAsyncRequestTerminator { - private final RequestSettings requestSettings; +public class CurrentWeatherAsyncRequestTerminator + extends GenericAsyncRequestTerminator + implements UniversalFormatAsyncApiTerminator { /** * Instantiates a new Single result current weather async request terminator. @@ -42,28 +41,6 @@ public class CurrentWeatherAsyncRequestTerminator { * @param requestSettings request settings object. */ CurrentWeatherAsyncRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; - } - - public CompletableFuture asJava() { - return CompletableFuture.supplyAsync(() -> new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).mapToWeather(getRawResponse())); - } - - public CompletableFuture asJSON() { - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - public CompletableFuture asXML() { - requestSettings.setResponseType(ResponseType.XML); - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - public CompletableFuture asHTML() { - requestSettings.setResponseType(ResponseType.HTML); - return CompletableFuture.supplyAsync(this::getRawResponse); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); + super(new CurrentWeatherRequestTerminator(requestSettings)); } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestCustomizer.java index 3499232..b543a49 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestCustomizer.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,8 +23,10 @@ package com.github.prominence.openweathermap.api.request.weather; import com.github.prominence.openweathermap.api.enums.Language; -import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.weather.CurrentWeather; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatApiTerminator; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatAsyncApiTerminator; /** * The type Single result current weather request customizer. @@ -46,16 +48,11 @@ public class CurrentWeatherRequestCustomizer { return this; } - public CurrentWeatherRequestCustomizer unitSystem(UnitSystem unitSystem) { - requestSettings.setUnitSystem(unitSystem); - return this; - } - - public CurrentWeatherRequestTerminator retrieve() { + public UniversalFormatApiTerminator retrieve() { return new CurrentWeatherRequestTerminator(requestSettings); } - public CurrentWeatherAsyncRequestTerminator retrieveAsync() { + public UniversalFormatAsyncApiTerminator retrieveAsync() { return new CurrentWeatherAsyncRequestTerminator(requestSettings); } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminator.java index 3e7e45f..d92f1d5 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,17 +22,18 @@ package com.github.prominence.openweathermap.api.request.weather; -import com.github.prominence.openweathermap.api.core.net.RequestExecutor; -import com.github.prominence.openweathermap.api.enums.ResponseType; -import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper; -import com.github.prominence.openweathermap.api.model.weather.Weather; +import com.github.prominence.openweathermap.api.model.weather.CurrentWeather; +import com.github.prominence.openweathermap.api.model.weather.CurrentWeatherModel; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequestTerminator; +import com.github.prominence.openweathermap.api.request.generic.UniversalFormatApiTerminator; /** * The type Single result current weather request terminator. */ -public class CurrentWeatherRequestTerminator { - private final RequestSettings requestSettings; +public class CurrentWeatherRequestTerminator + extends GenericRequestTerminator + implements UniversalFormatApiTerminator { /** * Instantiates a new Single result current weather request terminator. @@ -40,28 +41,12 @@ public class CurrentWeatherRequestTerminator { * @param requestSettings request settings object. */ CurrentWeatherRequestTerminator(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); } - public Weather asJava() { - return new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).mapToWeather(asJSON()); + @Override + protected Class getValueType() { + return CurrentWeatherModel.class; } - public String asJSON() { - return getRawResponse(); - } - - public String asXML() { - requestSettings.setResponseType(ResponseType.XML); - return getRawResponse(); - } - - public String asHTML() { - requestSettings.setResponseType(ResponseType.HTML); - return getRawResponse(); - } - - private String getRawResponse() { - return new RequestExecutor(requestSettings).getResponse(); - } } 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 4a47fff..b3d96b9 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) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,14 +22,17 @@ package com.github.prominence.openweathermap.api.request.weather; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.request.generic.GenericRequester; + +import static com.github.prominence.openweathermap.api.request.RequestSettings.LATITUDE_PARAM; +import static com.github.prominence.openweathermap.api.request.RequestSettings.LONGITUDE_PARAM; /** * The type Single location current weather requester. */ -public class CurrentWeatherRequester { - private final RequestSettings requestSettings; +public class CurrentWeatherRequester extends GenericRequester { /** * Instantiates a new Single location current weather requester. @@ -37,49 +40,14 @@ public class CurrentWeatherRequester { * @param requestSettings request settings object. */ public CurrentWeatherRequester(RequestSettings requestSettings) { - this.requestSettings = requestSettings; + super(requestSettings); this.requestSettings.appendToURL("data/2.5/weather"); } - @Deprecated - public CurrentWeatherRequestCustomizer byCityName(String cityName) { - requestSettings.putRequestParameter("q", cityName); - return new CurrentWeatherRequestCustomizer(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())); + requestSettings.putRequestParameter(LATITUDE_PARAM, String.valueOf(coordinates.getLatitude())); + requestSettings.putRequestParameter(LONGITUDE_PARAM, 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/serializer/EpochSecondsSerializer.java b/src/main/java/com/github/prominence/openweathermap/api/serializer/EpochSecondsSerializer.java new file mode 100644 index 0000000..194f1dd --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/serializer/EpochSecondsSerializer.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.serializer; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; +import java.time.OffsetDateTime; +import java.util.Optional; + +public class EpochSecondsSerializer extends JsonSerializer { + + @Override + public void serialize(final OffsetDateTime value, final JsonGenerator generator, final SerializerProvider provider) throws IOException { + final Optional optional = Optional.ofNullable(value); + if (optional.isPresent()) { + final long epochSeconds = optional + .map(OffsetDateTime::toEpochSecond) + .get(); + generator.writeNumber(epochSeconds); + } else { + generator.writeNull(); + } + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/serializer/RoadRiskRequestSerializer.java b/src/main/java/com/github/prominence/openweathermap/api/serializer/RoadRiskRequestSerializer.java deleted file mode 100644 index 0dd9990..0000000 --- a/src/main/java/com/github/prominence/openweathermap/api/serializer/RoadRiskRequestSerializer.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.github.prominence.openweathermap.api.serializer; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.github.prominence.openweathermap.api.model.Coordinates; -import com.github.prominence.openweathermap.api.model.roadrisk.TrackPoint; -import com.github.prominence.openweathermap.api.request.roadrisk.model.RoadRiskRequestPayload; - -import java.io.IOException; -import java.time.ZoneId; -import java.util.List; - -public class RoadRiskRequestSerializer extends JsonSerializer { - @Override - public void serialize(RoadRiskRequestPayload roadRiskRequestPayload, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { - jsonGenerator.writeStartObject(); - jsonGenerator.writeArrayFieldStart("track"); - - final List trackPoints = roadRiskRequestPayload.getPayload(); - for (TrackPoint point : trackPoints) { - jsonGenerator.writeStartObject(); - jsonGenerator.writeNumberField("dt", point.getRequestedTime().atZone(ZoneId.systemDefault()).toEpochSecond()); - - final Coordinates coordinates = point.getCoordinates(); - jsonGenerator.writeNumberField("lat", coordinates.getLatitude()); - jsonGenerator.writeNumberField("lon", coordinates.getLongitude()); - - jsonGenerator.writeEndObject(); - } - - jsonGenerator.writeEndArray(); - jsonGenerator.writeEndObject(); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/ApiTest.java b/src/test/java/com/github/prominence/openweathermap/api/ApiTest.java index ea42665..6fa5479 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/ApiTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/ApiTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,15 +22,21 @@ package com.github.prominence.openweathermap.api; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; import org.junit.jupiter.api.BeforeAll; +import java.util.Optional; + public class ApiTest { + public static final String OPENWEATHER_API_KEY = "OPENWEATHER_API_KEY"; + public static final String RUN_ONE_CALL = "RUN_ONE_CALL"; private static OpenWeatherMapClient client; @BeforeAll public static void retrieveApiKey() { - String apiKey = System.getenv("OPENWEATHER_API_KEY"); - client = new OpenWeatherMapClient(apiKey); + String apiKey = Optional.ofNullable(System.getenv(OPENWEATHER_API_KEY)) + .orElse("PLEASE SET OPENWEATHER_API_KEY ENV VAR!"); + client = new OpenWeatherMapClient(ApiConfiguration.builder().apiKey(apiKey).build()); } protected static OpenWeatherMapClient getClient() { diff --git a/src/test/java/com/github/prominence/openweathermap/api/context/ApiConfigurationTest.java b/src/test/java/com/github/prominence/openweathermap/api/context/ApiConfigurationTest.java new file mode 100644 index 0000000..cf44b5f --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/context/ApiConfigurationTest.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2021-present 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.context; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.prominence.openweathermap.api.conf.TimeoutSettings; +import com.github.prominence.openweathermap.api.core.net.HttpURLConnectionBasedHttpClient; +import com.github.prominence.openweathermap.api.enums.ApiVariant; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +class ApiConfigurationTest { + + @SuppressWarnings("ConstantConditions") + @Test + void testBuilder_ShouldThrowException_WhenNullIsPassedAsApiKey() { + //given + final ApiConfiguration.ApiConfigurationBuilder builder = ApiConfiguration.builder(); + + //when + Assertions.assertThrows(IllegalArgumentException.class, () -> builder.apiKey(null)); + + //then + exception + } + + @SuppressWarnings("ConstantConditions") + @Test + void testBuilder_ShouldThrowException_WhenNullIsPassedAsHttpClient() { + //given + final ApiConfiguration.ApiConfigurationBuilder builder = ApiConfiguration.builder(); + + //when + Assertions.assertThrows(IllegalArgumentException.class, () -> builder.httpClient(null)); + + //then + exception + } + + @SuppressWarnings("ConstantConditions") + @Test + void testBuilder_ShouldThrowException_WhenNullIsPassedAsObjectMapper() { + //given + final ApiConfiguration.ApiConfigurationBuilder builder = ApiConfiguration.builder(); + + //when + Assertions.assertThrows(IllegalArgumentException.class, () -> builder.objectMapper(null)); + + //then + exception + } + + @SuppressWarnings("ConstantConditions") + @Test + void testBuilder_ShouldThrowException_WhenNullIsPassedAsDefaultTimeoutSettings() { + //given + final ApiConfiguration.ApiConfigurationBuilder builder = ApiConfiguration.builder(); + + //when + Assertions.assertThrows(IllegalArgumentException.class, () -> builder.defaultTimeoutSettings(null)); + + //then + exception + } + + @SuppressWarnings("ConstantConditions") + @Test + void testBuilder_ShouldThrowException_WhenNullIsPassedAsBaseUriMap() { + //given + final ApiConfiguration.ApiConfigurationBuilder builder = ApiConfiguration.builder(); + + //when + Assertions.assertThrows(IllegalArgumentException.class, () -> builder.baseUrls(null)); + + //then + exception + } + + @Test + void testBuilder_ShouldThrowException_WhenBaseUriMapDoesNotContainAllKeys() { + //given + final ApiConfiguration.ApiConfigurationBuilder builder = ApiConfiguration.builder(); + + //when + Assertions.assertThrows(IllegalArgumentException.class, + () -> builder.baseUrls(Collections.singletonMap(ApiVariant.BASE, ApiVariant.BASE.getBaseUrl()))); + + //then + exception + } + + @Test + void testBuilderBuild_ShouldSetEverything_WhenEveryFieldIsPopulatedWithValidData() { + //given + final String apiKey = "apiKey"; + final TimeoutSettings defaultTimeoutSettings = new TimeoutSettings(40, 100); + final Map baseUrls = new TreeMap<>(); + baseUrls.put(ApiVariant.BASE, "https://base.openweathermap.org/"); + baseUrls.put(ApiVariant.PRO, "https://premium.openweathermap.org/"); + final HttpURLConnectionBasedHttpClient httpClient = new HttpURLConnectionBasedHttpClient(); + final ObjectMapper objectMapper = new ObjectMapper(); + + //when + final ApiConfiguration actual = ApiConfiguration.builder() + .apiKey(apiKey) + .baseUrls(baseUrls) + .defaultTimeoutSettings(defaultTimeoutSettings) + .httpClient(httpClient) + .objectMapper(objectMapper) + .build(); + + + //then + Assertions.assertEquals(apiKey, actual.getApiKey()); + Assertions.assertEquals(httpClient, actual.getHttpClient()); + Assertions.assertNotNull(actual.getObjectReader()); + Assertions.assertNotNull(actual.getObjectWriter()); + baseUrls.keySet().forEach(key -> { + Assertions.assertEquals(baseUrls.get(key), actual.getBaseUrls().get(key)); + }); + Assertions.assertEquals(defaultTimeoutSettings, actual.getDefaultTimeoutSettings()); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/context/TestMappingUtils.java b/src/test/java/com/github/prominence/openweathermap/api/context/TestMappingUtils.java new file mode 100644 index 0000000..2c0a576 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/context/TestMappingUtils.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021-present 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.context; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.CollectionType; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.List; + +public class TestMappingUtils { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + public static OffsetDateTime parseDateTime(int seconds) { + return OffsetDateTime.ofInstant(Instant.ofEpochSecond(seconds), ZoneOffset.UTC); + } + + public static T loadDeserializedResourceAs(String resource, Class type) throws JsonProcessingException { + final String json = readJson(resource); + return OBJECT_MAPPER.readValue(json, type); + } + + public static List loadDeserializedResourceAsList(String resource, Class type) throws JsonProcessingException { + final String json = readJson(resource); + final CollectionType listType = OBJECT_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, type); + return OBJECT_MAPPER.readValue(json, listType); + } + + private static String readJson(String resource) { + final String json; + try { + json = IOUtils.resourceToString(resource, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new IllegalStateException(e.getMessage(), e); + } + return json; + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/core/net/HttpURLConnectionBasedHttpClientTest.java b/src/test/java/com/github/prominence/openweathermap/api/core/net/HttpURLConnectionBasedHttpClientTest.java new file mode 100644 index 0000000..0fee41b --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/core/net/HttpURLConnectionBasedHttpClientTest.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2021-present 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.core.net; + +import com.github.prominence.openweathermap.api.conf.TimeoutSettings; +import com.github.prominence.openweathermap.api.exception.InvalidAuthTokenException; +import com.github.prominence.openweathermap.api.exception.NoDataFoundException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atMostOnce; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class HttpURLConnectionBasedHttpClientTest { + + private static final String MULTI_LINE_RESPONSE = "response line 1" + System.lineSeparator() + + "line 2" + System.lineSeparator() + + System.lineSeparator() + + "4"; + + public static Stream validGetRequestDataProvider() { + return Stream.builder() + .add(Arguments.of("http://localhost", 200, MULTI_LINE_RESPONSE)) + .add(Arguments.of("http://127.0.0.1", 200, "{}")) + .build(); + } + + public static Stream invalidGetRequestDataProvider() { + return Stream.builder() + .add(Arguments.of("http://localhost", 404, false, NoDataFoundException.class)) + .add(Arguments.of("http://127.0.0.1", 400, false, NoDataFoundException.class)) + .add(Arguments.of("http://127.0.0.1", 401, false, InvalidAuthTokenException.class)) + .add(Arguments.of("http://localhost", 301, true, NoDataFoundException.class)) + .build(); + } + + public static Stream validPostRequestDataProvider() { + return Stream.builder() + .add(Arguments.of("http://localhost", "input", 200, MULTI_LINE_RESPONSE)) + .add(Arguments.of("http://127.0.0.1", null, 200, "{}")) + .build(); + } + + public static Stream cleanUpInputProvider() { + return Stream.builder() + .add(Arguments.of("http://localhost", 200, MULTI_LINE_RESPONSE)) + .add(Arguments.of("http://localhost", 301, MULTI_LINE_RESPONSE)) + .add(Arguments.of("http://127.0.0.1", 404, null)) + .add(Arguments.of("http://127.0.0.1", 401, null)) + .build(); + } + + @Test + void testSetTimeoutSettings_ShouldSetTimeOutValues_WhenCalled() throws IOException { + //given + HttpURLConnectionBasedHttpClient underTest = spy(new HttpURLConnectionBasedHttpClient()); + final TimeoutSettings timeoutSettings = new TimeoutSettings(500, 1000); + HttpURLConnection connection = mock(HttpURLConnection.class); + when(connection.getResponseCode()).thenReturn(200); + when(connection.getInputStream()).thenReturn(new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8))); + doReturn(connection).when(underTest).getConnection(anyString()); + + //when + underTest.setTimeoutSettings(timeoutSettings); + underTest.executeGetRequest("http://localhsot"); + + //then + verify(connection).setConnectTimeout(eq(timeoutSettings.getConnectionTimeout())); + verify(connection).setReadTimeout(eq(timeoutSettings.getReadTimeout())); + } + + @ParameterizedTest + @MethodSource("validPostRequestDataProvider") + void testExecutePostRequest_ShouldProcessResponse_WhenThereIsOne( + final String url, final String body, final int responseCode, final String response) throws IOException { + //given + HttpURLConnectionBasedHttpClient underTest = spy(new HttpURLConnectionBasedHttpClient()); + HttpURLConnection connection = mock(HttpURLConnection.class); + when(connection.getResponseCode()).thenReturn(responseCode); + when(connection.getInputStream()).thenReturn(new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8))); + ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + doReturn(connection).when(underTest).getConnection(urlCaptor.capture()); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + doReturn(output).when(connection).getOutputStream(); + + //when + final String actual = underTest.executePostRequest(url, body); + + //then + verify(underTest).getConnection(eq(url)); + verify(connection).getResponseCode(); + verify(connection).getInputStream(); + verify(connection).setRequestMethod("POST"); + assertEquals(Optional.ofNullable(body).orElse(""), output.toString(StandardCharsets.UTF_8.toString())); + assertEquals(response, actual); + } + + @ParameterizedTest + @MethodSource("validGetRequestDataProvider") + void testExecuteGetRequest_ShouldProcessResponse_WhenThereIsOne( + final String url, final int responseCode, final String response) throws IOException { + //given + HttpURLConnectionBasedHttpClient underTest = spy(new HttpURLConnectionBasedHttpClient()); + HttpURLConnection connection = mock(HttpURLConnection.class); + when(connection.getResponseCode()).thenReturn(responseCode); + when(connection.getInputStream()).thenReturn(new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8))); + doReturn(connection).when(underTest).getConnection(eq(url)); + + //when + final String actual = underTest.executeGetRequest(url); + + //then + verify(underTest).getConnection(eq(url)); + verify(connection).getResponseCode(); + verify(connection).getInputStream(); + verify(connection).setRequestMethod("GET"); + assertEquals(response, actual); + } + + @ParameterizedTest + @MethodSource("invalidGetRequestDataProvider") + void testExecuteGetRequest_ShouldThrowException_WhenTheRequestWasNotSuccessful( + final String url, + final int responseCode, + final boolean shouldCallInputStream, + final Class exception) throws IOException { + //given + HttpURLConnectionBasedHttpClient underTest = spy(new HttpURLConnectionBasedHttpClient()); + HttpURLConnection connection = mock(HttpURLConnection.class); + when(connection.getResponseCode()).thenReturn(responseCode); + ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + doReturn(connection).when(underTest).getConnection(urlCaptor.capture()); + + //when + assertThrows(exception, () -> underTest.executeGetRequest(url)); + + //then + exception + verify(connection).setRequestMethod("GET"); + verify(connection).getResponseCode(); + if (!shouldCallInputStream) { + verify(connection, never()).getInputStream(); + } + assertEquals(url, urlCaptor.getValue()); + } + + @ParameterizedTest + @MethodSource("cleanUpInputProvider") + void testExecuteGetRequest_ShouldAttemptToCloseTheResponseInputStream_WhenCalled( + final String url, + final int responseCode, + final String response) throws IOException { + //given + HttpURLConnectionBasedHttpClient underTest = spy(new HttpURLConnectionBasedHttpClient()); + HttpURLConnection connection = mock(HttpURLConnection.class); + when(connection.getResponseCode()).thenReturn(responseCode); + ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + if (response == null) { + when(connection.getInputStream()).thenReturn(null); + } else { + final ByteArrayInputStream stream = mock(ByteArrayInputStream.class); + doThrow(new IOException("fail")).when(stream).close(); + when(connection.getInputStream()).thenReturn(stream); + } + doReturn(connection).when(underTest).getConnection(urlCaptor.capture()); + + //when + assertThrows(Exception.class, () -> underTest.executeGetRequest(url)); + + //then + exception + verify(connection).setRequestMethod("GET"); + verify(connection).getResponseCode(); + verify(connection, atMostOnce()).getInputStream(); + assertEquals(url, urlCaptor.getValue()); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/core/net/MockHttpClient.java b/src/test/java/com/github/prominence/openweathermap/api/core/net/MockHttpClient.java deleted file mode 100644 index 45c6407..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/core/net/MockHttpClient.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.github.prominence.openweathermap.api.core.net; - -import com.github.prominence.openweathermap.api.conf.TimeoutSettings; - -public class MockHttpClient implements HttpClient { - private String responseOutput; - - @Override - public void setTimeoutSettings(TimeoutSettings timeoutSettings) { - - } - - @Override - public String executeGetRequest(String url) { - System.out.println("Executing request to " + url); - - return responseOutput; - } - - @Override - public String executePostRequest(String url, String body) { - System.out.println("Executing request to " + url); - System.out.println("Request body: " + body); - - return responseOutput; - } - - public void setResponseOutput(String responseOutput) { - this.responseOutput = responseOutput; - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/enums/AirQualityIndexTest.java b/src/test/java/com/github/prominence/openweathermap/api/enums/AirQualityIndexTest.java new file mode 100644 index 0000000..f46f33d --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/enums/AirQualityIndexTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-present 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.enums; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class AirQualityIndexTest { + + public static Stream valueProvider() { + return Stream.builder() + .add(Arguments.of(AirQualityIndex.GOOD.getValue(), AirQualityIndex.GOOD)) + .add(Arguments.of(AirQualityIndex.FAIR.getValue(), AirQualityIndex.FAIR)) + .add(Arguments.of(AirQualityIndex.MODERATE.getValue(), AirQualityIndex.MODERATE)) + .add(Arguments.of(AirQualityIndex.POOR.getValue(), AirQualityIndex.POOR)) + .add(Arguments.of(AirQualityIndex.VERY_POOR.getValue(), AirQualityIndex.VERY_POOR)) + .add(Arguments.of(6, null)) + .build(); + } + + @ParameterizedTest + @MethodSource("valueProvider") + void testGetByIndex_ShouldReturnNull_WhenValueIsNotFound(final int index, final AirQualityIndex expected) { + //given + + //when + final AirQualityIndex actual = AirQualityIndex.getByIndex(index); + + //then + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/enums/DayTimeTest.java b/src/test/java/com/github/prominence/openweathermap/api/enums/DayTimeTest.java new file mode 100644 index 0000000..54fc251 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/enums/DayTimeTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021-present 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.enums; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class DayTimeTest { + + public static Stream valueProvider() { + return Stream.builder() + .add(Arguments.of(DayTime.DAY.getValue(), DayTime.DAY)) + .add(Arguments.of(DayTime.NIGHT.getValue(), DayTime.NIGHT)) + .add(Arguments.of("N/A", null)) + .build(); + } + + @ParameterizedTest + @MethodSource("valueProvider") + void testFindByValue_ShouldReturnNull_WhenValueIsNotFound(final String value, final DayTime expected) { + //given + + //when + final DayTime actual = DayTime.findByValue(value); + + //then + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/enums/EventLevelTest.java b/src/test/java/com/github/prominence/openweathermap/api/enums/EventLevelTest.java new file mode 100644 index 0000000..c827dc5 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/enums/EventLevelTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-present 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.enums; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class EventLevelTest { + + public static Stream valueProvider() { + return Stream.builder() + .add(Arguments.of(EventLevel.UNKNOWN.getValue(), EventLevel.UNKNOWN)) + .add(Arguments.of(EventLevel.GREEN.getValue(), EventLevel.GREEN)) + .add(Arguments.of(EventLevel.YELLOW.getValue(), EventLevel.YELLOW)) + .add(Arguments.of(EventLevel.ORANGE.getValue(), EventLevel.ORANGE)) + .add(Arguments.of(EventLevel.RED.getValue(), EventLevel.RED)) + .add(Arguments.of(6, null)) + .build(); + } + + @ParameterizedTest + @MethodSource("valueProvider") + void testFindByValue_ShouldReturnNull_WhenValueIsNotFound(final int index, final EventLevel expected) { + //given + + //when + final EventLevel actual = EventLevel.findByValue(index); + + //then + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/enums/MoonTypeTest.java b/src/test/java/com/github/prominence/openweathermap/api/enums/MoonTypeTest.java new file mode 100644 index 0000000..c749360 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/enums/MoonTypeTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021-present 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.enums; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class MoonTypeTest { + + public static Stream inputProvider() { + return Stream.builder() + .add(Arguments.of(0, MoonType.NEW_MOON)) + .add(Arguments.of(1, MoonType.NEW_MOON)) + .add(Arguments.of(0.25, MoonType.FIRST_QUARTER_MOON)) + .add(Arguments.of(0.5, MoonType.FULL_MOON)) + .add(Arguments.of(0.75, MoonType.LAST_QUARTER_MOON)) + .add(Arguments.of(0.01, MoonType.WAXING_CRESCENT)) + .add(Arguments.of(0.24, MoonType.WAXING_CRESCENT)) + .add(Arguments.of(0.26, MoonType.WAXING_GIBBOUS)) + .add(Arguments.of(0.49, MoonType.WAXING_GIBBOUS)) + .add(Arguments.of(0.51, MoonType.WANING_GIBBOUS)) + .add(Arguments.of(0.74, MoonType.WANING_GIBBOUS)) + .add(Arguments.of(0.76, MoonType.WANING_CRESCENT)) + .add(Arguments.of(0.99, MoonType.WANING_CRESCENT)) + .add(Arguments.of(1.01, MoonType.INVALID)) + .build(); + } + + @ParameterizedTest + @MethodSource("inputProvider") + void testValueOf_ShouldReturnTheAppropriateValue_WhenCalled(final double value, final MoonType expected) { + //given + + //when + final MoonType actual = MoonType.valueOf(value); + + //then + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/enums/WeatherConditionUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/enums/WeatherConditionUnitTest.java index 908483d..43b3c51 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/enums/WeatherConditionUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/enums/WeatherConditionUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -24,82 +24,134 @@ package com.github.prominence.openweathermap.api.enums; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; public class WeatherConditionUnitTest { - @Test - public void getId() { - final WeatherCondition weatherCondition = WeatherCondition.ASH; - assertNotEquals(0, weatherCondition.getId()); + private static final int EXPECTED_ID = 762; + private static final String EXPECTED_NAME = "Ash"; + private static final String EXPECTED_DESCRIPTION = "volcanic ash"; + private static final String EXPECTED_ICON = "50"; + + @Test + public void testGetId_ShouldReturnPredefinedValue_WhenCalled() { + //given + final WeatherCondition underTest = WeatherCondition.ASH; + + //when + final int actual = underTest.getId(); + + //then + assertEquals(EXPECTED_ID, actual); } @Test - public void getName() { - final WeatherCondition weatherCondition = WeatherCondition.ASH; + public void testGetName_ShouldReturnPredefinedValue_WhenCalled() { + //given + final WeatherCondition underTest = WeatherCondition.ASH; - assertNotNull(weatherCondition.getName()); - assertNotEquals("", weatherCondition.getName()); + //when + final String actual = underTest.getName(); + + //then + assertEquals(EXPECTED_NAME, actual); } @Test - public void getDescription() { - final WeatherCondition weatherCondition = WeatherCondition.ASH; + public void testGetDescription_ShouldReturnPredefinedValue_WhenCalled() { + //given + final WeatherCondition underTest = WeatherCondition.ASH; - assertNotNull(weatherCondition.getDescription()); - assertNotEquals("", weatherCondition.getDescription()); + //when + final String actual = underTest.getDescription(); + + //then + assertEquals(EXPECTED_DESCRIPTION, actual); } @Test - public void getDayIconId() { - final WeatherCondition weatherCondition = WeatherCondition.ASH; + public void testGetDayIconId_ShouldReturnDayVariantOfPredefinedIcon_WhenCalled() { + //given + final WeatherCondition underTest = WeatherCondition.ASH; - assertNotNull(weatherCondition.getDayIconId()); - assertNotEquals("", weatherCondition.getDayIconId()); + //when + final String actual = underTest.getDayIconId(); + + //then + assertEquals(EXPECTED_ICON + "d", actual); } @Test - public void getNightIconId() { - final WeatherCondition weatherCondition = WeatherCondition.ASH; + public void testGetNightIconId_ShouldReturnNightVariantOfPredefinedIcon_WhenCalled() { + //given + final WeatherCondition underTest = WeatherCondition.ASH; - assertNotNull(weatherCondition.getNightIconId()); - assertNotEquals("", weatherCondition.getNightIconId()); + //when + final String actual = underTest.getNightIconId(); + + //then + assertEquals(EXPECTED_ICON + "n", actual); } @Test - public void getDayIconUrl() { - final WeatherCondition weatherCondition = WeatherCondition.ASH; + public void testGetDayIconUrl_ShouldReturnUrlEndingWithDayVariantOfPredefinedIcon_WhenCalled() { + //given + final WeatherCondition underTest = WeatherCondition.ASH; - assertNotNull(weatherCondition.getDayIconUrl()); - assertNotEquals("", weatherCondition.getDayIconUrl()); + //when + final String actual = underTest.getDayIconUrl(false); + + //then + assertTrue(actual.endsWith(EXPECTED_ICON + "d.png")); } @Test - public void getNightIconUrl() { - final WeatherCondition weatherCondition = WeatherCondition.ASH; + public void testGetNightIconUrl_ShouldReturnUrlEndingWithNightVariantOfPredefinedIcon_WhenCalled() { + //given + final WeatherCondition underTest = WeatherCondition.ASH; - assertNotNull(weatherCondition.getNightIconUrl()); - assertNotEquals("", weatherCondition.getNightIconUrl()); + //when + final String actual = underTest.getNightIconUrl(true); + + //then + assertTrue(actual.endsWith(EXPECTED_ICON + "n.png")); } @Test - public void getIconUrl() { - final WeatherCondition weatherCondition = WeatherCondition.ASH; + public void testGetById_ShouldReturnMatchingEnum_WhenCalledWithKnownId() { + //given - assertNotNull(WeatherCondition.getIconUrl(weatherCondition.getNightIconId())); - assertNotEquals("", WeatherCondition.getIconUrl(weatherCondition.getNightIconId())); + //when + final WeatherCondition actual = WeatherCondition.getById(EXPECTED_ID); + + //then + assertEquals(WeatherCondition.ASH, actual); } @Test - public void getById() { - assertEquals(WeatherCondition.ASH, WeatherCondition.getById(WeatherCondition.ASH.getId())); + public void testGetById_ShouldReturnNull_WhenCalledWithUnknownId() { + //given + + //when + final WeatherCondition actual = WeatherCondition.getById(-EXPECTED_ID); + + //then + assertNull(actual); } @Test - public void testToString() { - final WeatherCondition weatherCondition = WeatherCondition.ASH; + public void testGetById_ShouldReturnStringContainingIdNameDescription_WhenCalled() { + //given + final WeatherCondition underTest = WeatherCondition.ASH; - assertNotNull(weatherCondition.toString()); - assertNotEquals("", weatherCondition.toString()); + //when + final String actual = underTest.toString(); + + //then + assertTrue(actual.contains(String.valueOf(EXPECTED_ID))); + assertTrue(actual.contains(EXPECTED_NAME)); + assertTrue(actual.contains(EXPECTED_DESCRIPTION)); } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/mapper/ClimaticForecastResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/ClimaticForecastResponseMapperTest.java index ac9df48..d62b426 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/mapper/ClimaticForecastResponseMapperTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/ClimaticForecastResponseMapperTest.java @@ -1,126 +1,115 @@ +/* + * Copyright (c) 2021-present 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.Wind; -import com.github.prominence.openweathermap.api.model.*; -import com.github.prominence.openweathermap.api.model.forecast.climatic.AtmosphericPressure; -import com.github.prominence.openweathermap.api.model.forecast.climatic.Temperature; -import com.github.prominence.openweathermap.api.model.forecast.climatic.*; -import com.github.prominence.openweathermap.api.utils.TestMappingUtils; +import com.github.prominence.openweathermap.api.context.TestMappingUtils; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.forecast.climatic.ThirtyDaysDailyForecast; +import com.github.prominence.openweathermap.api.model.forecast.climatic.ThirtyDaysDailyForecastModel; +import com.github.prominence.openweathermap.api.model.forecast.climatic.WeatherForecastDay; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.pressure.BaseAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.DailyTemperature; +import com.github.prominence.openweathermap.api.model.generic.wind.BasicWind; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.io.IOException; +import java.math.BigDecimal; + +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAs; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; class ClimaticForecastResponseMapperTest { @Test - public void mapToForecast() { - final String jsonResponse = """ - { - "cod": "200", - "city": { - "id": 2643743, - "name": "London", - "coord": { - "lon": -0.1277, - "lat": 51.5073 - }, - "country": "GB" - }, - "message": 0.353472054, - "list": [ - { - "dt": 1594382400, - "sunrise": 1594353335, - "sunset": 1594412149, - "temp": { - "day": 286.98, - "min": 285.22, - "max": 287.97, - "night": 285.22, - "eve": 287.97, - "morn": 287.29 - }, - "feels_like": { - "day": 282.61, - "night": 283.19, - "eve": 284.98, - "morn": 282.68 - }, - "pressure": 1016, - "humidity": 84, - "weather": [ - { - "id": 500, - "main": "Rain", - "description": "light rain", - "icon": "10d" - } - ], - "speed": 6.78, - "deg": 320, - "clouds": 81, - "rain": 1.96, - "snow": 2.21 - } - ] - } - """; + public void testDeserialize_ShouldSucceed_WhenCalledWithFullyPopulatedJson() throws IOException { + //given + final String resource = "/responses/valid/climatic.json"; - final Forecast forecast = new ClimaticForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonResponse); - assertNotNull(forecast); + //when + final ThirtyDaysDailyForecast actual = loadDeserializedResourceAs(resource, ThirtyDaysDailyForecastModel.class); - final Location location = forecast.getLocation(); + //then + assertNotNull(actual); + + final BaseLocation location = actual.getLocation(); assertNotNull(location); - assertEquals(Coordinates.of(51.5073, -0.1277), location.getCoordinates()); - assertEquals(2643743, location.getId()); - assertEquals("London", location.getName()); + assertEquals(new Coordinates(51.5073, -0.1277), location.getCoordinates()); + assertEquals(2643743, location.getCityId()); + assertNull(location.getTimeZone()); + assertEquals("London", location.getCityName()); assertEquals("GB", location.getCountryCode()); - assertNull(location.getPopulation()); - assertNull(location.getZoneOffset()); - assertEquals(1, forecast.getWeatherForecasts().size()); - final WeatherForecast weatherForecast = forecast.getWeatherForecasts().get(0); + assertEquals(1, actual.getWeatherForecasts().size()); + final WeatherForecastDay weatherForecast = actual.getWeatherForecasts().get(0); assertEquals(TestMappingUtils.parseDateTime(1594382400), weatherForecast.getForecastTime()); - assertEquals(TestMappingUtils.parseDateTime(1594353335), weatherForecast.getSunriseTime()); - assertEquals(TestMappingUtils.parseDateTime(1594412149), weatherForecast.getSunsetTime()); - final Temperature temperature = weatherForecast.getTemperature(); - assertEquals(286.98, temperature.getDay()); - assertEquals(285.22, temperature.getMin()); - assertEquals(287.97, temperature.getMax()); - assertEquals(285.22, temperature.getNight()); - assertEquals(287.97, temperature.getEve()); - assertEquals(287.29, temperature.getMorning()); - assertEquals(282.61, temperature.getDayFeelsLike()); - assertEquals(283.19, temperature.getNightFeelsLike()); - assertEquals(284.98, temperature.getEveFeelsLike()); - assertEquals(282.68, temperature.getMorningFeelsLike()); + final SunlightStages sunlightStages = weatherForecast.getSunlightStages(); + assertEquals(TestMappingUtils.parseDateTime(1594353335), sunlightStages.getSunriseTime()); + assertEquals(TestMappingUtils.parseDateTime(1594412149), sunlightStages.getSunsetTime()); - final AtmosphericPressure pressure = weatherForecast.getAtmosphericPressure(); - assertEquals(1016, pressure.getSeaLevelValue()); + final DailyTemperature temperature = weatherForecast.getTemperature(); + assertEquals(BigDecimal.valueOf(287), temperature.getDay().asKelvin()); + assertEquals(BigDecimal.valueOf(285), temperature.getMin().asKelvin()); + assertEquals(BigDecimal.valueOf(288), temperature.getMax().asKelvin()); + assertEquals(BigDecimal.valueOf(285), temperature.getNight().asKelvin()); + assertEquals(BigDecimal.valueOf(288), temperature.getEve().asKelvin()); + assertEquals(BigDecimal.valueOf(287), temperature.getMorning().asKelvin()); + assertEquals(BigDecimal.valueOf(283), temperature.getDayFeelsLike().asKelvin()); + assertEquals(BigDecimal.valueOf(283), temperature.getNightFeelsLike().asKelvin()); + assertEquals(BigDecimal.valueOf(285), temperature.getEveFeelsLike().asKelvin()); + assertEquals(BigDecimal.valueOf(283), temperature.getMorningFeelsLike().asKelvin()); + + final BaseAtmosphericPressure pressure = weatherForecast.getAtmosphericPressure(); + assertEquals(BigDecimal.valueOf(1016), pressure.getPressure()); final Humidity humidity = weatherForecast.getHumidity(); - assertEquals(84, humidity.getValue()); + assertEquals(84, humidity.getHumidityPercentage()); - final Wind wind = weatherForecast.getWind(); - assertEquals(6.78, wind.getSpeed()); - assertEquals(320, wind.getDegrees()); + final BasicWind wind = weatherForecast.getWind(); + assertEquals(BigDecimal.valueOf(6.78), wind.getSpeed().asMetersPerSecond()); + assertEquals(320, wind.getDirectionDegrees()); - final Clouds clouds = weatherForecast.getClouds(); - assertEquals(81, clouds.getValue()); + final CloudCoverage clouds = weatherForecast.getCloudCoverage(); + assertEquals(81, clouds.getCoveragePercentage()); assertEquals(1, weatherForecast.getWeatherStates().size()); - final WeatherState weatherState = weatherForecast.getWeatherStates().get(0); + final WeatherCondition weatherState = weatherForecast.getWeatherStates().get(0); assertEquals(500, weatherState.getId()); assertEquals("Rain", weatherState.getName()); assertEquals("light rain", weatherState.getDescription()); - assertEquals("10d", weatherState.getIconId()); + assertEquals("10d", weatherState.getDayIconId()); - final Rain rain = weatherForecast.getRain(); - assertEquals(1.96, rain.getLevel()); + final BigDecimal rain = weatherForecast.getPrecipitation().getRain(); + assertEquals(BigDecimal.valueOf(1.96), rain); - final Snow snow = weatherForecast.getSnow(); - assertEquals(2.21, snow.getLevel()); + final BigDecimal snow = weatherForecast.getPrecipitation().getSnow(); + assertEquals(BigDecimal.valueOf(2.21), snow); } -} \ No newline at end of file +} 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 index b387ecd..ba133cc 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapperTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/CurrentWeatherResponseMapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,1233 +22,269 @@ 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 com.fasterxml.jackson.core.JsonProcessingException; +import com.github.prominence.openweathermap.api.model.weather.CurrentWeather; +import com.github.prominence.openweathermap.api.model.weather.CurrentWeatherModel; +import com.github.prominence.openweathermap.api.model.weather.PrecipitationDetails; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.math.BigDecimal; + +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAs; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; 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 - } - """; + public void testDeserialize_ShouldSucceed_WhenCalledWithOfficialJsonExample() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-official.json"; - final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).mapToWeather(jsonString); + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); - assertNotNull(weather); + //then + assertNotNull(actual); + //TODO: Consider adding more assertions } @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 - } - """; + public void testDeserialize_ShouldSucceed_WhenCalledWithFullyPopulatedExample() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk.json"; - final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).mapToWeather(jsonString); + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); - assertNotNull(weather); + //then + assertNotNull(actual); + + assertLatitudeSet(actual); + assertLongitudeSet(actual); + assertCountryCodeSet(actual); + + assertTemperatureSet(actual); + assertFeelsLikeSet(actual); + assertMinTempSet(actual); + assertMaxTempSet(actual); + + assertWindSpeedSet(actual); + assertWindDirectionSet(actual); + assertWindSpeedGustSet(actual); + + final PrecipitationDetails precipitation = actual.getPrecipitation(); + assert1HrRainSet(precipitation); + assert3HrRainSet(precipitation); + assert1HrSnowSet(precipitation); + assert3HrSnowSet(precipitation); } @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)); + public void testDeserialize_ShouldThrowException_WhenCalledWithInvalidJson() { + //given + final String resource = "/responses/invalid/current-weather-minsk-invalid.json"; + + //when + assertThrows(JsonProcessingException.class, () -> loadDeserializedResourceAs(resource, CurrentWeatherModel.class)); + + //then + exception } @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 - } - """; + public void testDeserialize_ShouldLeaveOutForecastTime_WhenCalledWithJsonWithoutDt() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk-missing-dt.json"; - final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).mapToWeather(jsonString); + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); - assertNotNull(weather); - assertNull(weather.getCalculationTime()); + //then + assertNotNull(actual); + assertNull(actual.getForecastTime()); + } + + + @Test + public void testDeserialize_ShouldLeaveOutFeelsLike_WhenCalledWithJsonWithoutFeelsLike() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk-missing-feelslike.json"; + + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); + + //then + assertNotNull(actual); + assertTemperatureSet(actual); + assertNull(actual.getTemperature().getFeelsLike()); + assertMinTempSet(actual); + assertMaxTempSet(actual); } @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 - } - """; + public void testDeserialize_ShouldLeaveOutMinTemp_WhenCalledWithJsonWithoutMinTemp() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk-missing-mintemp.json"; - final Weather weather = new CurrentWeatherResponseMapper(UnitSystem.METRIC).mapToWeather(jsonString); + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); - assertNotNull(weather); - assertNull(weather.getWeatherStates()); + //then + assertNotNull(actual); + assertTemperatureSet(actual); + assertFeelsLikeSet(actual); + assertNull(actual.getTemperature().getMin()); + assertMaxTempSet(actual); } @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); + public void testDeserialize_ShouldLeaveOutMaxTemp_WhenCalledWithJsonWithoutMaxTemp() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk-missing-maxtemp.json"; - Weather weather = mapper.mapToWeather(jsonString); + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); - 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()); + //then + assertNotNull(actual); + assertTemperatureSet(actual); + assertFeelsLikeSet(actual); + assertMinTempSet(actual); + assertNull(actual.getTemperature().getMax()); } @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 - } - """; + public void testDeserialize_ShouldLeaveOutWindDirection_WhenCalledWithJsonWithoutWindDirection() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk-missing-wind-direction.json"; - final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); - Weather weather = mapper.mapToWeather(jsonString); + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); - 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); + //then + assertNotNull(actual); + assertWindSpeedSet(actual); + assertNull(actual.getWind().getDirectionDegrees()); + assertWindSpeedGustSet(actual); } @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 - } - """; + public void testDeserialize_ShouldLeaveOutWindSpeedGust_WhenCalledWithJsonWithoutWindSpeedGust() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk-missing-gust.json"; - final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); - Weather weather = mapper.mapToWeather(jsonWith1Hr); + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); - // 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); + //then + assertNotNull(actual); + assertWindSpeedSet(actual); + assertWindDirectionSet(actual); + assertNull(actual.getWind().getGust()); } @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 - } - """; + public void testDeserialize_ShouldLeaveOut1HrPrecipitation_WhenCalledWithJsonWithout1HrPrecipitation() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk-missing-1h.json"; - final CurrentWeatherResponseMapper mapper = new CurrentWeatherResponseMapper(UnitSystem.METRIC); - Weather weather = mapper.mapToWeather(jsonWith1Hr); + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); - // 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); + //then + final PrecipitationDetails precipitation = actual.getPrecipitation(); + assertNull(precipitation.getOneHourRainLevel()); + assert3HrRainSet(precipitation); + assertNull(precipitation.getOneHourSnowLevel()); + assert3HrSnowSet(precipitation); } @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); + public void testDeserialize_ShouldLeaveOut3HrPrecipitation_WhenCalledWithJsonWithout3HrPrecipitation() throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk-missing-3h.json"; - Weather weather = mapper.mapToWeather(jsonString); + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); - assertNotNull(weather.getLocation().getCoordinates()); - 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().getCoordinates()); - 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().getCoordinates()); - 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().getCoordinates()); - assertNotNull(weather.getLocation().getCountryCode()); + //then + final PrecipitationDetails precipitation = actual.getPrecipitation(); + assert1HrRainSet(precipitation); + assertNull(precipitation.getThreeHoursRainLevel()); + assert1HrSnowSet(precipitation); + assertNull(precipitation.getThreeHoursSnowLevel()); } -} \ No newline at end of file + + @Test + public void testDeserialize_ShouldLeaveOutCoordinatesAndCountry_WhenCalledWithJsonWithoutCoordinatesAndCountryCode() + throws JsonProcessingException { + //given + final String resource = "/responses/valid/current-weather-minsk-missing-coord-and-country.json"; + + //when + final CurrentWeather actual = loadDeserializedResourceAs(resource, CurrentWeatherModel.class); + + //then + assertNull(actual.getLocation().getCoordinates()); + assertNull(actual.getLocation().getCountryCode()); + } + + private void assertCountryCodeSet(CurrentWeather weather) { + assertEquals("BY", weather.getLocation().getCountryCode()); + } + + private void assertLongitudeSet(CurrentWeather weather) { + assertEquals(27.5667D, weather.getLocation().getCoordinates().getLongitude()); + } + + private void assertLatitudeSet(CurrentWeather weather) { + assertEquals(53.9D, weather.getLocation().getCoordinates().getLatitude()); + } + + + private void assertMaxTempSet(CurrentWeather weather) { + assertEquals(BigDecimal.valueOf(2), weather.getTemperature().getMax().asKelvin()); + } + + private void assertMinTempSet(CurrentWeather weather) { + assertEquals(BigDecimal.valueOf(2), weather.getTemperature().getMin().asKelvin()); + } + + private void assertFeelsLikeSet(CurrentWeather weather) { + assertEquals(BigDecimal.valueOf(0), weather.getTemperature().getFeelsLike().asKelvin()); + } + + private void assertTemperatureSet(CurrentWeather weather) { + assertEquals(BigDecimal.valueOf(2), weather.getTemperature().getTemperature().asKelvin()); + } + + private void assertWindSpeedGustSet(CurrentWeather weather) { + assertEquals(BigDecimal.valueOf(2.44), weather.getWind().getGust().asMetersPerSecond()); + } + + private void assertWindDirectionSet(CurrentWeather weather) { + assertEquals(250, weather.getWind().getDirectionDegrees()); + } + + private void assertWindSpeedSet(CurrentWeather weather) { + assertEquals(new BigDecimal("2.00"), weather.getWind().getSpeed().asMetersPerSecond()); + } + + private void assert1HrRainSet(PrecipitationDetails weather) { + assertEquals(BigDecimal.valueOf(0.1), weather.getOneHourRainLevel()); + } + + private void assert3HrRainSet(PrecipitationDetails weather) { + assertEquals(BigDecimal.valueOf(0.6), weather.getThreeHoursRainLevel()); + } + + private void assert1HrSnowSet(PrecipitationDetails weather) { + assertEquals(BigDecimal.valueOf(0.2), weather.getOneHourSnowLevel()); + } + + private void assert3HrSnowSet(PrecipitationDetails weather) { + assertEquals(BigDecimal.valueOf(0.7), weather.getThreeHoursSnowLevel()); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapperTest.java index c533e6c..384a048 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapperTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/DailyForecastResponseMapperTest.java @@ -1,137 +1,118 @@ +/* + * Copyright (c) 2021-present 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.daily.AtmosphericPressure; -import com.github.prominence.openweathermap.api.model.forecast.daily.Temperature; -import com.github.prominence.openweathermap.api.model.forecast.daily.*; -import com.github.prominence.openweathermap.api.utils.TestMappingUtils; +import com.github.prominence.openweathermap.api.context.TestMappingUtils; +import com.github.prominence.openweathermap.api.enums.DayTime; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.forecast.daily.DailyWeather; +import com.github.prominence.openweathermap.api.model.forecast.daily.SixteenDaysDailyForecast; +import com.github.prominence.openweathermap.api.model.forecast.daily.SixteenDaysDailyForecastModel; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.DetailedLocationInfo; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.BaseAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.DailyTemperature; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; import org.junit.jupiter.api.Test; +import java.io.IOException; +import java.math.BigDecimal; import java.time.ZoneOffset; +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAs; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; class DailyForecastResponseMapperTest { @Test - public void mapToForecast() { - final String jsonResponse = """ - { - "city": { - "id": 2643743, - "name": "London", - "coord": { - "lon": -0.1258, - "lat": 51.5085 - }, - "country": "GB", - "population": 0, - "timezone": 3600 - }, - "cod": "200", - "message": 0.7809187, - "cnt": 1, - "list": [ - { - "dt": 1568977200, - "sunrise": 1568958164, - "sunset": 1569002733, - "temp": { - "day": 293.79, - "min": 288.85, - "max": 294.47, - "night": 288.85, - "eve": 290.44, - "morn": 293.79 - }, - "feels_like": { - "day": 278.87, - "night": 282.73, - "eve": 281.92, - "morn": 278.87 - }, - "pressure": 1025.04, - "humidity": 42, - "weather": [ - { - "id": 800, - "main": "Clear", - "description": "sky is clear", - "icon": "01d" - } - ], - "speed": 4.66, - "deg": 102, - "gust": 5.3, - "clouds": 0, - "pop": 0.24, - "rain": 22.2, - "snow": 24.2 - } - ] - } - """; + public void testDeserialize_ShouldSucceed_WhenCalledWithFullyPopulatedJson() throws IOException { + //given + final String resource = "/responses/valid/16days-daily.json"; - final Forecast forecast = new DailyForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonResponse); - assertNotNull(forecast); + //when + final SixteenDaysDailyForecast actual = loadDeserializedResourceAs(resource, SixteenDaysDailyForecastModel.class); - final Location location = forecast.getLocation(); + //then + assertNotNull(actual); + + final DetailedLocationInfo location = actual.getLocation(); assertNotNull(location); - assertEquals(Coordinates.of(51.5085, -0.1258), location.getCoordinates()); - assertEquals(2643743, location.getId()); - assertEquals("London", location.getName()); + assertEquals(new Coordinates(51.5085, -0.1258), location.getCoordinates()); + assertEquals(2643743, location.getCityId()); + assertEquals("London", location.getCityName()); assertEquals("GB", location.getCountryCode()); assertEquals(0, location.getPopulation()); - assertEquals(ZoneOffset.ofTotalSeconds(3600), location.getZoneOffset()); + assertEquals(ZoneOffset.ofTotalSeconds(3600), location.getTimeZone()); - assertEquals(1, forecast.getWeatherForecasts().size()); - final WeatherForecast weatherForecast = forecast.getWeatherForecasts().get(0); + assertEquals(1, actual.getWeatherForecasts().size()); + final DailyWeather weatherForecast = actual.getWeatherForecasts().get(0); assertEquals(TestMappingUtils.parseDateTime(1568977200), weatherForecast.getForecastTime()); // TODO: Does the API provide the sunrise and sunset info??? It is not officially described in the API but present in the example. - assertEquals(TestMappingUtils.parseDateTime(1568958164), weatherForecast.getSunriseTime()); - assertEquals(TestMappingUtils.parseDateTime(1569002733), weatherForecast.getSunsetTime()); + final SunlightStages sunlightStages = weatherForecast.getSunlightStages(); + assertEquals(TestMappingUtils.parseDateTime(1568958164), sunlightStages.getSunriseTime()); + assertEquals(TestMappingUtils.parseDateTime(1569002733), sunlightStages.getSunsetTime()); - final Temperature temperature = weatherForecast.getTemperature(); - assertEquals(293.79, temperature.getDay()); - assertEquals(288.85, temperature.getMin()); - assertEquals(294.47, temperature.getMax()); - assertEquals(288.85, temperature.getNight()); - assertEquals(290.44, temperature.getEve()); - assertEquals(293.79, temperature.getMorning()); - assertEquals(278.87, temperature.getDayFeelsLike()); - assertEquals(282.73, temperature.getNightFeelsLike()); - assertEquals(281.92, temperature.getEveFeelsLike()); - assertEquals(278.87, temperature.getMorningFeelsLike()); + final DailyTemperature temperature = weatherForecast.getTemperature(); + assertEquals(BigDecimal.valueOf(294), temperature.getDay().asKelvin()); + assertEquals(BigDecimal.valueOf(289), temperature.getMin().asKelvin()); + assertEquals(BigDecimal.valueOf(294), temperature.getMax().asKelvin()); + assertEquals(BigDecimal.valueOf(289), temperature.getNight().asKelvin()); + assertEquals(BigDecimal.valueOf(290), temperature.getEve().asKelvin()); + assertEquals(BigDecimal.valueOf(294), temperature.getMorning().asKelvin()); + assertEquals(BigDecimal.valueOf(279), temperature.getDayFeelsLike().asKelvin()); + assertEquals(BigDecimal.valueOf(283), temperature.getNightFeelsLike().asKelvin()); + assertEquals(BigDecimal.valueOf(282), temperature.getEveFeelsLike().asKelvin()); + assertEquals(BigDecimal.valueOf(279), temperature.getMorningFeelsLike().asKelvin()); - final AtmosphericPressure pressure = weatherForecast.getAtmosphericPressure(); - assertEquals(1025.04, pressure.getSeaLevelValue()); + final BaseAtmosphericPressure pressure = weatherForecast.getAtmosphericPressure(); + assertEquals(BigDecimal.valueOf(1025.04), pressure.getPressure()); final Humidity humidity = weatherForecast.getHumidity(); - assertEquals(42, humidity.getValue()); + assertEquals(42, humidity.getHumidityPercentage()); - final Wind wind = weatherForecast.getWind(); - assertEquals(4.66, wind.getSpeed()); - assertEquals(102, wind.getDegrees()); - assertEquals(5.3, wind.getGust()); + final DetailedWindInfo wind = weatherForecast.getWind(); + assertEquals(BigDecimal.valueOf(4.66), wind.getSpeed().asMetersPerSecond()); + assertEquals(102, wind.getDirectionDegrees()); + assertEquals(new BigDecimal("5.30"), wind.getGust().asMetersPerSecond()); - final Clouds clouds = weatherForecast.getClouds(); - assertEquals(0, clouds.getValue()); + final CloudCoverage clouds = weatherForecast.getCloudCoverage(); + assertEquals(0, clouds.getCoveragePercentage()); assertEquals(1, weatherForecast.getWeatherStates().size()); - final WeatherState weatherState = weatherForecast.getWeatherStates().get(0); + final WeatherCondition weatherState = weatherForecast.getWeatherStates().get(0); assertEquals(800, weatherState.getId()); assertEquals("Clear", weatherState.getName()); - assertEquals("sky is clear", weatherState.getDescription()); - assertEquals("01d", weatherState.getIconId()); + assertEquals("clear sky", weatherState.getDescription()); + assertEquals("01d", weatherState.getIconId(DayTime.DAY)); - final Rain rain = weatherForecast.getRain(); - assertEquals(22.2, rain.getLevel()); - - final Snow snow = weatherForecast.getSnow(); - assertEquals(24.2, snow.getLevel()); - - assertEquals(0.24, weatherForecast.getProbabilityOfPrecipitation()); + final PrecipitationForecast precipitation = weatherForecast.getPrecipitation(); + assertEquals(BigDecimal.valueOf(22.2), precipitation.getRain()); + assertEquals(BigDecimal.valueOf(24.2), precipitation.getSnow()); + assertEquals(24, precipitation.getProbabilityOfPrecipitation()); } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapperTest.java index b37e57b..2068efd 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapperTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/FiveDayThreeHourStepForecastResponseMapperTest.java @@ -1,184 +1,128 @@ +/* + * Copyright (c) 2021-present 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.free.*; -import com.github.prominence.openweathermap.api.utils.TestMappingUtils; +import com.github.prominence.openweathermap.api.context.TestMappingUtils; +import com.github.prominence.openweathermap.api.enums.DayTime; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecast; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecastModel; +import com.github.prominence.openweathermap.api.model.forecast.free.ThreeHourWeather; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.DetailedLocationInfo; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.pressure.DetailedAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureWithRange; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; import org.junit.jupiter.api.Test; +import java.io.IOException; +import java.math.BigDecimal; +import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.List; +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAs; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; class FiveDayThreeHourStepForecastResponseMapperTest { @Test - void mapToForecast() { - final String jsonResponse = """ - { - "cod": "200", - "message": 0, - "cnt": 40, - "list": [ - { - "dt": 1647345600, - "main": { - "temp": 286.88, - "feels_like": 285.93, - "temp_min": 286.74, - "temp_max": 286.88, - "pressure": 1021, - "sea_level": 1021, - "grnd_level": 1018, - "humidity": 62, - "temp_kf": 0.14 - }, - "weather": [ - { - "id": 804, - "main": "Clouds", - "description": "overcast clouds", - "icon": "04d" - } - ], - "clouds": { - "all": 85 - }, - "wind": { - "speed": 3.25, - "deg": 134, - "gust": 4.45 - }, - "visibility": 10000, - "pop": 0, - "sys": { - "pod": "d" - }, - "rain": { - "3h": 22.1 - }, - "snow": { - "3h": 13.6 - }, - "dt_txt": "2022-03-15 12:00:00" - }, - { - "dt": 1647356400, - "main": { - "temp": 286.71, - "feels_like": 285.77, - "temp_min": 286.38, - "temp_max": 286.71, - "pressure": 1021, - "sea_level": 1021, - "grnd_level": 1017, - "humidity": 63, - "temp_kf": 0.33 - }, - "weather": [ - { - "id": 804, - "main": "Clouds", - "description": "overcast clouds", - "icon": "04d" - } - ], - "clouds": { - "all": 90 - }, - "wind": { - "speed": 3.34, - "deg": 172, - "gust": 4.03 - }, - "visibility": 10000, - "pop": 0, - "sys": { - "pod": "d" - }, - "dt_txt": "2022-03-15 15:00:00" - } - ], - "city": { - "id": 2643743, - "name": "London", - "coord": { - "lat": 51.5073, - "lon": -0.1277 - }, - "country": "GB", - "population": 1000000, - "timezone": 0, - "sunrise": 1647324903, - "sunset": 1647367441 - } - } - """; + void testDeserialize_ShouldSucceed_WhenCalledWithFullyPopulatedJson() throws IOException { + //given + final String resource = "/responses/valid/5days3hours.json"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonResponse); - assertNotNull(forecast); + //when + final FiveDaysThreeHoursForecast actual = loadDeserializedResourceAs(resource, FiveDaysThreeHoursForecastModel.class); - final Location location = forecast.getLocation(); + //then + assertNotNull(actual); + + final DetailedLocationInfo location = actual.getLocation(); assertNotNull(location); - assertEquals(Coordinates.of(51.5073, -0.1277), location.getCoordinates()); - assertEquals(2643743, location.getId()); - assertEquals("London", location.getName()); + assertEquals(new Coordinates(51.5073, -0.1277), location.getCoordinates()); + assertEquals(2643743, location.getCityId()); + assertEquals("London", location.getCityName()); assertEquals("GB", location.getCountryCode()); assertEquals(1000000, location.getPopulation()); - assertEquals(TestMappingUtils.parseDateTime(1647324903), location.getSunriseTime()); - assertEquals(TestMappingUtils.parseDateTime(1647367441), location.getSunsetTime()); - assertEquals(ZoneOffset.ofTotalSeconds(0), location.getZoneOffset()); + assertEquals(ZoneOffset.ofTotalSeconds(0), location.getTimeZone()); + + final SunlightStages sunlightStages = actual.getSunlightStages(); + assertEquals(TestMappingUtils.parseDateTime(1647324903), sunlightStages.getSunriseTime()); + assertEquals(TestMappingUtils.parseDateTime(1647367441), sunlightStages.getSunsetTime()); - final List weatherForecastList = forecast.getWeatherForecasts(); + final List weatherForecastList = actual.getWeatherForecasts(); assertEquals(2, weatherForecastList.size()); - final WeatherForecast weatherForecast = weatherForecastList.get(0); + final ThreeHourWeather weatherForecast = weatherForecastList.get(0); assertNotNull(weatherForecast); assertEquals(TestMappingUtils.parseDateTime(1647345600), weatherForecast.getForecastTime()); - assertEquals(10000, weatherForecast.getVisibilityInMetres()); - assertEquals(0, weatherForecast.getProbabilityOfPrecipitation()); - assertEquals("2022-03-15 12:00:00", weatherForecast.getForecastTimeISO()); - assertEquals(DayTime.DAY, weatherForecast.getDayTime()); + assertEquals(new BigDecimal("10000.00"), weatherForecast.getVisibility().asMeters()); + assertEquals(0, weatherForecast.getThreeHoursPrecipitation().getProbabilityOfPrecipitation()); + assertEquals(OffsetDateTime.of(2022, 3, 15, 12, 0, 0, 0, ZoneOffset.UTC), + weatherForecast.getForecastTime()); + assertEquals(DayTime.DAY, weatherForecast.getPartOfDay()); - final Temperature temperature = weatherForecast.getTemperature(); + final TemperatureWithRange temperature = weatherForecast.getTemperature(); assertNotNull(temperature); - assertEquals(286.88, temperature.getValue()); - assertEquals(285.93, temperature.getFeelsLike()); - assertEquals(286.74, temperature.getMinTemperature()); - assertEquals(286.88, temperature.getMaxTemperature()); + assertEquals(BigDecimal.valueOf(287), temperature.getTemperature().asKelvin()); + assertEquals(BigDecimal.valueOf(286), temperature.getFeelsLike().asKelvin()); + assertEquals(BigDecimal.valueOf(287), temperature.getMin().asKelvin()); + assertEquals(BigDecimal.valueOf(287), temperature.getMax().asKelvin()); - final AtmosphericPressure pressure = weatherForecast.getAtmosphericPressure(); - assertEquals(1021, pressure.getValue()); - assertEquals(1021, pressure.getSeaLevelValue()); - assertEquals(1018, pressure.getGroundLevelValue()); + final DetailedAtmosphericPressure pressure = weatherForecast.getAtmosphericPressure(); + assertEquals(BigDecimal.valueOf(1021), pressure.getPressure()); + assertEquals(BigDecimal.valueOf(1021), pressure.getSeaLevel()); + assertEquals(BigDecimal.valueOf(1018), pressure.getGroundLevel()); final Humidity humidity = weatherForecast.getHumidity(); - assertEquals(62, humidity.getValue()); + assertEquals(62, humidity.getHumidityPercentage()); - final Clouds clouds = weatherForecast.getClouds(); - assertEquals(85, clouds.getValue()); + final CloudCoverage clouds = weatherForecast.getClouds(); + assertEquals(85, clouds.getCoveragePercentage()); - final Wind wind = weatherForecast.getWind(); - assertEquals(3.25, wind.getSpeed()); - assertEquals(134, wind.getDegrees()); - assertEquals(4.45, wind.getGust()); + final DetailedWindInfo wind = weatherForecast.getWind(); + assertEquals(BigDecimal.valueOf(3.25), wind.getSpeed().asMetersPerSecond()); + assertEquals(134, wind.getDirectionDegrees()); + assertEquals(BigDecimal.valueOf(4.45), wind.getGust().asMetersPerSecond()); assertEquals(1, weatherForecast.getWeatherStates().size()); - final WeatherState weatherState = weatherForecast.getWeatherStates().get(0); + final WeatherCondition weatherState = weatherForecast.getWeatherStates().get(0); assertEquals(804, weatherState.getId()); assertEquals("Clouds", weatherState.getName()); - assertEquals("overcast clouds", weatherState.getDescription()); - assertEquals("04d", weatherState.getIconId()); + assertEquals("overcast clouds: 85-100%", weatherState.getDescription()); + assertEquals("04d", weatherState.getIconId(weatherForecast.getPartOfDay())); - final Rain rain = weatherForecast.getRain(); - assertEquals(22.1, rain.getThreeHourLevel()); + final BigDecimal rain = weatherForecast.getThreeHoursPrecipitation().getRain(); + assertEquals(BigDecimal.valueOf(22.1), rain); - final Snow snow = weatherForecast.getSnow(); - assertEquals(13.6, snow.getThreeHourLevel()); + final BigDecimal snow = weatherForecast.getThreeHoursPrecipitation().getSnow(); + assertEquals(BigDecimal.valueOf(13.6), snow); } -} \ 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 index 04a82c3..370570a 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapperTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/GeocodingResponseMapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,179 +22,47 @@ 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 com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingModel; +import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingModel; import org.junit.jupiter.api.Test; +import java.io.IOException; import java.util.List; +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAs; +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAsList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; 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" - } - ] - """; + public void testDeserialize_ShouldSucceed_WhenCalledWithValidReverseGeocodingJson() throws IOException { + //given + final String resource = "/responses/valid/geocoding-reverse.json"; - List geocodingRecords = new GeocodingResponseMapper().mapGeocodingResponse(jsonResponse); + //when + List actual = loadDeserializedResourceAsList(resource, GeocodingModel.class); - assertNotNull(geocodingRecords); - assertEquals(5, geocodingRecords.size()); + //then + assertNotNull(actual); + assertEquals(5, actual.size()); } - public void zipGeocodingInfoResponseMappingTest() { - String jsonResponse = """ - { - "zip": "90210", - "name": "Beverly Hills", - "lat": 34.0901, - "lon": -118.4065, - "country": "US" - } - """; + @Test + public void testDeserialize_ShouldSucceed_WhenCalledWithValidZipCodeGeocodingJson() throws IOException { + //given + final String resource = "/responses/valid/geocoding-zipcode.json"; - ZipCodeGeocodingRecord zipCodeGeocodingRecord = new GeocodingResponseMapper().mapZipCodeGeocodingResponse(jsonResponse); + //when + ZipCodeGeocodingModel actual = loadDeserializedResourceAs(resource, ZipCodeGeocodingModel.class); - assertNotNull(zipCodeGeocodingRecord); - assertEquals("90210", zipCodeGeocodingRecord.getZip()); - assertEquals("Beverly Hills", zipCodeGeocodingRecord.getName()); - assertEquals("US", zipCodeGeocodingRecord.getCountryCode()); - assertEquals(Coordinates.of(34.0901, -118.4065), zipCodeGeocodingRecord.getCoordinates()); + //then + assertNotNull(actual); + assertEquals("90210", actual.getZipCode()); + assertEquals("Beverly Hills", actual.getName()); + assertEquals("US", actual.getCountryCode()); + assertEquals(new Coordinates(34.0901, -118.4065), actual.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 index aa41fb6..950c0be 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapperTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/HourlyForecastResponseMapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,138 +22,91 @@ 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 com.github.prominence.openweathermap.api.enums.DayTime; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.forecast.hourly.FourDaysHourlyForecast; +import com.github.prominence.openweathermap.api.model.forecast.hourly.FourDaysHourlyForecastModel; +import com.github.prominence.openweathermap.api.model.forecast.hourly.HourlyWeather; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.pressure.DetailedAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureWithRange; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; import org.junit.jupiter.api.Test; +import java.io.IOException; +import java.math.BigDecimal; import java.time.Instant; -import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.time.ZoneOffset; -import java.util.TimeZone; +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAs; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; 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 - } - } - """; + void testDeserialize_ShouldSucceed_WhenCalledWithOfficialExample() throws IOException { + //given + final String resource = "/responses/valid/hourly-forecast.json"; - final HourlyForecast hourlyForecast = new HourlyForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonResponse); - assertNotNull(hourlyForecast); + //when + final FourDaysHourlyForecast actual = loadDeserializedResourceAs(resource, FourDaysHourlyForecastModel.class); - final Location location = hourlyForecast.getLocation(); - assertEquals(2643743, location.getId()); - assertEquals("London", location.getName()); - assertEquals(Coordinates.of(51.5085, -0.1258), location.getCoordinates()); + //then + assertNotNull(actual); + + final BaseLocation location = actual.getLocation(); + assertEquals(2643743, location.getCityId()); + assertEquals("London", location.getCityName()); + assertEquals(new Coordinates(51.5085, -0.1258), location.getCoordinates()); 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()); + assertEquals(ZoneOffset.ofTotalSeconds(0), location.getTimeZone()); - 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 SunlightStages sunlightStages = actual.getSunlightStages(); + assertEquals(OffsetDateTime.ofInstant(Instant.ofEpochSecond(1568958164), ZoneOffset.UTC), sunlightStages.getSunriseTime()); + assertEquals(OffsetDateTime.ofInstant(Instant.ofEpochSecond(1569002733), ZoneOffset.UTC), sunlightStages.getSunsetTime()); - 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 HourlyWeather weatherForecast = actual.getWeatherForecasts().get(0); + assertEquals(OffsetDateTime.ofInstant(Instant.ofEpochSecond(1596632400), ZoneOffset.UTC), weatherForecast.getForecastTime()); + assertEquals(DayTime.NIGHT, weatherForecast.getPartOfDay()); + assertEquals(new BigDecimal("10000.00"), weatherForecast.getVisibility().asMeters()); + assertEquals(4, weatherForecast.getHourlyPrecipitation().getProbabilityOfPrecipitation()); - final AtmosphericPressure pressure = weatherForecast.getAtmosphericPressure(); - assertEquals(1013, pressure.getValue()); - assertEquals(1013, pressure.getSeaLevelValue()); - assertEquals(1010, pressure.getGroundLevelValue()); + final TemperatureWithRange temperature = weatherForecast.getTemperature(); + assertEquals(BigDecimal.valueOf(289), temperature.getTemperature().asKelvin()); + assertEquals(BigDecimal.valueOf(288), temperature.getFeelsLike().asKelvin()); + assertEquals(BigDecimal.valueOf(289), temperature.getMin().asKelvin()); + assertEquals(BigDecimal.valueOf(289), temperature.getMax().asKelvin()); + + final DetailedAtmosphericPressure pressure = weatherForecast.getAtmosphericPressure(); + assertEquals(BigDecimal.valueOf(1013), pressure.getPressure()); + assertEquals(BigDecimal.valueOf(1013), pressure.getSeaLevel()); + assertEquals(BigDecimal.valueOf(1010), pressure.getGroundLevel()); final Humidity humidity = weatherForecast.getHumidity(); - assertEquals(78, humidity.getValue()); + assertEquals(78, humidity.getHumidityPercentage()); - final WeatherState weatherState = weatherForecast.getWeatherStates().get(0); + final WeatherCondition weatherState = weatherForecast.getWeatherStates().get(0); assertEquals(804, weatherState.getId()); assertEquals("Clouds", weatherState.getName()); - assertEquals("overcast clouds", weatherState.getDescription()); - assertEquals("04n", weatherState.getIconId()); + assertEquals("overcast clouds: 85-100%", weatherState.getDescription()); + assertEquals("04n", weatherState.getIconId(DayTime.NIGHT)); - final Clouds clouds = weatherForecast.getClouds(); - assertEquals(100, clouds.getValue()); + final CloudCoverage clouds = weatherForecast.getClouds(); + assertEquals(100, clouds.getCoveragePercentage()); - final Wind wind = weatherForecast.getWind(); - assertEquals(2.03, wind.getSpeed()); - assertEquals(252, wind.getDegrees()); - assertEquals(5.46, wind.getGust()); + final DetailedWindInfo wind = weatherForecast.getWind(); + assertEquals(BigDecimal.valueOf(2.03), wind.getSpeed().asMetersPerSecond()); + assertEquals(252, wind.getDirectionDegrees()); + assertEquals(BigDecimal.valueOf(5.46), wind.getGust().asMetersPerSecond()); - final Rain rain = weatherForecast.getRain(); - assertEquals(23.3, rain.getOneHourLevel()); + assertEquals(BigDecimal.valueOf(23.3), weatherForecast.getHourlyPrecipitation().getRain()); - final Snow snow = weatherForecast.getSnow(); - assertEquals(27.945, snow.getOneHourLevel()); + assertEquals(BigDecimal.valueOf(27.945), weatherForecast.getHourlyPrecipitation().getSnow()); } -} \ 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 index f55d17f..0ac4e12 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapperTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/OneCallWeatherResponseMapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,202 +22,30 @@ 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 com.github.prominence.openweathermap.api.model.onecall.current.OneCallCurrentForecastModel; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.io.IOException; + +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAs; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; 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" - ] - } - ] - } - """; + void testDeserialize_ShouldSucceed_WhenCalledWithOfficialExample() throws IOException { + //given + final String resource = "/responses/valid/onecall-current.json"; - final CurrentWeatherData weatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToCurrent(jsonResponse); + //when + final OneCallCurrentForecastModel actual = loadDeserializedResourceAs(resource, OneCallCurrentForecastModel.class); - assertNotNull(weatherData); - assertNotEquals(0, weatherData.getDailyList().size()); - assertEquals(1, weatherData.getAlerts().get(0).getTags().size()); + //then + assertNotNull(actual); + assertNotEquals(0, actual.getDailyList().size()); + assertEquals(1, actual.getAlerts().get(0).getTags().size()); + //TODO: verify more fields } - - @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/mapper/RoadRiskResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapperTest.java index 0817a8c..3eca5eb 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapperTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapperTest.java @@ -1,67 +1,48 @@ +/* + * Copyright (c) 2021-present 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.roadrisk.RoadRiskRecord; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskModel; import org.junit.jupiter.api.Test; +import java.io.IOException; import java.util.List; +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAsList; import static org.junit.jupiter.api.Assertions.assertNotNull; class RoadRiskResponseMapperTest { @Test - void mapToObjects() { - final String jsonResponse = """ - [ - { - "dt": 1602702000, - "coord": [ - 7.27, - 44.04 - ], - "weather": { - "temp": 278.44, - "wind_speed": 2.27, - "wind_deg": 7, - "precipitation_intensity": 0.38, - "dew_point": 276.13 - }, - "road": { - "state": 2, - "temp": 293.85 - }, - "alerts": [ - { - "sender_name": "METEO-FRANCE", - "event": "Moderate thunderstorm warning", - "event_level": 2 - } - ] - }, - { - "dt": 1602702400, - "coord": [ - 7.37, - 45.04 - ], - "weather": { - "temp": 282.44, - "wind_speed": 1.84, - "wind_deg": 316, - "dew_point": 275.99 - }, - "road": { - "state": 1, - "temp": 293.85 - }, - "alerts": [ - ] - } - ] - """; + void testDeserialize_ShouldSucceed_WhenCalledWithOfficialExample() throws IOException { + //given + final String resource = "/responses/valid/road-risk.json"; - final List roadRiskRecords = new RoadRiskResponseMapper().mapToObjects(jsonResponse); - assertNotNull(roadRiskRecords); + //when + final List actual = loadDeserializedResourceAsList(resource, RoadRiskModel.class); + //then + assertNotNull(actual); + //TODO: verify more fields } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/mapper/SolarRadiationResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/SolarRadiationResponseMapperTest.java index 22bbb66..f31f74e 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/mapper/SolarRadiationResponseMapperTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/SolarRadiationResponseMapperTest.java @@ -1,57 +1,66 @@ +/* + * Copyright (c) 2021-present 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.context.TestMappingUtils; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import com.github.prominence.openweathermap.api.model.radiation.SolarRadiation; -import com.github.prominence.openweathermap.api.model.radiation.SolarRadiationRecord; -import com.github.prominence.openweathermap.api.utils.TestMappingUtils; +import com.github.prominence.openweathermap.api.model.radiation.SolarRadiationEntry; +import com.github.prominence.openweathermap.api.model.radiation.SolarRadiationModel; import org.junit.jupiter.api.Test; +import java.io.IOException; import java.util.List; +import static com.github.prominence.openweathermap.api.context.TestMappingUtils.loadDeserializedResourceAs; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; class SolarRadiationResponseMapperTest { + @Test - void mapToObject() { - final String jsonResponse = """ - { - "coord": { - "lon": -114.6244, - "lat": 32.7243 - }, - "list": [ - { - "radiation": { - "ghi": 206.68, - "dni": 2.27, - "dhi": 204.83, - "ghi_cs": 826.71, - "dni_cs": 885.47, - "dhi_cs": 114.93 - }, - "dt": 1618232400 - } - ] - } - """; + void testDeserialize_ShouldSucceed_WhenCalledWithOfficialExample() throws IOException { + //given + final String resource = "/responses/valid/solar-radiation.json"; - final SolarRadiation solarRadiation = new SolarRadiationResponseMapper().mapToObject(jsonResponse); - assertNotNull(solarRadiation); + //when + final SolarRadiation actual = loadDeserializedResourceAs(resource, SolarRadiationModel.class); - assertEquals(Coordinates.of(32.7243, -114.6244), solarRadiation.getCoordinates()); + //then + assertNotNull(actual); + assertEquals(new Coordinates(32.7243, -114.6244), actual.getCoordinates()); - final List records = solarRadiation.getSolarRadiationRecords(); + final List records = actual.getSolarRadiationRecords(); assertEquals(1, records.size()); - final SolarRadiationRecord record = records.get(0); + final SolarRadiationEntry record = records.get(0); assertEquals(TestMappingUtils.parseDateTime(1618232400), record.getMeasurementTime()); - assertEquals(206.68, record.getCloudSkyGlobalHorizontalIrradiance()); - assertEquals(2.27, record.getCloudSkyDirectNormalIrradiance()); - assertEquals(204.83, record.getCloudSkyDiffuseHorizontalIrradiance()); - assertEquals(826.71, record.getClearSkyGlobalHorizontalIrradiance()); - assertEquals(885.47, record.getClearSkyDirectNormalIrradiance()); - assertEquals(114.93, record.getClearSkyDiffuseHorizontalIrradiance()); + assertEquals(206.68, record.getSolarRadiationMeasurement().getGlobalHorizontalIrradiance()); + assertEquals(2.27, record.getSolarRadiationMeasurement().getDirectNormalIrradiance()); + assertEquals(204.83, record.getSolarRadiationMeasurement().getDiffuseHorizontalIrradiance()); + assertEquals(826.71, record.getSolarRadiationMeasurement().getGlobalHorizontalIrradianceClearSky()); + assertEquals(885.47, record.getSolarRadiationMeasurement().getDirectNormalIrradianceClearSky()); + assertEquals(114.93, record.getSolarRadiationMeasurement().getDiffuseHorizontalIrradianceClearSky()); } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/AtmosphericPressureUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/AtmosphericPressureUnitTest.java deleted file mode 100644 index f053ad7..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/AtmosphericPressureUnitTest.java +++ /dev/null @@ -1,130 +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; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class AtmosphericPressureUnitTest { - @Test - public void whenCreatePressureWithArgs_thenValueIsSet() { - AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(100); - assertEquals(100, atmosphericPressure.getValue(), 0.00001); - - assertEquals(0, AtmosphericPressure.withValue(0).getValue(), 0.00001); - assertEquals(100, AtmosphericPressure.withValue(100).getValue(), 0.00001); - assertEquals(55, AtmosphericPressure.withValue(55).getValue(), 0.00001); - } - - @Test - public void whenCreateTwoIdenticalInstances_thenWheyAreEquals() { - AtmosphericPressure one = AtmosphericPressure.withValue(22); - AtmosphericPressure two = AtmosphericPressure.withValue(22); - - assertEquals(one, two); - assertEquals(one, one); - assertEquals(one.hashCode(), two.hashCode()); - - one.setSeaLevelValue(333); - one.setGroundLevelValue(555); - - two.setSeaLevelValue(333); - two.setGroundLevelValue(555); - - assertEquals(one, two); - assertEquals(two, one); - assertEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCreateTwoDifferentInstances_thenWheyAreNotEquals() { - AtmosphericPressure one = AtmosphericPressure.withValue(5); - AtmosphericPressure two = AtmosphericPressure.withValue(88); - - assertNotEquals(one, two); - assertNotEquals(two, one); - assertNotEquals(one, new Object()); - assertNotEquals(one.hashCode(), two.hashCode()); - - one = AtmosphericPressure.withValue(44); - one.setSeaLevelValue(44); - two = AtmosphericPressure.withValue(44); - two.setGroundLevelValue(22); - - assertNotEquals(one, two); - assertNotEquals(two, one); - - two.setSeaLevelValue(44); - - assertNotEquals(one, two); - assertNotEquals(two, one); - } - - @Test - public void whenSetValidValues_thenAllIsFine() { - AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(14); - atmosphericPressure.setValue(0); - atmosphericPressure.setValue(15); - atmosphericPressure.setValue(100); - - atmosphericPressure.setGroundLevelValue(222); - assertEquals(222, atmosphericPressure.getGroundLevelValue(), 0.00001); - - atmosphericPressure.setSeaLevelValue(4232); - assertEquals(4232, atmosphericPressure.getSeaLevelValue(), 0.00001); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final String pressureString = AtmosphericPressure.withValue(44).toString(); - assertNotNull(pressureString); - assertNotEquals("", pressureString); - } - - @Test - public void whenCreatePressureByConstructorWithInvalidDataNegative_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> AtmosphericPressure.withValue(-33)); - } - - @Test - public void whenCreatePressureAndSetInvalidDataNegative_thenThrowAnException() { - AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(88); - - assertThrows(IllegalArgumentException.class, () -> atmosphericPressure.setValue(-89)); - } - - @Test - public void whenSetInvalidSeaLevelPressure_thenThrowAnException() { - AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(88); - - assertThrows(IllegalArgumentException.class, () -> atmosphericPressure.setSeaLevelValue(-89)); - } - - @Test - public void whenSetInvalidGroundLevelPressure_thenThrowAnException() { - AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(88); - - assertThrows(IllegalArgumentException.class, () -> atmosphericPressure.setGroundLevelValue(-223)); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/CloudsUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/CloudsUnitTest.java deleted file mode 100644 index f01590c..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/CloudsUnitTest.java +++ /dev/null @@ -1,102 +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; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class CloudsUnitTest { - @Test - public void whenCreateCloudsWithValidArgs_thenValueIsSet() { - Clouds clouds = Clouds.withValue((byte) 100); - assertEquals(100, clouds.getValue()); - - assertEquals(0, Clouds.withValue((byte) 0).getValue()); - assertEquals(100, Clouds.withValue((byte) 100).getValue()); - assertEquals(55, Clouds.withValue((byte) 55).getValue()); - } - - @Test - public void whenCreateCloudsByConstructorWithInvalidDataAboveHundred_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Clouds.withValue((byte) 110)); - } - - @Test - public void whenCreateCloudsByConstructorWithInvalidDataNegative_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Clouds.withValue((byte) -33)); - } - - @Test - public void whenSetValidValues_thenAllIsFine() { - Clouds clouds = Clouds.withValue((byte) 14); - clouds.setValue((byte) 0); - assertEquals(0, clouds.getValue()); - clouds.setValue((byte) 15); - assertEquals(15, clouds.getValue()); - clouds.setValue((byte) 100); - assertEquals(100, clouds.getValue()); - } - - @Test - public void whenCreateCloudsAndSetInvalidDataAboveHundred_thenThrowAnException() { - Clouds clouds = Clouds.withValue((byte) 12); - - assertThrows(IllegalArgumentException.class, () -> clouds.setValue((byte) 112)); - } - - @Test - public void whenCreateCloudsAndSetInvalidDataNegative_thenThrowAnException() { - Clouds clouds = Clouds.withValue((byte) 88); - - assertThrows(IllegalArgumentException.class, () -> clouds.setValue((byte) -89)); - } - - @Test - public void whenCreateTwoIdenticalInstances_thenWheyAreEquals() { - Clouds one = Clouds.withValue((byte) 22); - Clouds two = Clouds.withValue((byte) 22); - - assertEquals(one, two); - assertEquals(one, one); - assertEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCreateTwoDifferentInstances_thenWheyAreNotEquals() { - Clouds one = Clouds.withValue((byte) 5); - Clouds two = Clouds.withValue((byte) 88); - - assertNotEquals(one, two); - assertNotEquals(two, one); - assertNotEquals(one, new Object()); - assertNotEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final String cloudsString = Clouds.withValue((byte) 44).toString(); - assertNotNull(cloudsString); - assertNotEquals("", cloudsString); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangleUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangleUnitTest.java index 8c454e2..e32c4fb 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangleUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesRectangleUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,9 +22,13 @@ package com.github.prominence.openweathermap.api.model; +import com.github.prominence.openweathermap.api.model.generic.location.CoordinatesRectangle; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; public class CoordinatesRectangleUnitTest { @Test diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesUnitTest.java index 3c0a535..94b1b0c 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/CoordinatesUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,150 +22,83 @@ package com.github.prominence.openweathermap.api.model; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; public class CoordinatesUnitTest { @Test public void whenCreateCoordinateWithValidValues_thenObjectCreated() { - Coordinates.of(44, 53); + new Coordinates(44, 53); } @Test public void whenCreateCoordinateWithInvalidLatitudeBelowMinus90_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Coordinates.of(-333, 44)); + assertThrows(IllegalArgumentException.class, () -> new Coordinates(-333, 44)); } @Test public void whenCreateCoordinateWithInvalidLatitudeAbove90_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Coordinates.of(223, 44)); + assertThrows(IllegalArgumentException.class, () -> new Coordinates(223, 44)); } @Test public void whenCreateCoordinateWithInvalidLongitudeBelowMinus180_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Coordinates.of(33, -999)); + assertThrows(IllegalArgumentException.class, () -> new Coordinates(33, -999)); } @Test public void whenCreateCoordinateWithInvalidLongitudeAbove180_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Coordinates.of(33, 999)); + assertThrows(IllegalArgumentException.class, () -> new Coordinates(33, 999)); } @Test public void whenSetValidCoordinates_thenAllIsFine() { - final Coordinates coordinates = Coordinates.of(0, 0); - - coordinates.setLatitude(-90); + Coordinates coordinates = new Coordinates(-90, -180); assertEquals(-90, coordinates.getLatitude(), 0.00001); - coordinates.setLatitude(90); - assertEquals(90, coordinates.getLatitude(), 0.00001); - coordinates.setLatitude(44); - assertEquals(44, coordinates.getLatitude(), 0.00001); - - coordinates.setLongitude(-180); assertEquals(-180, coordinates.getLongitude(), 0.00001); - coordinates.setLongitude(180); + + coordinates = new Coordinates(90, 180); + assertEquals(90, coordinates.getLatitude(), 0.00001); assertEquals(180, coordinates.getLongitude(), 0.00001); - coordinates.setLongitude(130); + + coordinates = new Coordinates(44, 130); + assertEquals(44, coordinates.getLatitude(), 0.00001); assertEquals(130, coordinates.getLongitude(), 0.00001); } @Test public void whenSetInvalidLatitudeBelowMinus90_thenThrowAnException() { - final Coordinates coordinates = Coordinates.of(0, 0); - assertThrows(IllegalArgumentException.class, () -> coordinates.setLatitude(-91)); + assertThrows(IllegalArgumentException.class, () -> new Coordinates(-91, 0)); } @Test public void whenSetInvalidLatitudeAbove90_thenThrowAnException() { - final Coordinates coordinates = Coordinates.of(0, 0); - assertThrows(IllegalArgumentException.class, () -> coordinates.setLatitude(92)); + assertThrows(IllegalArgumentException.class, () -> new Coordinates(92, 0)); } @Test public void whenSetInvalidLongitudeBelowMinus180_thenThrowAnException() { - final Coordinates coordinates = Coordinates.of(0, 0); - assertThrows(IllegalArgumentException.class, () -> coordinates.setLongitude(-194)); + assertThrows(IllegalArgumentException.class, () -> new Coordinates(0, -194)); } @Test public void whenSetInvalidLongitudeAbove180_thenThrowAnException() { - final Coordinates coordinates = Coordinates.of(0, 0); - assertThrows(IllegalArgumentException.class, () -> coordinates.setLongitude(444)); + assertThrows(IllegalArgumentException.class, () -> new Coordinates(0, 444)); } @Test public void whenGetLatitude_thenAllIsFine() { - final Coordinates coordinates = Coordinates.of(0, 0); - assertEquals(0, coordinates.getLatitude(), 0.00001); - - coordinates.setLatitude(45); - - assertEquals(45, coordinates.getLatitude(), 0.00001); + final Coordinates coordinates = new Coordinates(44, 0); + assertEquals(44, coordinates.getLatitude(), 0.00001); } @Test public void whenGetLongitude_thenAllIsFine() { - final Coordinates coordinates = Coordinates.of(0, 0); - assertEquals(0, coordinates.getLongitude(), 0.00001); - - coordinates.setLongitude(33); - + final Coordinates coordinates = new Coordinates(0, 33); assertEquals(33, coordinates.getLongitude(), 0.00001); } - - @Test - public void whenCallToString_thenAllIsFine() { - final Coordinates coordinates = Coordinates.of(0, 0); - assertNotNull(coordinates.toString()); - assertNotEquals("", coordinates.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Coordinates first = Coordinates.of(22, 66); - final Coordinates second = Coordinates.of(22, 44); - - assertNotEquals(first.hashCode(), second.hashCode()); - - second.setLongitude(66); - - assertEquals(first.hashCode(), second.hashCode()); - - second.setLatitude(89); - - assertNotEquals(first.hashCode(), second.hashCode()); - - first.setLatitude(89); - - assertEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Coordinates first = Coordinates.of(11, 99); - final Coordinates second = Coordinates.of(11, 99); - - assertEquals(first, second); - assertEquals(first, first); - assertNotEquals(first, new Object()); - - first.setLatitude(34); - - assertNotEquals(first, second); - - second.setLatitude(34); - - assertEquals(first, second); - - second.setLongitude(74); - - assertNotEquals(first, second); - - first.setLongitude(74); - - assertEquals(first, second); - } } diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/DayTimeUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/DayTimeUnitTest.java index 5167503..b37ed30 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/DayTimeUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/DayTimeUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,6 +22,7 @@ package com.github.prominence.openweathermap.api.model; +import com.github.prominence.openweathermap.api.enums.DayTime; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/HumidityUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/HumidityUnitTest.java deleted file mode 100644 index ab0d11d..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/HumidityUnitTest.java +++ /dev/null @@ -1,100 +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; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class HumidityUnitTest { - @Test - public void whenCreateHumidityWithArgs_thenValueIsSet() { - Humidity humidity = Humidity.withValue((byte) 100); - assertEquals(100, humidity.getValue()); - - assertEquals(0, Humidity.withValue((byte) 0).getValue()); - assertEquals(55, Humidity.withValue((byte) 55).getValue()); - } - - @Test - public void whenCreateHumidityByConstructorWithInvalidDataAboveHundred_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Humidity.withValue((byte) 112)); - } - - @Test - public void whenCreateHumidityByConstructorWithInvalidDataNegative_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Humidity.withValue((byte) -33)); - } - - @Test - public void whenSetValidValues_thenAllIsFine() { - Humidity humidity = Humidity.withValue((byte) 14); - assertEquals(14, humidity.getValue()); - humidity.setValue((byte) 0); - assertEquals(0, humidity.getValue()); - humidity.setValue((byte) 15); - assertEquals(15, humidity.getValue()); - humidity.setValue((byte) 100); - assertEquals(100, humidity.getValue()); - } - - @Test - public void whenCreateHumidityAndSetInvalidDataAboveHundred_thenThrowAnException() { - Humidity humidity = Humidity.withValue((byte) 12); - assertThrows(IllegalArgumentException.class, () -> humidity.setValue((byte) 112)); - } - - @Test - public void whenCreateHumidityAndSetInvalidDataNegative_thenThrowAnException() { - Humidity humidity = Humidity.withValue((byte) 88); - assertThrows(IllegalArgumentException.class, () -> humidity.setValue((byte) -89)); - } - - @Test - public void whenCreateTwoIdenticalInstances_thenWheyAreEquals() { - Humidity one = Humidity.withValue((byte) 22); - Humidity two = Humidity.withValue((byte) 22); - - assertEquals(one, two); - assertEquals(one, one); - assertEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCreateTwoDifferentInstances_thenWheyAreNotEquals() { - Humidity one = Humidity.withValue((byte) 5); - Humidity two = Humidity.withValue((byte) 88); - - assertNotEquals(one, two); - assertNotEquals(two, one); - assertNotEquals(one, new Object()); - assertNotEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final String humidityString = Humidity.withValue((byte) 44).toString(); - assertNotNull(humidityString); - assertNotEquals("", humidityString); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/TemperatureUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/TemperatureUnitTest.java deleted file mode 100644 index 716102d..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/TemperatureUnitTest.java +++ /dev/null @@ -1,175 +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; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class TemperatureUnitTest { - @Test - public void whenCreateObjectWithValidArgs_thenObjectIsCreated() { - Temperature.withValue(22.2, "K"); - } - - @Test - public void whenCreateObjectWithEmptyUnit_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Temperature.withValue(22.2, null)); - } - - @Test - public void whenSetValue_thenAllIsFine() { - final Temperature temperature = Temperature.withValue(22.2, "K"); - temperature.setValue(55.44); - - assertEquals(55.44, temperature.getValue(), 0.00001); - } - - @Test - public void whenSetMaximumTemperature_thenAllIsOk() { - final Temperature temperature = Temperature.withValue(22.2, "K"); - temperature.setMaxTemperature(44.4); - - assertEquals(44.4, temperature.getMaxTemperature(), 0.00001); - - temperature.setMaxTemperature(null); - - assertNull(temperature.getMaxTemperature()); - } - - @Test - public void whenSetMinimumTemperature_thenAllIsOk() { - final Temperature temperature = Temperature.withValue(22.2, "K"); - temperature.setMinTemperature(33.2); - - assertEquals(33.2, temperature.getMinTemperature(), 0.00001); - - temperature.setMinTemperature(null); - - assertNull(temperature.getMinTemperature()); - } - - @Test - public void whenSetFeelsLikeTemperature_thenAllIsOk() { - final Temperature temperature = Temperature.withValue(22.2, "K"); - temperature.setFeelsLike(22.3); - - assertEquals(22.3, temperature.getFeelsLike(), 0.00001); - - temperature.setFeelsLike(null); - - assertNull(temperature.getFeelsLike()); - } - - @Test - public void whenSetNonNullUnit_thenAllIsOk() { - final Temperature temperature = Temperature.withValue(22.2, "K"); - temperature.setUnit("test"); - - assertEquals("test", temperature.getUnit()); - } - - @Test - public void whenSetNullUnit_thenThrowAnException() { - final Temperature temperature = Temperature.withValue(22.2, "K"); - - assertThrows(IllegalArgumentException.class, () -> temperature.setUnit(null)); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final Temperature temperature = Temperature.withValue(22.2, "K"); - - assertNotNull(temperature.toString()); - assertNotEquals("", temperature.toString()); - - temperature.setMinTemperature(11.2); - - assertNotNull(temperature.toString()); - assertNotEquals("", temperature.toString()); - - temperature.setMaxTemperature(44.3); - - assertNotNull(temperature.toString()); - assertNotEquals("", temperature.toString()); - - temperature.setFeelsLike(22.4); - - assertNotNull(temperature.toString()); - assertNotEquals("", temperature.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Temperature one = Temperature.withValue(22.2, "K"); - final Temperature two = Temperature.withValue(22.2, "K"); - - assertEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Temperature one = Temperature.withValue(22.2, "K"); - final Temperature two = Temperature.withValue(21.2, "K"); - - assertEquals(one, one); - assertNotEquals(one, new Object()); - assertNotEquals(one, two); - - one.setValue(21.2); - - assertEquals(one, two); - - one.setMaxTemperature(33.56); - - assertNotEquals(one, two); - - two.setMaxTemperature(33.56); - - assertEquals(one, two); - - one.setMinTemperature(11.54); - - assertNotEquals(one, two); - - two.setMinTemperature(11.54); - - assertEquals(one, two); - - two.setUnit("U"); - - assertNotEquals(one, two); - - one.setUnit("U"); - - assertEquals(one, two); - - one.setFeelsLike(22.3); - - assertNotEquals(one, two); - - two.setFeelsLike(22.3); - - assertEquals(one, two); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/WeatherStateUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/WeatherStateUnitTest.java index c0da7ef..b77ff6f 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/WeatherStateUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/WeatherStateUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -25,102 +25,53 @@ package com.github.prominence.openweathermap.api.model; import com.github.prominence.openweathermap.api.enums.WeatherCondition; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; public class WeatherStateUnitTest { @Test public void getId() { - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); + final WeatherCondition weatherState = WeatherCondition.getById(800); assertEquals(800, weatherState.getId()); } @Test public void getName() { - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); + final WeatherCondition weatherState = WeatherCondition.getById(800); assertEquals("Clear", weatherState.getName()); } @Test public void getDescription() { - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); + final WeatherCondition weatherState = WeatherCondition.getById(800); assertEquals("clear sky", weatherState.getDescription()); } @Test public void getIconId() { - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - weatherState.setIconId("04d"); + final WeatherCondition weatherState = WeatherCondition.getById(800); - assertEquals("04d", weatherState.getIconId()); + assertEquals("01d", weatherState.getDayIconId()); } @Test public void getWeatherConditionEnum() { - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); + final WeatherCondition weatherState = WeatherCondition.getById(800); - assertEquals(WeatherCondition.CLEAR, weatherState.getWeatherConditionEnum()); + assertEquals(WeatherCondition.CLEAR, weatherState); } @Test public void getWeatherIconUrl() { - WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); + final WeatherCondition weatherState = WeatherCondition.getById(800); - String weatherIconUrl = weatherState.getWeatherIconUrl(); + String weatherIconUrl = weatherState.getDayIconUrl(true); assertNotNull(weatherIconUrl); - assertNotEquals("", weatherIconUrl); - - weatherState.setIconId("04n"); - weatherIconUrl = weatherState.getWeatherIconUrl(); - - assertNotNull(weatherIconUrl); - assertNotEquals("", weatherIconUrl); - - weatherState = new WeatherState(0, "Unknown", "unknown"); - weatherIconUrl = weatherState.getWeatherIconUrl(); - - assertNull(weatherIconUrl); + assertNotEquals("https://openweathermap.org/img/w/01.png", weatherIconUrl); } - - @Test - public void testEquals() { - final WeatherState first = new WeatherState(800, "Clear", "clear sky"); - final WeatherState second = new WeatherState(800, "Clear", "clear sky"); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - assertEquals(first, second); - - assertNotEquals(new WeatherState(800, "Clear", "clear sky"), new WeatherState(801, "Clear", "clear sky")); - assertNotEquals(new WeatherState(800, "Clear", "clear sky"), new WeatherState(800, "Clear1", "clear sky")); - assertNotEquals(new WeatherState(800, "Clear", "clear sky"), new WeatherState(800, "Clear", "clear sky1")); - - first.setIconId("50d"); - - assertNotEquals(first, second); - } - - @Test - public void testHashCode() { - final WeatherState first = new WeatherState(800, "Clear", "clear sky"); - final WeatherState second = new WeatherState(800, "Clear", "clear sky"); - final WeatherState third = new WeatherState(0, "Unknown", "unknown"); - - assertEquals(first.hashCode(), second.hashCode()); - assertNotEquals(first.hashCode(), third.hashCode()); - assertNotEquals(second.hashCode(), third.hashCode()); - } - - @Test - public void testToString() { - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - - assertNotNull(weatherState.toString()); - assertNotEquals("", weatherState.toString()); - } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsModelTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsModelTest.java new file mode 100644 index 0000000..c4a29e5 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsModelTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021-present 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.air.pollution; + +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; + +class AirPollutionDetailsModelTest { + + @Test + void testGetAirPollutionConcentration_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionDetailsModel underTest = new AirPollutionDetailsModel(); + final AirPollutionMeasurements components = new AirPollutionMeasurements(); + components.setCoarseParticulateMatter(new Concentration(BigDecimal.valueOf(0.54))); + final AirPollutionRecord expected = new AirPollutionRecord(); + expected.setComponents(components); + underTest.setAirPollutionRecords(Collections.singletonList(expected)); + + //when + final List actual = underTest.getAirPollutionConcentration(); + + //then + assertIterableEquals(Collections.singletonList(expected), actual); + } + + @Test + void testGetCoordinates_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionDetailsModel underTest = new AirPollutionDetailsModel(); + final Coordinates expected = new Coordinates(12, 34); + underTest.setCoordinates(expected); + + //when + final Coordinates actual = underTest.getCoordinates(); + + //then + assertEquals(expected, actual); + } +} 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 deleted file mode 100644 index db2f901..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsUnitTest.java +++ /dev/null @@ -1,98 +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.air.pollution; - -import com.github.prominence.openweathermap.api.model.Coordinates; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - -public class AirPollutionDetailsUnitTest { - @Test - public void getCoordinates() { - final AirPollutionDetails airPollutionDetails = new AirPollutionDetails(); - final Coordinates coordinates = Coordinates.of(22.3, 44.2); - airPollutionDetails.setCoordinates(coordinates); - - assertEquals(coordinates, airPollutionDetails.getCoordinates()); - } - - @Test - public void getAirPollutionSamples() { - final AirPollutionDetails airPollutionDetails = new AirPollutionDetails(); - final List airPollutionRecords = new ArrayList<>(); - airPollutionDetails.setAirPollutionRecords(airPollutionRecords); - - assertEquals(airPollutionRecords, airPollutionDetails.getAirPollutionRecords()); - } - - @Test - public void testEquals() { - final AirPollutionDetails first = new AirPollutionDetails(); - final AirPollutionDetails second = new AirPollutionDetails(); - final Coordinates coordinates = Coordinates.of(22.3, 44.2); - final List airPollutionRecords = new ArrayList<>(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertEquals(first, second); - assertNotEquals(first, new Object()); - - assertEquals(first, second); - - first.setCoordinates(coordinates); - - assertNotEquals(first, second); - - second.setCoordinates(coordinates); - - assertEquals(first, second); - - first.setAirPollutionRecords(airPollutionRecords); - - assertNotEquals(first, second); - - second.setAirPollutionRecords(airPollutionRecords); - - assertEquals(first, second); - } - - @Test - public void testHashCode() { - final AirPollutionDetails first = new AirPollutionDetails(); - final AirPollutionDetails second = new AirPollutionDetails(); - final Coordinates coordinates = Coordinates.of(22.3, 44.2); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setCoordinates(coordinates); - - assertNotEquals(first.hashCode(), second.hashCode()); - } -} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecordUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecordUnitTest.java index 2937a17..e4a2065 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecordUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecordUnitTest.java @@ -1,25 +1,23 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.air.pollution; @@ -27,254 +25,170 @@ package com.github.prominence.openweathermap.api.model.air.pollution; import com.github.prominence.openweathermap.api.enums.AirQualityIndex; import org.junit.jupiter.api.Test; -import java.time.LocalDateTime; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; public class AirPollutionRecordUnitTest { @Test - public void getForecastTime() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final LocalDateTime now = LocalDateTime.now(); - airPollutionRecord.setForecastTime(now); + public void testGetForecastTime_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); + underTest.setMeasurementTime(now); - assertEquals(now, airPollutionRecord.getForecastTime()); + //when + final OffsetDateTime actual = underTest.getMeasurementTime(); + + //then + assertEquals(now, actual); } @Test - public void getAirQualityIndex() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - airPollutionRecord.setAirQualityIndex(AirQualityIndex.FAIR); + public void testGetAirQualityIndex_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + underTest.setAirQualityIndex(AirQualityIndex.FAIR); - assertEquals(AirQualityIndex.FAIR, airPollutionRecord.getAirQualityIndex()); + //when + final AirQualityIndex actual = underTest.getAirQualityIndex(); + + //then + assertEquals(AirQualityIndex.FAIR, actual); } @Test - public void getCarbonMonoxide() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final double value = 0.55; - airPollutionRecord.setCO(value); + public void testGetAmmonia_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + final AirPollutionMeasurements components = new AirPollutionMeasurements(); + final BigDecimal expected = new BigDecimal("0.12369127571582794"); + components.setAmmonia(new Concentration(expected)); + underTest.setComponents(components); - assertEquals(value, airPollutionRecord.getCarbonMonoxide(), 0.00001); + //when + final Concentration actual = underTest.getAmmonia(); + + //then + assertEquals(round(expected), actual.asMicrogramsPerCubicMeters()); } @Test - public void getNitrogenMonoxide() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final double value = 0.55; - airPollutionRecord.setNO(value); + public void testGetOzone_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + final AirPollutionMeasurements components = new AirPollutionMeasurements(); + final BigDecimal expected = new BigDecimal("68.66455078125"); + components.setOzone(new Concentration(expected)); + underTest.setComponents(components); - assertEquals(value, airPollutionRecord.getNitrogenMonoxide(), 0.00001); + //when + final Concentration actual = underTest.getOzone(); + + //then + assertEquals(round(expected), actual.asMicrogramsPerCubicMeters()); } @Test - public void getNitrogenDioxide() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final double value = 0.55; - airPollutionRecord.setNO2(value); + public void testGetCarbonMonoxide_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + final AirPollutionMeasurements components = new AirPollutionMeasurements(); + final BigDecimal expected = new BigDecimal("201.94053649902344"); + components.setCarbonMonoxide(new Concentration(expected)); + underTest.setComponents(components); - assertEquals(value, airPollutionRecord.getNitrogenDioxide(), 0.00001); + //when + final Concentration actual = underTest.getCarbonMonoxide(); + + //then + assertEquals(round(expected), actual.asMicrogramsPerCubicMeters()); } @Test - public void getOzone() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final double value = 0.55; - airPollutionRecord.setO3(value); + public void testGetNitrogenMonoxide_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + final AirPollutionMeasurements components = new AirPollutionMeasurements(); + final BigDecimal expected = new BigDecimal("0.01877197064459324"); + components.setNitrogenMonoxide(new Concentration(expected)); + underTest.setComponents(components); - assertEquals(value, airPollutionRecord.getOzone(), 0.00001); + //when + final Concentration actual = underTest.getNitrogenMonoxide(); + + //then + assertEquals(round(expected), actual.asMicrogramsPerCubicMeters()); } @Test - public void getSulphurDioxide() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final double value = 0.55; - airPollutionRecord.setSO2(value); + public void testGetNitrogenDioxide_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + final AirPollutionMeasurements components = new AirPollutionMeasurements(); + final BigDecimal expected = new BigDecimal("0.7711350917816162"); + components.setNitrogenDioxide(new Concentration(expected)); + underTest.setComponents(components); - assertEquals(value, airPollutionRecord.getSulphurDioxide(), 0.00001); + //when + final Concentration actual = underTest.getNitrogenDioxide(); + + //then + assertEquals(round(expected), actual.asMicrogramsPerCubicMeters()); } @Test - public void getFineParticlesMatter() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final double value = 0.55; - airPollutionRecord.setPM2_5(value); + public void testGetSulphurDioxide_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + final AirPollutionMeasurements components = new AirPollutionMeasurements(); + final BigDecimal expected = new BigDecimal("0.6407499313354492"); + components.setSulphurDioxide(new Concentration(expected)); + underTest.setComponents(components); - assertEquals(value, airPollutionRecord.getFineParticlesMatter(), 0.00001); + //when + final Concentration actual = underTest.getSulphurDioxide(); + + //then + assertEquals(round(expected), actual.asMicrogramsPerCubicMeters()); } @Test - public void getCoarseParticulateMatter() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final double value = 0.55; - airPollutionRecord.setPM10(value); + public void testGetFineParticlesMatter_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + final AirPollutionMeasurements components = new AirPollutionMeasurements(); + final BigDecimal expected = BigDecimal.valueOf(0.5); + components.setFineParticlesMatter(new Concentration(expected)); + underTest.setComponents(components); - assertEquals(value, airPollutionRecord.getCoarseParticulateMatter(), 0.00001); + //when + final Concentration actual = underTest.getFineParticlesMatter(); + + //then + assertEquals(round(expected), actual.asMicrogramsPerCubicMeters()); } @Test - public void getAmmonia() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final double value = 0.55; - airPollutionRecord.setNH3(value); + public void testGetCoarseParticulateMatter_ShouldReturnPreviouslySetValue_WhenCalled() { + //given + final AirPollutionRecord underTest = new AirPollutionRecord(); + final AirPollutionMeasurements components = new AirPollutionMeasurements(); + final BigDecimal expected = new BigDecimal("0.540438711643219"); + components.setCoarseParticulateMatter(new Concentration(expected)); + underTest.setComponents(components); - assertEquals(value, airPollutionRecord.getAmmonia()); + //when + final Concentration actual = underTest.getCoarseParticulateMatter(); + + //then + assertEquals(round(expected), actual.asMicrogramsPerCubicMeters()); } - @Test - public void testEquals() { - final AirPollutionRecord first = new AirPollutionRecord(); - final AirPollutionRecord second = new AirPollutionRecord(); - final LocalDateTime now = LocalDateTime.now(); - final AirQualityIndex aqi = AirQualityIndex.GOOD; - final double value = 0.55; - - assertEquals(first, first); - assertNotEquals(first, null); - assertEquals(first, second); - assertNotEquals(first, new Object()); - - assertEquals(first, second); - - first.setForecastTime(now); - - assertNotEquals(first, second); - - second.setForecastTime(now); - - assertEquals(first, second); - - first.setAirQualityIndex(aqi); - - assertNotEquals(first, second); - - second.setAirQualityIndex(aqi); - - assertEquals(first, second); - - first.setCO(value); - - assertNotEquals(first, second); - - second.setCO(value); - - assertEquals(first, second); - - first.setNO(value); - - assertNotEquals(first, second); - - second.setNO(value); - - assertEquals(first, second); - - first.setNO2(value); - - assertNotEquals(first, second); - - second.setNO2(value); - - assertEquals(first, second); - - first.setO3(value); - - assertNotEquals(first, second); - - second.setO3(value); - - assertEquals(first, second); - - first.setSO2(value); - - assertNotEquals(first, second); - - second.setSO2(value); - - assertEquals(first, second); - - first.setPM2_5(value); - - assertNotEquals(first, second); - - second.setPM2_5(value); - - assertEquals(first, second); - - first.setPM10(value); - - assertNotEquals(first, second); - - second.setPM10(value); - - assertEquals(first, second); - - first.setNH3(value); - - assertNotEquals(first, second); - - second.setNH3(value); - - assertEquals(first, second); + private static BigDecimal round(BigDecimal expected) { + return expected.setScale(10, RoundingMode.HALF_EVEN); } - - @Test - public void testHashCode() { - final AirPollutionRecord first = new AirPollutionRecord(); - final AirPollutionRecord second = new AirPollutionRecord(); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setSO2(33.2); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void testToString() { - final AirPollutionRecord airPollutionRecord = new AirPollutionRecord(); - final LocalDateTime now = LocalDateTime.now(); - final AirQualityIndex aqi = AirQualityIndex.GOOD; - final double value = 0.55; - - airPollutionRecord.setForecastTime(now); - airPollutionRecord.setAirQualityIndex(aqi); - - assertNotNull(airPollutionRecord.toString()); - - airPollutionRecord.setCO(value); - - assertNotNull(airPollutionRecord.toString()); - - airPollutionRecord.setNO(value); - - assertNotNull(airPollutionRecord.toString()); - - airPollutionRecord.setNO2(value); - - assertNotNull(airPollutionRecord.toString()); - - airPollutionRecord.setO3(value); - - assertNotNull(airPollutionRecord.toString()); - - airPollutionRecord.setSO2(value); - - assertNotNull(airPollutionRecord.toString()); - - airPollutionRecord.setPM2_5(value); - - assertNotNull(airPollutionRecord.toString()); - - airPollutionRecord.setPM10(value); - - assertNotNull(airPollutionRecord.toString()); - - airPollutionRecord.setNH3(value); - - assertNotNull(airPollutionRecord.toString()); - - airPollutionRecord.setCO(null); - - assertNotNull(airPollutionRecord.toString()); - } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/ForecastUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/ForecastUnitTest.java deleted file mode 100644 index 42d3968..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/ForecastUnitTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.free; - -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; - -import static org.junit.jupiter.api.Assertions.*; - -public class ForecastUnitTest { - @Test - public void whenLocationIsSet_thenAllIsOk() { - final Forecast forecast = new Forecast(); - forecast.setLocation(Location.withValues(2, "asd")); - - assertNotNull(forecast.getLocation()); - } - - @Test - public void whenWeatherForecastsAreSet_thenAllIsOk() { - final Forecast forecast = new Forecast(); - forecast.setWeatherForecasts(new ArrayList<>()); - - assertNotNull(forecast.getWeatherForecasts()); - } - - @Test - public void whenCalculateHashCode_thenAllIsOk() { - final Forecast one = new Forecast(); - final Forecast two = new Forecast(); - - assertEquals(one.hashCode(), two.hashCode()); - - one.setLocation(Location.withValues(22, "444")); - - assertNotEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsOk() { - final Forecast one = new Forecast(); - final Forecast two = new Forecast(); - - assertEquals(one, one); - assertNotEquals(one, null); - assertEquals(one, two); - assertNotEquals(one, new Object()); - - one.setLocation(Location.withValues(22, "234")); - - assertNotEquals(one, two); - - two.setLocation(one.getLocation()); - - assertEquals(one, two); - - one.setWeatherForecasts(new ArrayList<>()); - - assertNotEquals(one, two); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationUnitTest.java deleted file mode 100644 index 839bb2d..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/LocationUnitTest.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * 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.free; - -import com.github.prominence.openweathermap.api.model.Coordinates; -import org.junit.jupiter.api.Test; - -import java.time.LocalDateTime; -import java.time.ZoneOffset; - -import static org.junit.jupiter.api.Assertions.*; - -public class LocationUnitTest { - @Test - public void whenCreateObjectWithValidArgs_thenObjectIsCreated() { - Location.withValues(33, "test"); - } - - @Test - public void whenCreateObjectWithoutName_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Location.withValues(33, null)); - } - - @Test - public void whenSetId_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - location.setId(55); - - assertEquals(55, location.getId()); - } - - @Test - public void whenSetName_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - location.setName("city"); - - assertEquals("city", location.getName()); - } - - @Test - public void whenSetCountryCode_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - location.setCountryCode("by"); - - assertEquals("by", location.getCountryCode()); - } - - @Test - public void whenSetSunrise_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - final LocalDateTime now = LocalDateTime.now(); - location.setSunriseTime(now); - - assertEquals(now, location.getSunriseTime()); - } - - @Test - public void whenSetSunset_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - final LocalDateTime now = LocalDateTime.now(); - location.setSunsetTime(now); - - assertEquals(now, location.getSunsetTime()); - } - - @Test - public void whenSetZoneOffset_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - final ZoneOffset offset = ZoneOffset.UTC; - location.setZoneOffset(offset); - - assertEquals(offset, location.getZoneOffset()); - } - - @Test - public void whenSetCoordinate_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - final Coordinates coordinates = Coordinates.of(33.2, 64.2); - location.setCoordinates(coordinates); - - assertEquals(coordinates, location.getCoordinates()); - } - - @Test - public void whenSetPopulation_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - location.setPopulation(3444L); - - assertEquals(3444L, location.getPopulation().longValue()); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final Location location = Location.withValues(44, "test"); - - assertNotEquals("", location.toString()); - - location.setCoordinates(Coordinates.of(33.2, 56.3)); - - assertNotEquals("", location.toString()); - - location.setCountryCode("TN"); - - assertNotEquals("", location.toString()); - assertNotNull(location.toString()); - - location.setPopulation(34343L); - assertNotEquals("", location.toString()); - assertNotNull(location.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Location one = Location.withValues(44, "test"); - final Location two = Location.withValues(44, "test"); - - assertEquals(one.hashCode(), two.hashCode()); - - two.setName("112"); - - assertNotEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Location one = Location.withValues(44, "test"); - final Location two = Location.withValues(44, "test"); - - assertEquals(one, one); - assertNotEquals(one, new Object()); - - assertEquals(one, two); - - two.setId(23); - - assertNotEquals(one, two); - - one.setId(23); - - assertEquals(one, two); - - one.setName("23"); - - assertNotEquals(one, two); - - two.setName("23"); - - assertEquals(one, two); - - one.setCountryCode("11"); - - assertNotEquals(one, two); - - two.setCountryCode("11"); - - assertEquals(one, two); - - final LocalDateTime now = LocalDateTime.now(); - - one.setSunriseTime(now); - - assertNotEquals(one, two); - - two.setSunriseTime(now); - - assertEquals(one, two); - - one.setSunsetTime(now); - - assertNotEquals(one, two); - - two.setSunsetTime(now); - - assertEquals(one, two); - - one.setZoneOffset(ZoneOffset.UTC); - - assertNotEquals(one, two); - - two.setZoneOffset(ZoneOffset.UTC); - - assertEquals(one, two); - - final Coordinates coordinates = Coordinates.of(33.5, -22.4); - - one.setCoordinates(coordinates); - - assertNotEquals(one, two); - - two.setCoordinates(coordinates); - - assertEquals(one, two); - - one.setPopulation(20000L); - - assertNotEquals(one, two); - - two.setPopulation(20000L); - - assertEquals(one, two); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/RainUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/RainUnitTest.java deleted file mode 100644 index 2b1807e..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/RainUnitTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.free; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class RainUnitTest { - @Test - public void whenCreateRainWithValidArgs_thenObjectIsCreated() { - Rain.withThreeHourLevelValue(2222.3); - Rain.withThreeHourLevelValue(0); - } - - @Test - public void whenCreateWithInvalidData_thenFail() { - assertThrows(IllegalArgumentException.class, () -> Rain.withThreeHourLevelValue(-20)); - } - - @Test - public void whenSetValues_thenTheyAreSet() { - final Rain rain = Rain.withThreeHourLevelValue(0); - - assertEquals(0, rain.getThreeHourLevel(), 0.00001); - - rain.setThreeHourLevel(55.5); - assertEquals(55.5, rain.getThreeHourLevel(), 0.00001); - } - - @Test - public void whenSetInvalidValue_thenFail() { - final Rain rain = Rain.withThreeHourLevelValue(0); - - assertThrows(IllegalArgumentException.class, () -> rain.setThreeHourLevel(-20)); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final Rain rain = Rain.withThreeHourLevelValue(33.5); - - assertNotNull(rain.toString()); - assertNotEquals("", rain.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Rain first = Rain.withThreeHourLevelValue(0); - final Rain second = Rain.withThreeHourLevelValue(0); - - assertEquals(first.hashCode(), second.hashCode()); - - second.setThreeHourLevel(11.0); - - assertNotEquals(first.hashCode(), second.hashCode()); - - first.setThreeHourLevel(11.0); - - assertEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Rain first = Rain.withThreeHourLevelValue(0); - final Rain second = Rain.withThreeHourLevelValue(0); - - assertEquals(first, second); - assertEquals(first, first); - assertNotEquals(first, new Object()); - - second.setThreeHourLevel(66.7); - - assertNotEquals(first, second); - - first.setThreeHourLevel(66.7); - - assertEquals(first, second); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/SnowUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/SnowUnitTest.java deleted file mode 100644 index b4b65fa..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/SnowUnitTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.free; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class SnowUnitTest { - @Test - public void whenCreateSnowWithValidArgs_ObjectIsCreated() { - Snow.withThreeHourLevelValue(2222.3); - Snow.withThreeHourLevelValue(0); - } - - @Test - public void whenCreateWithInvalidData_thenFail() { - assertThrows(IllegalArgumentException.class, () -> Snow.withThreeHourLevelValue(-20)); - } - - @Test - public void whenSetValues_thenTheyAreSet() { - final Snow snow = Snow.withThreeHourLevelValue(0); - - assertEquals(0, snow.getThreeHourLevel(), 0.00001); - - snow.setThreeHourLevel(55.5); - assertEquals(55.5, snow.getThreeHourLevel(), 0.00001); - } - - @Test - public void whenSetInvalidValue_thenFail() { - final Snow snow = Snow.withThreeHourLevelValue(0); - - assertThrows(IllegalArgumentException.class, () -> snow.setThreeHourLevel(-20)); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final Snow snow = Snow.withThreeHourLevelValue(33.5); - - assertNotNull(snow.toString()); - assertNotEquals("", snow.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Snow first = Snow.withThreeHourLevelValue(0); - final Snow second = Snow.withThreeHourLevelValue(0); - - assertEquals(first.hashCode(), second.hashCode()); - - second.setThreeHourLevel(11.0); - - assertNotEquals(first.hashCode(), second.hashCode()); - - first.setThreeHourLevel(11.0); - - assertEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Snow first = Snow.withThreeHourLevelValue(0); - final Snow second = Snow.withThreeHourLevelValue(0); - - assertEquals(first, second); - assertEquals(first, first); - assertNotEquals(first, new Object()); - - second.setThreeHourLevel(66.7); - - assertNotEquals(first, second); - - first.setThreeHourLevel(66.7); - - assertEquals(first, second); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecastUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecastUnitTest.java deleted file mode 100644 index e40946e..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WeatherForecastUnitTest.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * 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.free; - -import com.github.prominence.openweathermap.api.model.*; -import org.junit.jupiter.api.Test; - -import java.time.LocalDateTime; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -public class WeatherForecastUnitTest { - @Test - public void whenSetForecastTime_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - final LocalDateTime now = LocalDateTime.now(); - weatherForecast.setForecastTime(now); - - assertEquals(now, weatherForecast.getForecastTime()); - } - - @Test - public void whenSetTemperature_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - final Temperature temperature = Temperature.withValue(22.3, "a"); - weatherForecast.setTemperature(temperature); - - assertEquals(temperature, weatherForecast.getTemperature()); - } - - @Test - public void whenSetPressure_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(33.2); - weatherForecast.setAtmosphericPressure(atmosphericPressure); - - assertEquals(atmosphericPressure, weatherForecast.getAtmosphericPressure()); - } - - @Test - public void whenSetHumidity_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - final Humidity humidity = Humidity.withValue((byte) 44); - weatherForecast.setHumidity(humidity); - - assertEquals(humidity, weatherForecast.getHumidity()); - } - - @Test - public void whenSetWind_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - final Wind wind = Wind.withValue(22.2, "a"); - weatherForecast.setWind(wind); - - assertEquals(wind, weatherForecast.getWind()); - } - - @Test - public void whenSetRain_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - final Rain rain = Rain.withThreeHourLevelValue(0); - weatherForecast.setRain(rain); - - assertEquals(rain, weatherForecast.getRain()); - } - - @Test - public void whenSetSnow_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - final Snow snow = Snow.withThreeHourLevelValue(0); - weatherForecast.setSnow(snow); - - assertEquals(snow, weatherForecast.getSnow()); - } - - @Test - public void whenSetClouds_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - final Clouds clouds = Clouds.withValue((byte) 33); - weatherForecast.setClouds(clouds); - - assertEquals(clouds, weatherForecast.getClouds()); - } - - @Test - public void whenSetForecastTimeISO_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - - assertNull(weatherForecast.getForecastTimeISO()); - - weatherForecast.setForecastTimeISO("1994-2-3"); - - assertEquals("1994-2-3", weatherForecast.getForecastTimeISO()); - } - - @Test - public void whenSetDayTime_thenValueIsSet() { - final WeatherForecast weatherForecast = new WeatherForecast(); - - assertNull(weatherForecast.getDayTime()); - - weatherForecast.setDayTime(DayTime.DAY); - - assertEquals(DayTime.DAY, weatherForecast.getDayTime()); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final WeatherForecast weatherForecast = new WeatherForecast(); - final Location location = Location.withValues(12312, "asd"); - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - final Temperature temperature = Temperature.withValue(33.2, "asd"); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(44.4); - final Clouds clouds = Clouds.withValue((byte) 55); - final Rain rain = Rain.withThreeHourLevelValue(33.2); - final Snow snow = Snow.withThreeHourLevelValue(33.1); - - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setWeatherStates(List.of(weatherState)); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - location.setCountryCode("3d"); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setTemperature(temperature); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setAtmosphericPressure(atmosphericPressure); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setClouds(clouds); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setRain(rain); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setSnow(snow); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setRain(null); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setSnow(null); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setRain(Rain.withThreeHourLevelValue(0)); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - - weatherForecast.setSnow(Snow.withThreeHourLevelValue(0)); - assertNotEquals("", weatherForecast.toString()); - assertNotNull(weatherForecast.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final WeatherForecast first = new WeatherForecast(); - final WeatherForecast second = new WeatherForecast(); - - assertEquals(first.hashCode(), second.hashCode()); - - second.setDayTime(DayTime.NIGHT); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final WeatherForecast first = new WeatherForecast(); - final WeatherForecast second = new WeatherForecast(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - assertEquals(first, second); - - final LocalDateTime now = LocalDateTime.now(); - first.setForecastTime(now); - - assertNotEquals(first, second); - - second.setForecastTime(now); - - assertEquals(first, second); - - final Temperature temperature = Temperature.withValue(33.2, "as"); - first.setTemperature(temperature); - - assertNotEquals(first, second); - - second.setTemperature(temperature); - - assertEquals(first, second); - - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - first.setWeatherStates(List.of(weatherState)); - - assertNotEquals(first, second); - - second.setWeatherStates(List.of(weatherState)); - - assertEquals(first, second); - - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(33.33); - first.setAtmosphericPressure(atmosphericPressure); - - assertNotEquals(first, second); - - second.setAtmosphericPressure(atmosphericPressure); - - assertEquals(first, second); - - final Humidity humidity = Humidity.withValue((byte) 33); - first.setHumidity(humidity); - - assertNotEquals(first, second); - - second.setHumidity(humidity); - - assertEquals(first, second); - - final Wind wind = Wind.withValue(33.6, "asd"); - first.setWind(wind); - - assertNotEquals(first, second); - - second.setWind(wind); - - assertEquals(first, second); - - final Rain rain = Rain.withThreeHourLevelValue(0); - first.setRain(rain); - - assertNotEquals(first, second); - - second.setRain(rain); - - assertEquals(first, second); - - final Snow snow = Snow.withThreeHourLevelValue(0); - first.setSnow(snow); - - assertNotEquals(first, second); - - second.setSnow(snow); - - assertEquals(first, second); - - final Clouds clouds = Clouds.withValue((byte) 33); - first.setClouds(clouds); - - assertNotEquals(first, second); - - second.setClouds(clouds); - - assertEquals(first, second); - - first.setForecastTimeISO("test"); - - assertNotEquals(first, second); - - second.setForecastTimeISO("test"); - - assertEquals(first, second); - - first.setDayTime(DayTime.NIGHT); - - assertNotEquals(first, second); - - second.setDayTime(DayTime.DAY); - - assertNotEquals(first, second); - - first.setDayTime(DayTime.DAY); - - assertEquals(first, second); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WindUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WindUnitTest.java deleted file mode 100644 index 347732c..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/forecast/free/WindUnitTest.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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.free; - -import com.github.prominence.openweathermap.api.model.Wind; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class WindUnitTest { - @Test - public void whenCreateWindWithValidArgs_thenValueIsSet() { - assertEquals(44.0, Wind.withValue(44, "ms").getSpeed(), 0.00001); - } - - @Test - public void whenCreateWindWithInvalidSpeedArg_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Wind.withValue(-21, "a")); - } - - @Test - public void whenCreateWindWithInvalidUnitArg_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Wind.withValue(342, null)); - } - - @Test - public void whenSetValidSpeed_thenValueIsSet() { - final Wind wind = Wind.withValue(33, "as"); - - assertEquals(33, wind.getSpeed(), 0.00001); - - wind.setSpeed(0); - - assertEquals(0, wind.getSpeed(), 0.00001); - - wind.setSpeed(3656); - - assertEquals(3656, wind.getSpeed(), 0.00001); - } - - @Test - public void whenSetInvalidSpeedBelow0_thenThrowAnException() { - final Wind wind = Wind.withValue(33, "as"); - - assertEquals(33, wind.getSpeed(), 0.00001); - - assertThrows(IllegalArgumentException.class, () -> wind.setSpeed(-22)); - } - - @Test - public void whenSetValidDegrees_thenValueIsSet() { - final Wind wind = Wind.withValue(33, "as"); - - assertNull(wind.getDegrees()); - - wind.setDegrees(22); - - assertEquals(22, wind.getDegrees(), 0.00001); - - wind.setDegrees(0); - - assertEquals(0, wind.getDegrees(), 0.00001); - - wind.setDegrees(360); - - assertEquals(360, wind.getDegrees(), 0.00001); - } - - @Test - public void whenSetInvalidDegreesBelow0_thenThrowAnException() { - final Wind wind = Wind.withValue(33, "as"); - assertThrows(IllegalArgumentException.class, () -> wind.setDegrees(-32)); - } - - @Test - public void whenSetInvalidDegreesAbove360_thenThrowAnException() { - final Wind wind = Wind.withValue(33, "as"); - assertThrows(IllegalArgumentException.class, () -> wind.setDegrees(378)); - } - - @Test - public void whenSetNonNullUnit_thenValueIsSet() { - final Wind wind = Wind.withValue(33, "as"); - - assertEquals(wind.getUnit(), "as"); - - wind.setUnit("myUnit"); - - assertEquals(wind.getUnit(), "myUnit"); - } - - @Test - public void whenSetNullUnit_thenThrowAnException() { - final Wind wind = Wind.withValue(33, "as"); - - assertThrows(IllegalArgumentException.class, () -> wind.setUnit(null)); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final Wind wind = Wind.withValue(302, "a"); - - assertNotNull(wind.toString()); - - wind.setDegrees(22); - - assertNotNull(wind.toString()); - assertNotEquals("", wind.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Wind first = Wind.withValue(22, "a"); - final Wind second = Wind.withValue(22, "b"); - - assertNotEquals(first.hashCode(), second.hashCode()); - - second.setUnit("a"); - - assertEquals(first.hashCode(), second.hashCode()); - - second.setSpeed(33); - - assertNotEquals(first.hashCode(), second.hashCode()); - - first.setSpeed(333); - - assertNotEquals(first.hashCode(), second.hashCode()); - - first.setSpeed(33); - - assertEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Wind first = Wind.withValue(11, "a"); - final Wind second = Wind.withValue(12, "a"); - - assertNotEquals(first, second); - first.setSpeed(12); - - assertEquals(first, second); - assertEquals(first, first); - assertNotEquals(first, new Object()); - - first.setDegrees(34); - - assertNotEquals(first, second); - - second.setDegrees(34); - - assertEquals(first, second); - - second.setUnit("v"); - - assertNotEquals(first, second); - - first.setUnit("v"); - - assertEquals(first, second); - - first.setSpeed(second.getSpeed() + 4); - - assertNotEquals(first, second); - } -} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastSnowDeserializer.java b/src/test/java/com/github/prominence/openweathermap/api/model/free/RainUnitTest.java similarity index 57% rename from src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastSnowDeserializer.java rename to src/test/java/com/github/prominence/openweathermap/api/model/free/RainUnitTest.java index 7f2e9c6..07b726a 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/deserializer/forecast/free/FreeForecastSnowDeserializer.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/free/RainUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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,25 +20,22 @@ * SOFTWARE. */ -package com.github.prominence.openweathermap.api.deserializer.forecast.free; +package com.github.prominence.openweathermap.api.model.free; -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.free.Snow; +import com.github.prominence.openweathermap.api.model.forecast.free.Precipitation; +import org.junit.jupiter.api.Test; -import java.io.IOException; +import java.math.BigDecimal; -public class FreeForecastSnowDeserializer 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("3h"); - if (oneHourNode != null) { - return Snow.withThreeHourLevelValue(oneHourNode.asDouble()); - } - return null; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class RainUnitTest { + + @Test + public void getOneHourRainLevel() { + final Precipitation rain = new Precipitation(); + rain.setThreeHourLevel(BigDecimal.valueOf(220.0)); + + assertEquals(BigDecimal.valueOf(220.0), rain.getThreeHourLevel()); } } diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationIntensityTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationIntensityTest.java new file mode 100644 index 0000000..f4e608f --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/model/generic/precipitation/PrecipitationIntensityTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021-present 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.generic.precipitation; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PrecipitationIntensityTest { + + public static Stream millimetersPerHourProvider() { + return Stream.of(1d, 2.0, 3.1415, 42d) + .map(BigDecimal::valueOf) + .map(v -> Arguments.of(v, v.setScale(1, RoundingMode.HALF_EVEN))); + } + + public static Stream millimetersPerMinuteProvider() { + return Stream.of(1d, 2.0, 3.1415, 42d) + .map(BigDecimal::valueOf) + .map(v -> Arguments.of(v, v.divide(BigDecimal.valueOf(60), RoundingMode.HALF_EVEN).setScale(1, RoundingMode.HALF_EVEN))); + } + + @ParameterizedTest + @MethodSource("millimetersPerHourProvider") + void testAsMillimetersPerHour_ShouldReturnRoundedValue_WhenCalled(final BigDecimal value, final BigDecimal expected) { + //given + final PrecipitationIntensity underTest = new PrecipitationIntensity(value); + + //when + final BigDecimal actual = underTest.asMillimetersPerHour(); + + //then + assertEquals(expected, actual); + } + + @ParameterizedTest + @MethodSource("millimetersPerMinuteProvider") + void testAsMillimetersPerMinute_ShouldReturnRoundedAndConvertedValue_WhenCalled(final BigDecimal value, final BigDecimal expected) { + //given + final PrecipitationIntensity underTest = new PrecipitationIntensity(value); + + //when + final BigDecimal actual = underTest.asMillimetersPerMinute(); + + //then + assertEquals(expected, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureValueTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureValueTest.java new file mode 100644 index 0000000..470e44a --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/model/generic/temperature/TemperatureValueTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021-present 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.generic.temperature; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class TemperatureValueTest { + + + public static Stream validValueProvider() { + return Stream.builder() + .add(Arguments.of(BigDecimal.ZERO, BigDecimal.valueOf(-459.67), BigDecimal.valueOf(-273.15))) + .add(Arguments.of(BigDecimal.valueOf(273.15), BigDecimal.valueOf(32), BigDecimal.ZERO)) + .add(Arguments.of(BigDecimal.valueOf(313.15), BigDecimal.valueOf(104), BigDecimal.valueOf(40))) + .build(); + } + + @SuppressWarnings("unused") + @ParameterizedTest + @MethodSource("validValueProvider") + void testAsKelvin_ShouldRoundDecimalPlaces_WhenCalled( + final BigDecimal kelvin, final BigDecimal fahrenheit, final BigDecimal celsius) { + //given + final TemperatureValue underTest = new TemperatureValue(kelvin); + + //when + final BigDecimal actual = underTest.asKelvin(); + + //then + assertEquals(normalize(kelvin), actual); + } + + @SuppressWarnings("unused") + @ParameterizedTest + @MethodSource("validValueProvider") + void testAsCelsius_ShouldConvertAndRoundDecimalPlaces_WhenCalled( + final BigDecimal kelvin, final BigDecimal fahrenheit, final BigDecimal celsius) { + //given + final TemperatureValue underTest = new TemperatureValue(kelvin); + + //when + final BigDecimal actual = underTest.asCelsius(); + + //then + assertEquals(normalize(celsius), actual); + } + + @SuppressWarnings("unused") + @ParameterizedTest + @MethodSource("validValueProvider") + void testAsFahrenheit_ShouldConvertAndRoundDecimalPlaces_WhenCalled( + final BigDecimal kelvin, final BigDecimal fahrenheit, final BigDecimal celsius) { + //given + final TemperatureValue underTest = new TemperatureValue(kelvin); + + //when + final BigDecimal actual = underTest.asFahrenheit(); + + //then + assertEquals(normalize(fahrenheit), actual); + } + + private static BigDecimal normalize(BigDecimal value) { + return value.setScale(0, RoundingMode.HALF_EVEN); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/generic/visibility/VisibilityTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/generic/visibility/VisibilityTest.java new file mode 100644 index 0000000..7d21e1d --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/model/generic/visibility/VisibilityTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021-present 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.generic.visibility; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class VisibilityTest { + + public static Stream visibilityInputProvider() { + return Stream.builder() + .add(Arguments.of(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)) + .add(Arguments.of(BigDecimal.ONE, BigDecimal.valueOf(0.00), BigDecimal.valueOf(0.00))) + .add(Arguments.of(BigDecimal.TEN, BigDecimal.valueOf(0.01), BigDecimal.valueOf(0.01))) + .add(Arguments.of(BigDecimal.valueOf(42.0), BigDecimal.valueOf(0.04), BigDecimal.valueOf(0.03))) + .add(Arguments.of(BigDecimal.valueOf(42000.0), BigDecimal.valueOf(42.00), BigDecimal.valueOf(26.10))) + .build(); + } + + @SuppressWarnings("unused") + @ParameterizedTest + @MethodSource("visibilityInputProvider") + void testAsMeters_ShouldReturnRoundedValue_WhenCalled( + final BigDecimal meters, final BigDecimal kilometers, final BigDecimal miles) { + //given + final Visibility underTest = new Visibility(meters); + + //when + final BigDecimal actual = underTest.asMeters(); + + //then + assertEquals(normalize(meters), actual); + } + + @SuppressWarnings("unused") + @ParameterizedTest + @MethodSource("visibilityInputProvider") + void testAsMiles_ShouldReturnRoundedValue_WhenCalled( + final BigDecimal meters, final BigDecimal kilometers, final BigDecimal miles) { + //given + final Visibility underTest = new Visibility(meters); + + //when + final BigDecimal actual = underTest.asMiles(); + + //then + assertEquals(normalize(miles), actual); + } + + @SuppressWarnings("unused") + @ParameterizedTest + @MethodSource("visibilityInputProvider") + void testAsKilometers_ShouldReturnRoundedValue_WhenCalled( + final BigDecimal meters, final BigDecimal kilometers, final BigDecimal miles) { + //given + final Visibility underTest = new Visibility(meters); + + //when + final BigDecimal actual = underTest.asKilometers(); + + //then + assertEquals(normalize(kilometers), actual); + } + + private static BigDecimal normalize(BigDecimal value) { + return value.setScale(2, RoundingMode.HALF_EVEN); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/generic/wind/WindSpeedTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/generic/wind/WindSpeedTest.java new file mode 100644 index 0000000..2584ffb --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/model/generic/wind/WindSpeedTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021-present 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.generic.wind; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.stream.Stream; + +class WindSpeedTest { + + public static Stream speedInputProvider() { + return Stream.builder() + .add(Arguments.of(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)) + .add(Arguments.of(BigDecimal.ONE, BigDecimal.valueOf(0.44704), BigDecimal.valueOf(1.60934))) + .add(Arguments.of(BigDecimal.TEN, BigDecimal.valueOf(4.47040), BigDecimal.valueOf(16.0934))) + .add(Arguments.of(BigDecimal.valueOf(42.0), BigDecimal.valueOf(18.77568), BigDecimal.valueOf(67.59228))) + .build(); + } + + @SuppressWarnings("ConstantConditions") + @Test + void testConstructor_ShouldThrowException_WhenCalledWithNull() { + //given + + //when + Assertions.assertThrows(IllegalArgumentException.class, () -> new WindSpeed(null)); + + //then + exception + } + + @SuppressWarnings("unused") + @ParameterizedTest + @MethodSource("speedInputProvider") + void testAsMetersPerSecond_ShouldReturnMeterSPerSecondValueRoundedTo2Decimals_WhenCalled( + final BigDecimal milesPerHOur, final BigDecimal metersPerSecond, final BigDecimal kilometersPerHour) { + //given + final WindSpeed underTest = new WindSpeed(metersPerSecond); + + //when + final BigDecimal actual = underTest.asMetersPerSecond(); + + //then + Assertions.assertEquals(normalize(metersPerSecond), actual); + } + + @SuppressWarnings("unused") + @ParameterizedTest + @MethodSource("speedInputProvider") + void testAsMilesPerHour_ShouldReturnMeterSPerSecondValueConvertedAndRoundedTo2Decimals_WhenCalled( + final BigDecimal milesPerHOur, final BigDecimal metersPerSecond, final BigDecimal kilometersPerHour) { + //given + final WindSpeed underTest = new WindSpeed(metersPerSecond); + + //when + final BigDecimal actual = underTest.asMilesPerHour(); + + //then + Assertions.assertEquals(normalize(milesPerHOur), actual); + } + + @SuppressWarnings("unused") + @ParameterizedTest + @MethodSource("speedInputProvider") + void testAsKilometersPerHour_ShouldReturnMeterSPerSecondValueConvertedAndRoundedTo2Decimals_WhenCalled( + final BigDecimal milesPerHOur, final BigDecimal metersPerSecond, final BigDecimal kilometersPerHour) { + //given + final WindSpeed underTest = new WindSpeed(metersPerSecond); + + //when + final BigDecimal actual = underTest.asKilometersPerHour(); + + //then + Assertions.assertEquals(normalize(kilometersPerHour), actual); + } + + private static BigDecimal normalize(BigDecimal metersPerSecond) { + return metersPerSecond.setScale(2, RoundingMode.HALF_EVEN); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/AtmosphericPressureUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/AtmosphericPressureUnitTest.java deleted file mode 100644 index 64e1a67..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/AtmosphericPressureUnitTest.java +++ /dev/null @@ -1,85 +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 org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class AtmosphericPressureUnitTest { - @Test - public void withInvalidValue_negative() { - assertThrows(IllegalArgumentException.class, () -> AtmosphericPressure.withValue(-20.0)); - } - - @Test - public void getSeaLevelValue() { - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.2); - - assertEquals(22.2, atmosphericPressure.getSeaLevelValue(), 0.00001); - } - - @Test - public void getUnit() { - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.2); - - assertNotNull(atmosphericPressure.getUnit()); - assertNotEquals("", atmosphericPressure.getUnit()); - } - - @Test - public void testEquals() { - final AtmosphericPressure first = AtmosphericPressure.withValue(600); - final AtmosphericPressure second = AtmosphericPressure.withValue(600); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - assertEquals(first, second); - - first.setSeaLevelValue(200); - - assertNotEquals(first, second); - } - - @Test - public void testHashCode() { - final AtmosphericPressure first = AtmosphericPressure.withValue(600); - final AtmosphericPressure second = AtmosphericPressure.withValue(600); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setSeaLevelValue(200); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void testToString() { - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.2); - - assertNotNull(atmosphericPressure.toString()); - assertNotEquals("", atmosphericPressure.toString()); - } -} \ No newline at end of file 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 3adeef4..d32d483 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,22 +22,25 @@ 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 com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.precipitation.BasePrecipitation; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; import org.junit.jupiter.api.Test; -import java.time.LocalDateTime; -import java.util.List; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collections; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; public class CurrentUnitTest { @Test public void getForecastTime() { - final Current current = new Current(); - final LocalDateTime now = LocalDateTime.now(); + final BaseMeasurement current = new BaseMeasurement(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); current.setForecastTime(now); assertEquals(now, current.getForecastTime()); @@ -45,8 +48,8 @@ public class CurrentUnitTest { @Test public void getSunriseTime() { - final Current current = new Current(); - final LocalDateTime now = LocalDateTime.now(); + final BaseMeasurement current = new BaseMeasurement(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); current.setSunriseTime(now); assertEquals(now, current.getSunriseTime()); @@ -54,8 +57,8 @@ public class CurrentUnitTest { @Test public void getSunsetTime() { - final Current current = new Current(); - final LocalDateTime now = LocalDateTime.now(); + final BaseMeasurement current = new BaseMeasurement(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); current.setSunsetTime(now); assertEquals(now, current.getSunsetTime()); @@ -63,275 +66,95 @@ public class CurrentUnitTest { @Test public void getWeatherState() { - final Current current = new Current(); - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - current.setWeatherStates(List.of(weatherState)); + final BaseMeasurement current = new BaseMeasurement(); + final WeatherCondition weatherState = WeatherCondition.getById(800); + current.setWeatherStates(Collections.singletonList(weatherState)); assertEquals(weatherState, current.getWeatherStates().get(0)); } @Test public void getTemperature() { - final Current current = new Current(); - final Temperature temperature = Temperature.withValue(10, "K"); - - current.setTemperature(temperature); + final BaseMeasurement current = new BaseMeasurement(); + final TemperatureValue temperature = new TemperatureValue(BigDecimal.valueOf(10)); + final TemperatureValue temperatureFeelsLike = new TemperatureValue(BigDecimal.valueOf(100)); + current.setTemperatureMeasured(temperature); + current.setFeelsLike(temperatureFeelsLike); assertEquals(temperature, current.getTemperature()); + assertEquals(temperatureFeelsLike, current.getFeelsLike()); } @Test public void getAtmosphericPressure() { - final Current current = new Current(); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.3); - current.setAtmosphericPressure(atmosphericPressure); + final BaseMeasurement current = new BaseMeasurement(); + final BigDecimal atmosphericPressure = BigDecimal.valueOf(22.3); + current.setSeaLevel(atmosphericPressure); - assertEquals(atmosphericPressure, current.getAtmosphericPressure()); + assertEquals(atmosphericPressure, current.getSeaLevel()); } @Test public void getHumidity() { - final Current current = new Current(); - final Humidity humidity = Humidity.withValue((byte) 10); - current.setHumidity(humidity); + final BaseMeasurement current = new BaseMeasurement(); + final int humidity = 10; + current.setHumidityPercentage(humidity); - assertEquals(humidity, current.getHumidity()); + assertEquals(humidity, current.getHumidityPercentage()); } @Test public void getWind() { - final Current current = new Current(); - final Wind wind = Wind.withValue(13.2, "m/s"); - current.setWind(wind); + final BaseMeasurement current = new BaseMeasurement(); + final WindSpeed windSpeed = new WindSpeed(BigDecimal.valueOf(13.2)); + final WindSpeed windSpeedGust = new WindSpeed(BigDecimal.valueOf(15.2)); + final Integer windDirection = 123; + current.setSpeed(windSpeed); + current.setGust(windSpeedGust); + current.setDirectionDegrees(windDirection); - assertEquals(wind, current.getWind()); + assertEquals(windSpeed, current.getSpeed()); + assertEquals(windSpeedGust, current.getGust()); + assertEquals(windDirection, current.getDirectionDegrees()); } @Test public void getClouds() { - final Current current = new Current(); - final Clouds clouds = Clouds.withValue((byte) 25); - current.setClouds(clouds); + final BaseMeasurement current = new BaseMeasurement(); + final int clouds = 25; + current.setCoveragePercentage(clouds); - assertEquals(clouds, current.getClouds()); + assertEquals(clouds, current.getClouds().getCoveragePercentage()); } @Test public void getUvIndex() { - final Current current = new Current(); - final double uvIndex = 22.4; + final BaseMeasurement current = new BaseMeasurement(); + final BigDecimal uvIndex = BigDecimal.valueOf(22.4); current.setUvIndex(uvIndex); - assertEquals(uvIndex, current.getUvIndex(), 0.00001); + assertEquals(uvIndex, current.getUvIndex()); current.setUvIndex(null); assertNull(current.getUvIndex()); } - @Test - public void getIllegalUvIndexValue() { - final Current current = new Current(); - - assertThrows(IllegalArgumentException.class, () -> current.setUvIndex(-1.2)); - } - - @Test - public void getProbabilityOfPrecipitation() { - final Current current = new Current(); - final double vim = 120; - current.setVisibilityInMetres(vim); - - assertEquals(vim, current.getVisibilityInMetres(), 0.00001); - - current.setVisibilityInMetres(null); - - assertNull(current.getVisibilityInMetres()); - } - - @Test - public void getIllegalProbabilityOfPrecipitationValue_negative() { - final Current current = new Current(); - - assertThrows(IllegalArgumentException.class, () -> current.setVisibilityInMetres(-20.0)); - } - @Test public void getRain() { - final Current current = new Current(); - final Rain rain = Rain.withOneHourLevelValue(20.2); - current.setRain(rain); + final BaseMeasurement current = new BaseMeasurement(); + final BasePrecipitation rain = new BasePrecipitation(BigDecimal.valueOf(20.2)); + current.setRainModel(rain); - assertEquals(rain, current.getRain()); + assertEquals(rain.getOneHourLevel(), current.getRain()); } @Test public void getSnow() { - final Current current = new Current(); - final Snow snow = Snow.withOneHourLevelValue(25.0); - current.setSnow(snow); + final BaseMeasurement current = new BaseMeasurement(); + final BasePrecipitation snow = new BasePrecipitation(BigDecimal.valueOf(25.0)); + current.setSnowModel(snow); - assertEquals(snow, current.getSnow()); + assertEquals(snow.getOneHourLevel(), current.getSnow()); } - - @Test - public void getEquals() { - final LocalDateTime now = LocalDateTime.now(); - final Current first = new Current(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - final Current second = new Current(); - - assertEquals(first, second); - - first.setForecastTime(now); - - assertNotEquals(first, second); - - second.setForecastTime(now); - - assertEquals(first, second); - - first.setSunriseTime(now); - - assertNotEquals(first, second); - - second.setSunriseTime(now); - - assertEquals(first, second); - - first.setSunsetTime(now); - - assertNotEquals(first, second); - - second.setSunsetTime(now); - - assertEquals(first, second); - - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - - first.setWeatherStates(List.of(weatherState)); - - assertNotEquals(first, second); - - second.setWeatherStates(List.of(weatherState)); - - assertEquals(first, second); - - final Temperature temperature = Temperature.withValue(10, "K"); - - first.setTemperature(temperature); - - assertNotEquals(first, second); - - second.setTemperature(temperature); - - assertEquals(first, second); - - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.3); - - first.setAtmosphericPressure(atmosphericPressure); - - assertNotEquals(first, second); - - second.setAtmosphericPressure(atmosphericPressure); - - assertEquals(first, second); - - final Humidity humidity = Humidity.withValue((byte) 10); - - first.setHumidity(humidity); - - assertNotEquals(first, second); - - second.setHumidity(humidity); - - assertEquals(first, second); - - final Wind wind = Wind.withValue(13.2, "m/s"); - - first.setWind(wind); - - assertNotEquals(first, second); - - second.setWind(wind); - - assertEquals(first, second); - - final Clouds clouds = Clouds.withValue((byte) 25); - - first.setClouds(clouds); - - assertNotEquals(first, second); - - second.setClouds(clouds); - - assertEquals(first, second); - - final double uvIndex = 22.4; - - first.setUvIndex(uvIndex); - - assertNotEquals(first, second); - - second.setUvIndex(uvIndex); - - assertEquals(first, second); - - final double vim = 250; - - first.setVisibilityInMetres(vim); - - assertNotEquals(first, second); - - second.setVisibilityInMetres(vim); - - assertEquals(first, second); - - final Rain rain = Rain.withOneHourLevelValue(20.2); - - first.setRain(rain); - - assertNotEquals(first, second); - - second.setRain(rain); - - assertEquals(first, second); - - final Snow snow = Snow.withOneHourLevelValue(25.0); - - first.setSnow(snow); - - assertNotEquals(first, second); - - second.setSnow(snow); - - assertEquals(first, second); - } - - @Test - public void getHashCode() { - final Current first = new Current(); - final Current second = new Current(); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setForecastTime(LocalDateTime.now()); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void getToString() { - final LocalDateTime now = LocalDateTime.now(); - final Current current = new Current(); - - current.setForecastTime(now); - - assertNotNull(current.toString()); - assertNotEquals("", current.toString()); - } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/RainUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/RainUnitTest.java deleted file mode 100644 index 2244432..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/RainUnitTest.java +++ /dev/null @@ -1,85 +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 org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class RainUnitTest { - @Test - public void withInvalidValue_negative() { - assertThrows(IllegalArgumentException.class, () -> Rain.withOneHourLevelValue(-20.0)); - } - - @Test - public void getOneHourRainLevel() { - final Rain rain = Rain.withOneHourLevelValue(220.0); - - assertEquals(220.0, rain.getOneHourLevel(), 0.00001); - } - - @Test - public void getUnit() { - final Rain rain = Rain.withOneHourLevelValue(220.0); - - assertNotNull(rain.getUnit()); - assertNotEquals("", rain.getUnit()); - } - - @Test - public void testEquals() { - final Rain first = Rain.withOneHourLevelValue(600); - final Rain second = Rain.withOneHourLevelValue(600); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - assertEquals(first, second); - - first.setOneHourLevel(200); - - assertNotEquals(first, second); - } - - @Test - public void testHashCode() { - final Rain first = Rain.withOneHourLevelValue(600); - final Rain second = Rain.withOneHourLevelValue(600); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setOneHourLevel(200); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void testToString() { - final Rain rain = Rain.withOneHourLevelValue(22.2); - - assertNotNull(rain.toString()); - assertNotEquals("", rain.toString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/SnowUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/SnowUnitTest.java deleted file mode 100644 index 38bb658..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/SnowUnitTest.java +++ /dev/null @@ -1,85 +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 org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class SnowUnitTest { - @Test - public void withInvalidValue_negative() { - assertThrows(IllegalArgumentException.class, () -> Snow.withOneHourLevelValue(-20.0)); - } - - @Test - public void getOneHourRainLevel() { - final Snow snow = Snow.withOneHourLevelValue(220.0); - - assertEquals(220.0, snow.getOneHourLevel(), 0.00001); - } - - @Test - public void getUnit() { - final Snow snow = Snow.withOneHourLevelValue(220.0); - - assertNotNull(snow.getUnit()); - assertNotEquals("", snow.getUnit()); - } - - @Test - public void testEquals() { - final Snow first = Snow.withOneHourLevelValue(600); - final Snow second = Snow.withOneHourLevelValue(600); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - assertEquals(first, second); - - first.setOneHourLevel(200); - - assertNotEquals(first, second); - } - - @Test - public void testHashCode() { - final Snow first = Snow.withOneHourLevelValue(600); - final Snow second = Snow.withOneHourLevelValue(600); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setOneHourLevel(200); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void testToString() { - final Snow snow = Snow.withOneHourLevelValue(22.2); - - assertNotNull(snow.toString()); - assertNotEquals("", snow.toString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/TemperatureUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/TemperatureUnitTest.java deleted file mode 100644 index de24ea2..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/TemperatureUnitTest.java +++ /dev/null @@ -1,129 +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 org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class TemperatureUnitTest { - @Test - public void withInvalidValue_noUnit() { - assertThrows(IllegalArgumentException.class, () -> Temperature.withValue(-20, null)); - } - - @Test - public void getValue() { - final Temperature temperature = Temperature.withValue(20, "K"); - - assertEquals(20, temperature.getValue(), 0.00001); - } - - @Test - public void getFeelsLike() { - final Temperature temperature = Temperature.withValue(20, "K"); - temperature.setFeelsLike(18.0); - - assertEquals(18.0, temperature.getFeelsLike(), 0.00001); - } - - @Test - public void getDewPoint() { - final Temperature temperature = Temperature.withValue(20, "K"); - temperature.setDewPoint(5.0); - - assertEquals(5.0, temperature.getDewPoint(), 0.00001); - } - - @Test - public void getUnit() { - final Temperature temperature = Temperature.withValue(20, "K"); - - assertEquals("K", temperature.getUnit()); - } - - @Test - public void testEquals() { - final Temperature first = Temperature.withValue(30, "L"); - final Temperature second = Temperature.withValue(30, "K"); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - assertNotEquals(first, second); - - first.setUnit("K"); - - assertEquals(first, second); - - first.setFeelsLike(25.0); - - assertNotEquals(first, second); - - second.setFeelsLike(25.0); - - assertEquals(first, second); - - first.setDewPoint(10.0); - - assertNotEquals(first, second); - - second.setDewPoint(10.0); - - assertEquals(first, second); - - first.setValue(27.0); - - assertNotEquals(first, second); - - second.setValue(27.0); - - assertEquals(first, second); - } - - @Test - public void testHashCode() { - final Temperature first = Temperature.withValue(600, "K"); - final Temperature second = Temperature.withValue(600, "K"); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setFeelsLike(599d); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void testToString() { - final Temperature temperature = Temperature.withValue(20, "K"); - - assertNotNull(temperature.toString()); - assertNotEquals("", temperature.toString()); - - temperature.setFeelsLike(22.4); - - assertNotNull(temperature.toString()); - assertNotEquals("", temperature.toString()); - } -} \ No newline at end of file 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 deleted file mode 100644 index 59c9588..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/WindUnitTest.java +++ /dev/null @@ -1,156 +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 com.github.prominence.openweathermap.api.model.Wind; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class WindUnitTest { - @Test - public void withInvalidValue_noUnit() { - assertThrows(IllegalArgumentException.class, () -> Wind.withValue(20, null)); - } - - @Test - public void withInvalidValue_negative() { - assertThrows(IllegalArgumentException.class, () -> Wind.withValue(-20, "m/s")); - } - - @Test - public void getSpeed() { - final Wind wind = Wind.withValue(20, "m/s"); - - assertEquals(20.0, wind.getSpeed(), 0.00001); - } - - @Test - public void getGust() { - final Wind wind = Wind.withValue(20, "m/s"); - wind.setGust(40); - - assertEquals(40.0, wind.getGust(), 0.00001); - } - - @Test - public void setGust_negative() { - final Wind wind = Wind.withValue(20, "m/s"); - - assertThrows(IllegalArgumentException.class, () -> wind.setGust(-20)); - } - - @Test - public void getDegrees() { - final Wind wind = Wind.withValue(20, "m/s"); - wind.setDegrees(180); - - assertEquals(180.0, wind.getDegrees(), 0.00001); - } - - @Test - public void setDegrees_lessThanZero() { - final Wind wind = Wind.withValue(20, "m/s"); - - assertThrows(IllegalArgumentException.class, () -> wind.setDegrees(-20)); - } - - @Test - public void setDegrees_moreThan360() { - final Wind wind = Wind.withValue(20, "m/s"); - - assertThrows(IllegalArgumentException.class, () -> wind.setDegrees(420)); - } - - @Test - public void getUnit() { - final Wind wind = Wind.withValue(20, "m/s"); - - assertEquals("m/s", wind.getUnit()); - } - - @Test - public void testEquals() { - final Wind first = Wind.withValue(40, "m/s"); - final Wind second = Wind.withValue(40, "m/s"); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - assertEquals(first, second); - - first.setSpeed(20); - - assertNotEquals(first, second); - - second.setSpeed(20); - - assertEquals(first, second); - - first.setDegrees(10); - - assertNotEquals(first, second); - - second.setDegrees(10); - - assertEquals(first, second); - - first.setGust(30); - - assertNotEquals(first, second); - - second.setGust(30); - - assertEquals(first, second); - - second.setUnit("km/h"); - - assertNotEquals(first, second); - } - - @Test - public void testHashCode() { - final Wind first = Wind.withValue(40, "m/s"); - final Wind second = Wind.withValue(40, "m/s"); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setGust(30); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void testToString() { - final Wind wind = Wind.withValue(40, "m/s"); - - assertNotNull(wind.toString()); - assertNotEquals("", wind.toString()); - - wind.setGust(20); - - assertNotNull(wind.toString()); - assertNotEquals("", wind.toString()); - } -} \ No newline at end of file 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 4420e42..3e1fba1 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -24,11 +24,10 @@ package com.github.prominence.openweathermap.api.model.onecall.current; import org.junit.jupiter.api.Test; -import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; -import java.util.Collections; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; public class AlertUnitTest { @Test @@ -50,7 +49,7 @@ public class AlertUnitTest { @Test public void getStartTime() { final Alert alert = new Alert(); - final LocalDateTime now = LocalDateTime.now(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); alert.setStartTime(now); assertEquals(now, alert.getStartTime()); @@ -59,7 +58,7 @@ public class AlertUnitTest { @Test public void getEndTime() { final Alert alert = new Alert(); - final LocalDateTime now = LocalDateTime.now(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); alert.setEndTime(now); assertEquals(now, alert.getEndTime()); @@ -73,77 +72,4 @@ public class AlertUnitTest { assertEquals("Description", alert.getDescription()); } - @Test - public void getEquals() { - final Alert first = new Alert(); - final Alert second = new Alert(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - final String sender = "Sender"; - final String event = "Event"; - final String description = "Description"; - final LocalDateTime now = LocalDateTime.now(); - - assertEquals(first, second); - - first.setSenderName(sender); - - assertNotEquals(first, second); - - second.setSenderName(sender); - - assertEquals(first, second); - - first.setEventName(event); - - assertNotEquals(first, second); - - second.setEventName(event); - - assertEquals(first, second); - - first.setStartTime(now); - - assertNotEquals(first, second); - - second.setStartTime(now); - - assertEquals(first, second); - - first.setEndTime(now); - - assertNotEquals(first, second); - - second.setEndTime(now); - - assertEquals(first, second); - - first.setDescription(description); - - assertNotEquals(first, second); - - second.setDescription(description); - - assertEquals(first, second); - } - - @Test - public void getHashCode() { - 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()); - } - - @Test - public void getToString() { - final Alert alert = new Alert("Sender", "Event", LocalDateTime.now(), LocalDateTime.now().plus(2, ChronoUnit.HOURS), "Description", Collections.emptyList()); - - assertNotNull(alert.toString()); - assertNotEquals("", alert.toString()); - } -} \ No newline at end of file +} 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 38017e5..66a92db 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,8 +22,8 @@ package com.github.prominence.openweathermap.api.model.onecall.current; -import com.github.prominence.openweathermap.api.model.Coordinates; -import com.github.prominence.openweathermap.api.model.onecall.Current; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.onecall.Measurement; import org.junit.jupiter.api.Test; import java.time.ZoneId; @@ -31,184 +31,101 @@ import java.time.ZoneOffset; import java.util.ArrayList; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; public class CurrentWeatherDataUnitTest { @Test public void getCoordinates() { - final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); - final Coordinates coordinates = Coordinates.of(11.2, 43.2); - currentWeatherData.setCoordinates(coordinates); + final OneCallCurrentForecastModel currentWeatherData = new OneCallCurrentForecastModel(); + final Coordinates coordinates = new Coordinates(11.2, 43.2); + currentWeatherData.setLatitude(coordinates.getLatitude()); + currentWeatherData.setLongitude(coordinates.getLongitude()); - assertEquals(coordinates, currentWeatherData.getCoordinates()); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallCurrentForecast underTest = currentWeatherData; + + assertEquals(coordinates, underTest.getCoordinates()); } @Test public void getTimezone() { - final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); + final OneCallCurrentForecastModel currentWeatherData = new OneCallCurrentForecastModel(); final ZoneId timeZone = ZoneId.of("GMT"); currentWeatherData.setTimezone(timeZone); - assertEquals(timeZone, currentWeatherData.getTimezone()); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallCurrentForecast underTest = currentWeatherData; + + assertEquals(timeZone, underTest.getTimezone()); } @Test public void getTimezoneOffset() { - final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); + final OneCallCurrentForecastModel currentWeatherData = new OneCallCurrentForecastModel(); final ZoneOffset offset = ZoneOffset.UTC; currentWeatherData.setTimezoneOffset(offset); - assertEquals(offset, currentWeatherData.getTimezoneOffset()); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallCurrentForecast underTest = currentWeatherData; + + assertEquals(offset, underTest.getTimezoneOffset()); } @Test public void getCurrent() { - final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); - final Current current = new Current(); + final OneCallCurrentForecastModel currentWeatherData = new OneCallCurrentForecastModel(); + final Measurement current = new Measurement(); currentWeatherData.setCurrent(current); - assertEquals(current, currentWeatherData.getCurrent()); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallCurrentForecast underTest = currentWeatherData; + + assertEquals(current, underTest.getCurrentWeather()); } @Test public void getMinutelyList() { - final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); + final OneCallCurrentForecastModel currentWeatherData = new OneCallCurrentForecastModel(); final List minutelyList = new ArrayList<>(); + minutelyList.add(new Minutely()); currentWeatherData.setMinutelyList(minutelyList); - assertEquals(minutelyList, currentWeatherData.getMinutelyList()); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallCurrentForecast underTest = currentWeatherData; + + assertIterableEquals(minutelyList, underTest.getMinutelyForecast()); } @Test public void getHourlyList() { - final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); + final OneCallCurrentForecastModel currentWeatherData = new OneCallCurrentForecastModel(); final List hourlyList = new ArrayList<>(); + hourlyList.add(new Hourly()); currentWeatherData.setHourlyList(hourlyList); - assertEquals(hourlyList, currentWeatherData.getHourlyList()); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallCurrentForecast underTest = currentWeatherData; + + assertIterableEquals(hourlyList, underTest.getHourlyForecast()); } @Test public void getDailyList() { - final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); + final OneCallCurrentForecastModel currentWeatherData = new OneCallCurrentForecastModel(); final List dailyList = new ArrayList<>(); + dailyList.add(new Daily()); currentWeatherData.setDailyList(dailyList); - assertEquals(dailyList, currentWeatherData.getDailyList()); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallCurrentForecast underTest = currentWeatherData; + + assertIterableEquals(dailyList, underTest.getDailyForecast()); } @Test public void getAlerts() { - final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); + final OneCallCurrentForecastModel currentWeatherData = new OneCallCurrentForecastModel(); final List alerts = new ArrayList<>(); + alerts.add(new Alert()); currentWeatherData.setAlerts(alerts); - assertEquals(alerts, currentWeatherData.getAlerts()); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallCurrentForecast underTest = currentWeatherData; + + assertIterableEquals(alerts, underTest.getAlerts()); } - @Test - public void getEquals() { - final CurrentWeatherData first = new CurrentWeatherData(); - final CurrentWeatherData second = new CurrentWeatherData(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - final Coordinates coordinates = Coordinates.of(11, 12); - final ZoneId timeZone = ZoneId.of("GMT"); - final ZoneOffset offset = ZoneOffset.UTC; - final Current current = new Current(); - final List minutelyList = new ArrayList<>(); - final List hourlyList = new ArrayList<>(); - final List dailyList = new ArrayList<>(); - final List alerts = new ArrayList<>(); - - assertEquals(first, second); - - first.setCoordinates(coordinates); - - assertNotEquals(first, second); - - second.setCoordinates(coordinates); - - assertEquals(first, second); - - first.setTimezone(timeZone); - - assertNotEquals(first, second); - - second.setTimezone(timeZone); - - assertEquals(first, second); - - first.setTimezoneOffset(offset); - - assertNotEquals(first, second); - - second.setTimezoneOffset(offset); - - assertEquals(first, second); - - first.setCurrent(current); - - assertNotEquals(first, second); - - second.setCurrent(current); - - assertEquals(first, second); - - first.setMinutelyList(minutelyList); - - assertNotEquals(first, second); - - second.setMinutelyList(minutelyList); - - assertEquals(first, second); - - first.setHourlyList(hourlyList); - - assertNotEquals(first, second); - - second.setHourlyList(hourlyList); - - assertEquals(first, second); - - first.setDailyList(dailyList); - - assertNotEquals(first, second); - - second.setDailyList(dailyList); - - assertEquals(first, second); - - first.setAlerts(alerts); - - assertNotEquals(first, second); - - second.setAlerts(alerts); - - assertEquals(first, second); - } - - @Test - public void getHashCode() { - final CurrentWeatherData first = new CurrentWeatherData(); - final CurrentWeatherData second = new CurrentWeatherData(); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setCoordinates(Coordinates.of(11, 42)); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void getToString() { - final CurrentWeatherData currentWeatherData = new CurrentWeatherData(); - currentWeatherData.setCoordinates(Coordinates.of(32, 22)); - - assertNotNull(currentWeatherData.toString()); - assertNotEquals("", currentWeatherData.toString()); - } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyRainUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyRainUnitTest.java deleted file mode 100644 index 384a223..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyRainUnitTest.java +++ /dev/null @@ -1,81 +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.current; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class DailyRainUnitTest { - @Test - public void getValue() { - final DailyRain dailyRain = DailyRain.withValue(20); - - assertEquals(20, dailyRain.getValue(), 0.00001); - } - - @Test - public void getInvalidValue_negative() { - assertThrows(IllegalArgumentException.class, () -> DailyRain.withValue(-20)); - } - - @Test - public void getUnit() { - final DailyRain dailyRain = DailyRain.withValue(20); - - assertNotNull(dailyRain.getUnit()); - assertNotEquals("", dailyRain.getUnit()); - } - - @Test - public void getEquals() { - final DailyRain first = DailyRain.withValue(0); - final DailyRain second = DailyRain.withValue(0); - - assertEquals(first, second); - - first.setValue(20); - - assertNotEquals(first, second); - } - - @Test - public void getHashCode() { - final DailyRain first = DailyRain.withValue(0); - final DailyRain second = DailyRain.withValue(0); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setValue(20); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void getToString() { - final DailyRain dailyRain = DailyRain.withValue(20); - - assertNotNull(dailyRain.toString()); - assertNotEquals("", dailyRain.toString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailySnowUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailySnowUnitTest.java deleted file mode 100644 index ec4f51a..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailySnowUnitTest.java +++ /dev/null @@ -1,81 +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.current; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class DailySnowUnitTest { - @Test - public void getValue() { - final DailySnow dailySnow = DailySnow.withValue(20); - - assertEquals(20, dailySnow.getValue(), 0.00001); - } - - @Test - public void getInvalidValue_negative() { - assertThrows(IllegalArgumentException.class, () -> DailySnow.withValue(-20)); - } - - @Test - public void getUnit() { - final DailySnow dailySnow = DailySnow.withValue(20); - - assertNotNull(dailySnow.getUnit()); - assertNotEquals("", dailySnow.getUnit()); - } - - @Test - public void getEquals() { - final DailySnow first = DailySnow.withValue(0); - final DailySnow second = DailySnow.withValue(0); - - assertEquals(first, second); - - first.setValue(20); - - assertNotEquals(first, second); - } - - @Test - public void getHashCode() { - final DailySnow first = DailySnow.withValue(0); - final DailySnow second = DailySnow.withValue(0); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setValue(20); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void getToString() { - final DailySnow dailySnow = DailySnow.withValue(20); - - assertNotNull(dailySnow.toString()); - assertNotEquals("", dailySnow.toString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyTemperatureUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyTemperatureUnitTest.java deleted file mode 100644 index f083393..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/DailyTemperatureUnitTest.java +++ /dev/null @@ -1,258 +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.current; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - -public class DailyTemperatureUnitTest { - - @Test - public void getMorning() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setMorning(value); - - assertEquals(value, temperature.getMorning(), 0.00001); - } - - @Test - public void getMorningFeelsLike() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setMorningFeelsLike(value); - - assertEquals(value, temperature.getMorningFeelsLike(), 0.00001); - } - - @Test - public void getDay() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setDay(value); - - assertEquals(value, temperature.getDay(), 0.00001); - } - - @Test - public void getDayFeelsLike() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setDayFeelsLike(value); - - assertEquals(value, temperature.getDayFeelsLike(), 0.00001); - } - - @Test - public void getEve() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setEve(value); - - assertEquals(value, temperature.getEve(), 0.00001); - } - - @Test - public void getEveFeelsLike() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setEveFeelsLike(value); - - assertEquals(value, temperature.getEveFeelsLike(), 0.00001); - } - - @Test - public void getNight() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setNight(value); - - assertEquals(value, temperature.getNight(), 0.00001); - } - - @Test - public void getNightFeelsLike() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setNightFeelsLike(value); - - assertEquals(value, temperature.getNightFeelsLike(), 0.00001); - } - - @Test - public void getMin() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setMin(value); - - assertEquals(value, temperature.getMin(), 0.00001); - } - - @Test - public void getMax() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setMax(value); - - assertEquals(value, temperature.getMax(), 0.00001); - } - - @Test - public void getDewPoint() { - final DailyTemperature temperature = new DailyTemperature(); - final double value = 20.0; - temperature.setDewPoint(value); - - assertEquals(value, temperature.getDewPoint(), 0.00001); - } - - @Test - public void getUnit() { - final DailyTemperature temperature = new DailyTemperature(); - temperature.setUnit("T"); - - assertEquals("T", temperature.getUnit()); - } - - @Test - public void getEquals() { - final DailyTemperature first = new DailyTemperature(); - final DailyTemperature second = new DailyTemperature(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - assertEquals(first, second); - - first.setMorning(1.0); - - assertNotEquals(first, second); - - second.setMorning(1.0); - - assertEquals(first, second); - - first.setMorningFeelsLike(2.0); - - assertNotEquals(first, second); - - second.setMorningFeelsLike(2.0); - - assertEquals(first, second); - - first.setDay(3.0); - - assertNotEquals(first, second); - - second.setDay(3.0); - - assertEquals(first, second); - - first.setDayFeelsLike(4.0); - - assertNotEquals(first, second); - - second.setDayFeelsLike(4.0); - - assertEquals(first, second); - - first.setEve(5.0); - - assertNotEquals(first, second); - - second.setEve(5.0); - - assertEquals(first, second); - - first.setEveFeelsLike(6.0); - - assertNotEquals(first, second); - - second.setEveFeelsLike(6.0); - - assertEquals(first, second); - - first.setNight(7.0); - - assertNotEquals(first, second); - - second.setNight(7.0); - - assertEquals(first, second); - - first.setNightFeelsLike(8.0); - - assertNotEquals(first, second); - - second.setNightFeelsLike(8.0); - - assertEquals(first, second); - - first.setDewPoint(9.0); - - assertNotEquals(first, second); - - second.setDewPoint(9.0); - - assertEquals(first, second); - - first.setMin(10.0); - - assertNotEquals(first, second); - - second.setMin(10.0); - - assertEquals(first, second); - - first.setMax(11.0); - - assertNotEquals(first, second); - - second.setMax(11.0); - - assertEquals(first, second); - - first.setUnit("K"); - - assertNotEquals(first, second); - - second.setUnit("K"); - - assertEquals(first, second); - } - - @Test - public void getHashCode() { - final DailyTemperature first = new DailyTemperature(); - final DailyTemperature second = new DailyTemperature(); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setUnit("K"); - - assertNotEquals(first.hashCode(), second.hashCode()); - } -} \ No newline at end of file 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 732f7ec..6294215 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,377 +22,238 @@ 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.AtmosphericPressure; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.location.MoonlightStages; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; +import com.github.prominence.openweathermap.api.model.generic.precipitation.Humidity; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationForecast; +import com.github.prominence.openweathermap.api.model.generic.pressure.SeaLevelAtmosphericPressure; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureDailyBasic; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureDailyDetailed; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.wind.DetailedWindInfo; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; import org.junit.jupiter.api.Test; -import java.time.LocalDateTime; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collections; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; +import static org.junit.jupiter.api.Assertions.assertNull; public class DailyUnitTest { @Test public void getForecastTime() { final Daily daily = new Daily(); - final LocalDateTime now = LocalDateTime.now(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); daily.setForecastTime(now); - assertEquals(now, daily.getForecastTime()); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallDailyWeather underTest = daily; + + assertEquals(now, underTest.getForecastTime()); } @Test public void getSunriseTime() { final Daily daily = new Daily(); - final LocalDateTime now = LocalDateTime.now(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); daily.setSunriseTime(now); - assertEquals(now, daily.getSunriseTime()); + final SunlightStages underTest = daily.getSunlightStages(); + + assertEquals(now, underTest.getSunriseTime()); } @Test public void getSunsetTime() { final Daily daily = new Daily(); - final LocalDateTime now = LocalDateTime.now(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); daily.setSunsetTime(now); - assertEquals(now, daily.getSunsetTime()); + final SunlightStages underTest = daily.getSunlightStages(); + + assertEquals(now, underTest.getSunsetTime()); + } + + @Test + public void getMoonsetTime() { + final Daily daily = new Daily(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); + daily.setMoonsetTime(now); + + final MoonlightStages underTest = daily.getMoonLightStages(); + + assertEquals(now, underTest.getMoonsetTime()); + } + + @Test + public void getMoonriseTime() { + final Daily daily = new Daily(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); + daily.setMoonriseTime(now); + + final MoonlightStages underTest = daily.getMoonLightStages(); + + assertEquals(now, underTest.getMoonriseTime()); + } + + @Test + public void getMoonPhase() { + final Daily daily = new Daily(); + final MoonPhase phase = new MoonPhase(0.67); + daily.setMoonPhase(phase); + + final MoonlightStages underTest = daily.getMoonLightStages(); + + assertEquals(phase, underTest.getMoonPhase()); } @Test public void getWeatherState() { final Daily daily = new Daily(); - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - daily.setWeatherStates(List.of(weatherState)); + final WeatherCondition weatherState = WeatherCondition.getById(800); + final List weatherStates = Collections.singletonList(weatherState); + daily.setWeatherStates(weatherStates); - assertEquals(weatherState, daily.getWeatherStates().get(0)); + @SuppressWarnings("UnnecessaryLocalVariable") final OneCallDailyWeather underTest = daily; + + assertIterableEquals(weatherStates, underTest.getWeatherStates()); } @Test public void getTemperature() { final Daily daily = new Daily(); - final DailyTemperature dailyTemperature = new DailyTemperature(); - dailyTemperature.setDay(10.0); - dailyTemperature.setEveFeelsLike(44.2); + final TemperatureDailyDetailed dailyTemperature = new TemperatureDailyDetailed(); + dailyTemperature.setDay(new TemperatureValue(BigDecimal.valueOf(10.0))); + daily.setTemperatureMeasured(dailyTemperature); - daily.setTemperature(dailyTemperature); + final OneCallDailyTemperature underTest = daily.getTemperature(); - assertEquals(dailyTemperature, daily.getTemperature()); + assertNull(underTest.getMorningFeelsLike()); + assertNull(underTest.getDayFeelsLike()); + assertNull(underTest.getEveFeelsLike()); + assertNull(underTest.getNightFeelsLike()); + assertNull(underTest.getMorning()); + assertEquals(dailyTemperature.getDay(), underTest.getDay()); + assertNull(underTest.getEve()); + assertNull(underTest.getNight()); + } + + @Test + public void getTemperatureFeelsLike() { + final Daily daily = new Daily(); + final TemperatureDailyBasic dailyTemperature = new TemperatureDailyBasic(); + dailyTemperature.setEve(new TemperatureValue(BigDecimal.valueOf(44.2))); + daily.setFeelsLike(dailyTemperature); + + final OneCallDailyTemperature underTest = daily.getTemperature(); + + assertNull(underTest.getMorningFeelsLike()); + assertNull(underTest.getDayFeelsLike()); + assertEquals(dailyTemperature.getEve(), underTest.getEveFeelsLike()); + assertNull(underTest.getNightFeelsLike()); + assertNull(underTest.getMorning()); + assertNull(underTest.getDay()); + assertNull(underTest.getEve()); + assertNull(underTest.getNight()); } @Test public void getAtmosphericPressure() { final Daily daily = new Daily(); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.3); - daily.setAtmosphericPressure(atmosphericPressure); + final BigDecimal atmosphericPressure = BigDecimal.valueOf(22.3); + daily.setSeaLevel(atmosphericPressure); - assertEquals(atmosphericPressure, daily.getAtmosphericPressure()); + final SeaLevelAtmosphericPressure underTest = daily.getAtmosphericPressure(); + + assertEquals(atmosphericPressure, underTest.getSeaLevel()); } @Test public void getHumidity() { final Daily daily = new Daily(); - final Humidity humidity = Humidity.withValue((byte) 10); - daily.setHumidity(humidity); + final int humidity = 10; + daily.setHumidityPercentage(humidity); - assertEquals(humidity, daily.getHumidity()); + final Humidity underTest = daily.getHumidity(); + + assertEquals(humidity, underTest.getHumidityPercentage()); } @Test public void getWind() { final Daily daily = new Daily(); - final Wind wind = Wind.withValue(13.2, "m/s"); - daily.setWind(wind); + final WindSpeed windSpeed = new WindSpeed(BigDecimal.valueOf(13.2)); + final WindSpeed windSpeedGust = new WindSpeed(BigDecimal.valueOf(15.2)); + final Integer windDirection = 123; + daily.setSpeed(windSpeed); + daily.setGust(windSpeedGust); + daily.setDirectionDegrees(windDirection); - assertEquals(wind, daily.getWind()); + final DetailedWindInfo wind = daily.getWind(); + + assertEquals(windSpeed, wind.getSpeed()); + assertEquals(windSpeedGust, wind.getGust()); + assertEquals(windDirection, wind.getDirectionDegrees()); } @Test public void getClouds() { final Daily daily = new Daily(); - final Clouds clouds = Clouds.withValue((byte) 25); - daily.setClouds(clouds); + final int clouds = 25; + daily.setCoveragePercentage(clouds); - assertEquals(clouds, daily.getClouds()); + final CloudCoverage coverage = daily.getClouds(); + + assertEquals(clouds, coverage.getCoveragePercentage()); } @Test public void getUvIndex() { final Daily daily = new Daily(); - final double uvIndex = 22.4; + final BigDecimal uvIndex = BigDecimal.valueOf(22.4); daily.setUvIndex(uvIndex); - assertEquals(uvIndex, daily.getUvIndex(), 0.00001); + @SuppressWarnings("UnnecessaryLocalVariable") OneCallDailyWeather underTest = daily; - daily.setUvIndex(null); - - assertNull(daily.getUvIndex()); - } - - @Test - public void getIllegalUvIndexValue() { - final Daily daily = new Daily(); - - assertThrows(IllegalArgumentException.class, () -> daily.setUvIndex(-1.2)); + assertEquals(uvIndex, underTest.getUvIndex()); } @Test public void getProbabilityOfPrecipitation() { final Daily daily = new Daily(); - final double pop = 0.84; + final int pop = 84; daily.setProbabilityOfPrecipitation(pop); - assertEquals(pop, daily.getProbabilityOfPrecipitation(), 0.00001); - assertEquals((byte) 84, daily.getProbabilityOfPrecipitationPercentage()); + PrecipitationForecast underTest = daily.getPrecipitation(); - daily.setProbabilityOfPrecipitation(null); - - assertNull(daily.getProbabilityOfPrecipitation()); - assertNull(daily.getProbabilityOfPrecipitationPercentage()); - } - - @Test - public void getIllegalProbabilityOfPrecipitationValue_negative() { - final Daily daily = new Daily(); - - assertThrows(IllegalArgumentException.class, () -> daily.setProbabilityOfPrecipitation(-20.0)); - } - - @Test - public void getIllegalProbabilityOfPrecipitationValue_tooBig() { - final Daily daily = new Daily(); - - assertThrows(IllegalArgumentException.class, () -> daily.setProbabilityOfPrecipitation(120.0)); + assertEquals(pop, underTest.getProbabilityOfPrecipitation()); } @Test public void getRain() { final Daily daily = new Daily(); - final DailyRain rain = DailyRain.withValue(20.2); + final BigDecimal rain = BigDecimal.valueOf(20.2); daily.setRain(rain); - assertEquals(rain, daily.getRain()); + PrecipitationForecast underTest = daily.getPrecipitation(); + + assertEquals(rain, underTest.getRain()); } @Test public void getSnow() { final Daily daily = new Daily(); - final DailySnow snow = DailySnow.withValue(25.0); + final BigDecimal snow = BigDecimal.valueOf(25.0); daily.setSnow(snow); - assertEquals(snow, daily.getSnow()); + PrecipitationForecast underTest = daily.getPrecipitation(); + + assertEquals(snow, underTest.getSnow()); } - - @Test - public void getEquals() { - final LocalDateTime now = LocalDateTime.now(); - final Daily first = new Daily(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - final Daily second = new Daily(); - - assertEquals(first, second); - - first.setForecastTime(now); - - assertNotEquals(first, second); - - second.setForecastTime(now); - - assertEquals(first, second); - - first.setSunriseTime(now); - - assertNotEquals(first, second); - - second.setSunriseTime(now); - - assertEquals(first, second); - - first.setSunsetTime(now); - - assertNotEquals(first, second); - - second.setSunsetTime(now); - - assertEquals(first, second); - - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - - first.setWeatherStates(List.of(weatherState)); - - assertNotEquals(first, second); - - second.setWeatherStates(List.of(weatherState)); - - assertEquals(first, second); - - final DailyTemperature dailyTemperature = new DailyTemperature(); - - first.setTemperature(dailyTemperature); - - assertNotEquals(first, second); - - second.setTemperature(dailyTemperature); - - assertEquals(first, second); - - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.3); - - first.setAtmosphericPressure(atmosphericPressure); - - assertNotEquals(first, second); - - second.setAtmosphericPressure(atmosphericPressure); - - assertEquals(first, second); - - final Humidity humidity = Humidity.withValue((byte) 10); - - first.setHumidity(humidity); - - assertNotEquals(first, second); - - second.setHumidity(humidity); - - assertEquals(first, second); - - final Wind wind = Wind.withValue(13.2, "m/s"); - - first.setWind(wind); - - assertNotEquals(first, second); - - second.setWind(wind); - - assertEquals(first, second); - - final Clouds clouds = Clouds.withValue((byte) 25); - - first.setClouds(clouds); - - assertNotEquals(first, second); - - second.setClouds(clouds); - - assertEquals(first, second); - - final double uvIndex = 22.4; - - first.setUvIndex(uvIndex); - - assertNotEquals(first, second); - - second.setUvIndex(uvIndex); - - assertEquals(first, second); - - final double pop = 70.5; - - first.setProbabilityOfPrecipitation(pop); - - assertNotEquals(first, second); - - second.setProbabilityOfPrecipitation(pop); - - assertEquals(first, second); - - final DailyRain rain = DailyRain.withValue(20.2); - - first.setRain(rain); - - assertNotEquals(first, second); - - second.setRain(rain); - - assertEquals(first, second); - - final DailySnow snow = DailySnow.withValue(25.0); - - first.setSnow(snow); - - assertNotEquals(first, second); - - second.setSnow(snow); - - assertEquals(first, second); - } - - @Test - public void getHashCode() { - final Daily first = new Daily(); - final Daily second = new Daily(); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setForecastTime(LocalDateTime.now()); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void getToString() { - final LocalDateTime now = LocalDateTime.now(); - final Daily daily = new Daily(); - - daily.setForecastTime(now); - - assertNotNull(daily.toString()); - assertNotEquals("", daily.toString()); - - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - - daily.setWeatherStates(List.of(weatherState)); - - assertNotNull(daily.toString()); - assertNotEquals("", daily.toString()); - - final DailyTemperature dailyTemperature = new DailyTemperature(); - - daily.setTemperature(dailyTemperature); - - assertNotNull(daily.toString()); - assertNotEquals("", daily.toString()); - - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.3); - - daily.setAtmosphericPressure(atmosphericPressure); - - assertNotNull(daily.toString()); - assertNotEquals("", daily.toString()); - - final Wind wind = Wind.withValue(13.2, "m/s"); - - daily.setWind(wind); - - assertNotNull(daily.toString()); - assertNotEquals("", daily.toString()); - - final Clouds clouds = Clouds.withValue((byte) 25); - - daily.setClouds(clouds); - - assertNotNull(daily.toString()); - assertNotEquals("", daily.toString()); - - final DailyRain rain = DailyRain.withValue(20.2); - - daily.setRain(rain); - - assertNotNull(daily.toString()); - assertNotEquals("", daily.toString()); - - final DailySnow snow = DailySnow.withValue(25.0); - - daily.setSnow(snow); - - assertNotNull(daily.toString()); - assertNotEquals("", daily.toString()); - } -} \ No newline at end of file +} 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 cb8d1cd..11cb526 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,26 +22,25 @@ 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.AtmosphericPressure; -import com.github.prominence.openweathermap.api.model.onecall.Rain; -import com.github.prominence.openweathermap.api.model.onecall.Snow; -import com.github.prominence.openweathermap.api.model.onecall.Temperature; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.precipitation.BasePrecipitation; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; import org.junit.jupiter.api.Test; -import java.time.LocalDateTime; -import java.util.List; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collections; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; public class HourlyUnitTest { @Test public void getForecastTime() { final Hourly hourly = new Hourly(); - final LocalDateTime now = LocalDateTime.now(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); hourly.setForecastTime(now); assertEquals(now, hourly.getForecastTime()); @@ -50,8 +49,8 @@ public class HourlyUnitTest { @Test public void getWeatherState() { final Hourly hourly = new Hourly(); - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - hourly.setWeatherStates(List.of(weatherState)); + final WeatherCondition weatherState = WeatherCondition.getById(800); + hourly.setWeatherStates(Collections.singletonList(weatherState)); assertEquals(weatherState, hourly.getWeatherStates().get(0)); } @@ -59,8 +58,8 @@ public class HourlyUnitTest { @Test public void getTemperature() { final Hourly hourly = new Hourly(); - final Temperature temperature = Temperature.withValue(10, "K"); - hourly.setTemperature(temperature); + final TemperatureValue temperature = new TemperatureValue(BigDecimal.valueOf(10)); + hourly.setTemperatureMeasured(temperature); assertEquals(temperature, hourly.getTemperature()); } @@ -68,243 +67,89 @@ public class HourlyUnitTest { @Test public void getAtmosphericPressure() { final Hourly hourly = new Hourly(); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(100); - hourly.setAtmosphericPressure(atmosphericPressure); + final BigDecimal atmosphericPressure = BigDecimal.valueOf(100); + hourly.setSeaLevel(atmosphericPressure); - assertEquals(atmosphericPressure, hourly.getAtmosphericPressure()); + assertEquals(atmosphericPressure, hourly.getSeaLevel()); } @Test public void getHumidity() { final Hourly hourly = new Hourly(); - final Humidity humidity = Humidity.withValue((byte) 20); - hourly.setHumidity(humidity); + final int humidity = 20; + hourly.setHumidityPercentage(humidity); - assertEquals(humidity, hourly.getHumidity()); + assertEquals(humidity, hourly.getHumidityPercentage()); } @Test public void getUvIndex() { final Hourly hourly = new Hourly(); - final double uvIndex = 20.0; + final BigDecimal uvIndex = BigDecimal.valueOf(20.0); hourly.setUvIndex(uvIndex); - assertEquals(uvIndex, hourly.getUvIndex(), 0.00001); + assertEquals(uvIndex, hourly.getUvIndex()); } @Test public void getClouds() { final Hourly hourly = new Hourly(); - final Clouds clouds = Clouds.withValue((byte) 60); - hourly.setClouds(clouds); + final int clouds = 60; + hourly.setCoveragePercentage(clouds); - assertEquals(clouds, hourly.getClouds()); + assertEquals(clouds, hourly.getClouds().getCoveragePercentage()); } @Test public void getVisibilityInMetres() { final Hourly hourly = new Hourly(); - final double vim = 40.0; - hourly.setVisibilityInMetres(vim); + final Visibility vim = new Visibility(BigDecimal.valueOf(40.0)); + hourly.setVisibility(vim); - assertEquals(vim, hourly.getVisibilityInMetres(), 0.00001); + assertEquals(vim, hourly.getVisibility()); } @Test public void getWind() { final Hourly hourly = new Hourly(); - final Wind wind = Wind.withValue(200, "m/s"); - hourly.setWind(wind); + final WindSpeed windSpeed = new WindSpeed(BigDecimal.valueOf(13.2)); + final WindSpeed windSpeedGust = new WindSpeed(BigDecimal.valueOf(15.2)); + final Integer windDirection = 123; + hourly.setSpeed(windSpeed); + hourly.setGust(windSpeedGust); + hourly.setDirectionDegrees(windDirection); - assertEquals(wind, hourly.getWind()); + assertEquals(windSpeed, hourly.getSpeed()); + assertEquals(windSpeedGust, hourly.getGust()); + assertEquals(windDirection, hourly.getDirectionDegrees()); } @Test public void getProbabilityOfPrecipitation() { final Hourly hourly = new Hourly(); - final double pop = 0.84; + final Integer pop = 84; hourly.setProbabilityOfPrecipitation(pop); - assertEquals(pop, hourly.getProbabilityOfPrecipitation(), 0.00001); - assertEquals((byte) 84, hourly.getProbabilityOfPrecipitationPercentage()); - - hourly.setProbabilityOfPrecipitation(null); - - assertNull(hourly.getProbabilityOfPrecipitation()); - assertNull(hourly.getProbabilityOfPrecipitationPercentage()); + assertEquals(pop, hourly.getProbabilityOfPrecipitation()); } - @Test - public void getIllegalProbabilityOfPrecipitationValue_negative() { - final Hourly daily = new Hourly(); - - assertThrows(IllegalArgumentException.class, () -> daily.setProbabilityOfPrecipitation(-20.0)); - } - - @Test - public void getIllegalProbabilityOfPrecipitationValue_tooBig() { - final Hourly daily = new Hourly(); - - assertThrows(IllegalArgumentException.class, () -> daily.setProbabilityOfPrecipitation(120.0)); - } @Test public void getRain() { final Hourly hourly = new Hourly(); - final Rain rain = Rain.withOneHourLevelValue(100); - hourly.setRain(rain); + final BasePrecipitation rain = new BasePrecipitation(BigDecimal.valueOf(20.2)); + hourly.setRainModel(rain); - assertEquals(rain, hourly.getRain()); + assertEquals(rain.getOneHourLevel(), hourly.getRain()); } @Test public void getSnow() { final Hourly hourly = new Hourly(); - final Snow snow = Snow.withOneHourLevelValue(29); - hourly.setSnow(snow); + final BasePrecipitation snow = new BasePrecipitation(BigDecimal.valueOf(25.0)); + hourly.setSnowModel(snow); - assertEquals(snow, hourly.getSnow()); + assertEquals(snow.getOneHourLevel(), hourly.getSnow()); } - @Test - public void testEquals() { - final Hourly first = new Hourly(); - final Hourly second = new Hourly(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - final LocalDateTime forecastTime = LocalDateTime.now(); - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - final Temperature temperature = Temperature.withValue(10, "K"); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(200); - final Humidity humidity = Humidity.withValue((byte) 13); - final double uvIndex = 10.0; - final Clouds clouds = Clouds.withValue((byte) 20); - final double vim = 20; - final Wind wind = Wind.withValue(20, "m/s"); - final double pop = 30; - final Rain rain = Rain.withOneHourLevelValue(40); - final Snow snow = Snow.withOneHourLevelValue(11); - - assertEquals(first, second); - - first.setForecastTime(forecastTime); - - assertNotEquals(first, second); - - second.setForecastTime(forecastTime); - - assertEquals(first, second); - - first.setWeatherStates(List.of(weatherState)); - - assertNotEquals(first, second); - - second.setWeatherStates(List.of(weatherState)); - - assertEquals(first, second); - - first.setTemperature(temperature); - - assertNotEquals(first, second); - - second.setTemperature(temperature); - - assertEquals(first, second); - - first.setAtmosphericPressure(atmosphericPressure); - - assertNotEquals(first, second); - - second.setAtmosphericPressure(atmosphericPressure); - - assertEquals(first, second); - - first.setHumidity(humidity); - - assertNotEquals(first, second); - - second.setHumidity(humidity); - - assertEquals(first, second); - - first.setUvIndex(uvIndex); - - assertNotEquals(first, second); - - second.setUvIndex(uvIndex); - - assertEquals(first, second); - - first.setClouds(clouds); - - assertNotEquals(first, second); - - second.setClouds(clouds); - - assertEquals(first, second); - - first.setVisibilityInMetres(vim); - - assertNotEquals(first, second); - - second.setVisibilityInMetres(vim); - - assertEquals(first, second); - - first.setWind(wind); - - assertNotEquals(first, second); - - second.setWind(wind); - - assertEquals(first, second); - - first.setProbabilityOfPrecipitation(pop); - - assertNotEquals(first, second); - - second.setProbabilityOfPrecipitation(pop); - - assertEquals(first, second); - - first.setRain(rain); - - assertNotEquals(first, second); - - second.setRain(rain); - - assertEquals(first, second); - - first.setSnow(snow); - - assertNotEquals(first, second); - - second.setSnow(snow); - - assertEquals(first, second); - } - - @Test - public void testHashCode() { - final Hourly first = new Hourly(); - final Hourly second = new Hourly(); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setForecastTime(LocalDateTime.now()); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void testToString() { - final Hourly hourly = new Hourly(); - hourly.setForecastTime(LocalDateTime.now()); - - assertNotNull(hourly.toString()); - assertNotEquals("", hourly.toString()); - } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/MinutelyUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/MinutelyUnitTest.java deleted file mode 100644 index fb173ea..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/MinutelyUnitTest.java +++ /dev/null @@ -1,86 +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.current; - -import org.junit.jupiter.api.Test; - -import java.time.LocalDateTime; - -import static org.junit.jupiter.api.Assertions.*; - -public class MinutelyUnitTest { - @Test - public void withValue() { - final LocalDateTime now = LocalDateTime.now(); - final Minutely minutely = Minutely.withValue(now, 10.0); - - assertEquals(now, minutely.getForecastTime()); - assertEquals(10.0, minutely.getPrecipitationVolume(), 0.00001); - } - - @Test - public void withInvalidValueValue_negative() { - assertThrows(IllegalArgumentException.class, () -> Minutely.withValue(LocalDateTime.now(), -10.0)); - - } - - @Test - public void testEquals() { - final LocalDateTime now = LocalDateTime.now(); - final Minutely first = Minutely.withValue(now, 10.0); - final Minutely firstCopy = Minutely.withValue(now, 10.0); - final Minutely second = Minutely.withValue(now, 11.0); - final Minutely secondCopy = Minutely.withValue(now.plusMinutes(11), 11.0); - final Minutely third = Minutely.withValue(now.plusMinutes(22), 44.9); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - assertEquals(first, firstCopy); - assertNotEquals(first, second); - assertNotEquals(second, secondCopy); - assertNotEquals(second, third); - } - - @Test - public void testHashCode() { - final LocalDateTime now = LocalDateTime.now(); - final Minutely first = Minutely.withValue(now, 10.0); - final Minutely firstCopy = Minutely.withValue(now, 10.0); - final Minutely second = Minutely.withValue(now.plusMinutes(2), 11.0); - - assertEquals(first.hashCode(), first.hashCode()); - assertEquals(first.hashCode(), firstCopy.hashCode()); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void testToString() { - final Minutely minutely = Minutely.withValue(LocalDateTime.now(), 10.0); - - assertNotNull(minutely.toString()); - assertNotEquals("", minutely.toString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/MoonPhaseUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/MoonPhaseUnitTest.java index e8b0644..ce63825 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/MoonPhaseUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/model/onecall/current/MoonPhaseUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -26,7 +26,6 @@ import com.github.prominence.openweathermap.api.enums.MoonType; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; public class MoonPhaseUnitTest { @@ -66,35 +65,4 @@ public class MoonPhaseUnitTest { final MoonPhase waningCrescentMoon = new MoonPhase(0.9999d); assertEquals(MoonType.WANING_CRESCENT, waningCrescentMoon.getType()); } - - @Test - public void getEquals() { - final MoonPhase phase1 = new MoonPhase(0d); - final MoonPhase phase2 = new MoonPhase(0.5d); - - assertNotEquals(phase1, phase2); - - final MoonPhase phase3 = new MoonPhase(0d); - - assertEquals(phase1, phase3); - } - - @Test - public void getHashCode() { - final MoonPhase phase1 = new MoonPhase(0d); - final MoonPhase phase2 = new MoonPhase(0.5d); - - assertNotEquals(phase1.hashCode(), phase2.hashCode()); - - final MoonPhase phase3 = new MoonPhase(0d); - - assertEquals(phase1.hashCode(), phase3.hashCode()); - } - - @Test - public void getToString() { - final MoonPhase phase2 = new MoonPhase(0.5d); - - assertEquals("FULL_MOON(0.5)", phase2.toString()); - } } 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 b3ee4ab..1215cac 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,29 +22,32 @@ package com.github.prominence.openweathermap.api.model.onecall.historical; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.onecall.Measurement; import org.junit.jupiter.api.Test; import java.time.ZoneId; import java.time.ZoneOffset; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; public class HistoricalWeatherDataUnitTest { @Test public void getCoordinates() { - final HistoricalWeatherData historicalWeatherData = new HistoricalWeatherData(); - final Coordinates coordinates = Coordinates.of(11.2, 43.2); - historicalWeatherData.setCoordinates(coordinates); + final HistoricalWeather historicalWeatherData = new HistoricalWeather(); + final Coordinates coordinates = new Coordinates(11.2, 43.2); + historicalWeatherData.setLatitude(coordinates.getLatitude()); + historicalWeatherData.setLongitude(coordinates.getLongitude()); assertEquals(coordinates, historicalWeatherData.getCoordinates()); } @Test public void getTimezone() { - final HistoricalWeatherData historicalWeatherData = new HistoricalWeatherData(); + final HistoricalWeather historicalWeatherData = new HistoricalWeather(); final ZoneId timeZone = ZoneId.of("GMT"); historicalWeatherData.setTimezone(timeZone); @@ -53,7 +56,7 @@ public class HistoricalWeatherDataUnitTest { @Test public void getTimezoneOffset() { - final HistoricalWeatherData historicalWeatherData = new HistoricalWeatherData(); + final HistoricalWeather historicalWeatherData = new HistoricalWeather(); final ZoneOffset offset = ZoneOffset.UTC; historicalWeatherData.setTimezoneOffset(offset); @@ -62,98 +65,10 @@ public class HistoricalWeatherDataUnitTest { @Test public void getHistoricalWeather() { - final HistoricalWeatherData historicalWeatherData = new HistoricalWeatherData(); - final HistoricalWeather historicalWeather = new HistoricalWeather(); - historicalWeatherData.setHistoricalWeather(historicalWeather); + final HistoricalWeather historicalWeatherData = new HistoricalWeather(); + final List historicalWeather = Collections.singletonList(new Measurement()); + historicalWeatherData.setData(historicalWeather); - assertEquals(historicalWeather, historicalWeatherData.getHistoricalWeather()); + assertIterableEquals(historicalWeather, historicalWeatherData.getDataPoints()); } - - @Test - public void getHourlyList() { - final HistoricalWeatherData historicalWeatherData = new HistoricalWeatherData(); - final List hourlyList = new ArrayList<>(); - historicalWeatherData.setHourlyList(hourlyList); - - assertEquals(hourlyList, historicalWeatherData.getHourlyList()); - } - - @Test - public void getEquals() { - final HistoricalWeatherData first = new HistoricalWeatherData(); - final HistoricalWeatherData second = new HistoricalWeatherData(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - final Coordinates coordinates = Coordinates.of(11, 12); - final ZoneId timeZone = ZoneId.of("GMT"); - final ZoneOffset offset = ZoneOffset.UTC; - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final List hourlyList = new ArrayList<>(); - - assertEquals(first, second); - - first.setCoordinates(coordinates); - - assertNotEquals(first, second); - - second.setCoordinates(coordinates); - - assertEquals(first, second); - - first.setTimezone(timeZone); - - assertNotEquals(first, second); - - second.setTimezone(timeZone); - - assertEquals(first, second); - - first.setTimezoneOffset(offset); - - assertNotEquals(first, second); - - second.setTimezoneOffset(offset); - - assertEquals(first, second); - - first.setHistoricalWeather(historicalWeather); - - assertNotEquals(first, second); - - second.setHistoricalWeather(historicalWeather); - - assertEquals(first, second); - - first.setHourlyList(hourlyList); - - assertNotEquals(first, second); - - second.setHourlyList(hourlyList); - - assertEquals(first, second); - } - - @Test - public void getHashCode() { - final HistoricalWeatherData first = new HistoricalWeatherData(); - final HistoricalWeatherData second = new HistoricalWeatherData(); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setCoordinates(Coordinates.of(11, 42)); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void getToString() { - final HistoricalWeatherData historicalWeatherData = new HistoricalWeatherData(); - historicalWeatherData.setCoordinates(Coordinates.of(32, 22)); - - assertNotNull(historicalWeatherData.toString()); - assertNotEquals("", historicalWeatherData.toString()); - } -} \ No newline at end of file +} 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 2be1df4..eae874b 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,26 +22,26 @@ 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.AtmosphericPressure; -import com.github.prominence.openweathermap.api.model.onecall.Rain; -import com.github.prominence.openweathermap.api.model.onecall.Snow; -import com.github.prominence.openweathermap.api.model.onecall.Temperature; +import com.github.prominence.openweathermap.api.enums.WeatherCondition; +import com.github.prominence.openweathermap.api.model.generic.precipitation.BasePrecipitation; +import com.github.prominence.openweathermap.api.model.generic.temperature.TemperatureValue; +import com.github.prominence.openweathermap.api.model.generic.visibility.Visibility; +import com.github.prominence.openweathermap.api.model.generic.wind.WindSpeed; +import com.github.prominence.openweathermap.api.model.onecall.BaseMeasurement; import org.junit.jupiter.api.Test; -import java.time.LocalDateTime; -import java.util.List; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collections; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; public class HistoricalWeatherUnitTest { @Test public void getForecastTime() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final LocalDateTime now = LocalDateTime.now(); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); historicalWeather.setForecastTime(now); assertEquals(now, historicalWeather.getForecastTime()); @@ -49,8 +49,8 @@ public class HistoricalWeatherUnitTest { @Test public void getSunriseTime() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final LocalDateTime now = LocalDateTime.now(); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); historicalWeather.setSunriseTime(now); assertEquals(now, historicalWeather.getSunriseTime()); @@ -58,8 +58,8 @@ public class HistoricalWeatherUnitTest { @Test public void getSunsetTime() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final LocalDateTime now = LocalDateTime.now(); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); historicalWeather.setSunsetTime(now); assertEquals(now, historicalWeather.getSunsetTime()); @@ -67,275 +67,97 @@ public class HistoricalWeatherUnitTest { @Test public void getWeatherState() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - historicalWeather.setWeatherStates(List.of(weatherState)); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final WeatherCondition weatherState = WeatherCondition.getById(800); + historicalWeather.setWeatherStates(Collections.singletonList(weatherState)); assertEquals(weatherState, historicalWeather.getWeatherStates().get(0)); } @Test public void getTemperature() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final Temperature temperature = Temperature.withValue(10, "K"); - - historicalWeather.setTemperature(temperature); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final TemperatureValue temperature = new TemperatureValue(BigDecimal.valueOf(10.0)); + historicalWeather.setTemperatureMeasured(temperature); assertEquals(temperature, historicalWeather.getTemperature()); } @Test public void getAtmosphericPressure() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.3); - historicalWeather.setAtmosphericPressure(atmosphericPressure); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final BigDecimal atmosphericPressure = BigDecimal.valueOf(22.3); + historicalWeather.setSeaLevel(atmosphericPressure); - assertEquals(atmosphericPressure, historicalWeather.getAtmosphericPressure()); + assertEquals(atmosphericPressure, historicalWeather.getSeaLevel()); } @Test public void getHumidity() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final Humidity humidity = Humidity.withValue((byte) 10); - historicalWeather.setHumidity(humidity); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final int humidity = 10; + historicalWeather.setHumidityPercentage(humidity); - assertEquals(humidity, historicalWeather.getHumidity()); + assertEquals(humidity, historicalWeather.getHumidityPercentage()); } @Test public void getWind() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final Wind wind = Wind.withValue(13.2, "m/s"); - historicalWeather.setWind(wind); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + WindSpeed windSpeed = new WindSpeed(BigDecimal.valueOf(13.2)); + WindSpeed windSpeedGust = new WindSpeed(BigDecimal.valueOf(12.0)); + int direction = 50; + historicalWeather.setSpeed(windSpeed); + historicalWeather.setGust(windSpeedGust); + historicalWeather.setDirectionDegrees(direction); - assertEquals(wind, historicalWeather.getWind()); + assertEquals(windSpeed, historicalWeather.getWind().getSpeed()); + assertEquals(windSpeedGust, historicalWeather.getWind().getGust()); + assertEquals(direction, historicalWeather.getWind().getDirectionDegrees()); } @Test public void getClouds() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final Clouds clouds = Clouds.withValue((byte) 25); - historicalWeather.setClouds(clouds); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final int clouds = 25; + historicalWeather.setCoveragePercentage(clouds); - assertEquals(clouds, historicalWeather.getClouds()); + assertEquals(clouds, historicalWeather.getClouds().getCoveragePercentage()); } @Test public void getUvIndex() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final double uvIndex = 22.4; + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final BigDecimal uvIndex = BigDecimal.valueOf(22.4); historicalWeather.setUvIndex(uvIndex); - assertEquals(uvIndex, historicalWeather.getUvIndex(), 0.00001); - - historicalWeather.setUvIndex(null); - - assertNull(historicalWeather.getUvIndex()); + assertEquals(uvIndex, historicalWeather.getUvIndex()); } @Test - public void getIllegalUvIndexValue() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); + public void getVisibility() { + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final Visibility vim = new Visibility(new BigDecimal(120)); + historicalWeather.setVisibility(vim); - assertThrows(IllegalArgumentException.class, () -> historicalWeather.setUvIndex(-1.2)); - } - - @Test - public void getProbabilityOfPrecipitation() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final double vim = 120; - historicalWeather.setVisibilityInMetres(vim); - - assertEquals(vim, historicalWeather.getVisibilityInMetres(), 0.00001); - - historicalWeather.setVisibilityInMetres(null); - - assertNull(historicalWeather.getVisibilityInMetres()); - } - - @Test - public void getIllegalProbabilityOfPrecipitationValue_negative() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - - assertThrows(IllegalArgumentException.class, () -> historicalWeather.setVisibilityInMetres(-20.0)); + assertEquals(vim, historicalWeather.getVisibility()); } @Test public void getRain() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final Rain rain = Rain.withOneHourLevelValue(20.2); - historicalWeather.setRain(rain); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final BasePrecipitation rain = new BasePrecipitation(BigDecimal.valueOf(20.2)); + historicalWeather.setRainModel(rain); - assertEquals(rain, historicalWeather.getRain()); + assertEquals(rain.getOneHourLevel(), historicalWeather.getRain()); } @Test public void getSnow() { - final HistoricalWeather historicalWeather = new HistoricalWeather(); - final Snow snow = Snow.withOneHourLevelValue(25.0); - historicalWeather.setSnow(snow); + final BaseMeasurement historicalWeather = new BaseMeasurement(); + final BasePrecipitation snow = new BasePrecipitation(BigDecimal.valueOf(25.0)); + historicalWeather.setSnowModel(snow); - assertEquals(snow, historicalWeather.getSnow()); + assertEquals(snow.getOneHourLevel(), historicalWeather.getSnow()); } - - @Test - public void getEquals() { - final LocalDateTime now = LocalDateTime.now(); - final HistoricalWeather first = new HistoricalWeather(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - final HistoricalWeather second = new HistoricalWeather(); - - assertEquals(first, second); - - first.setForecastTime(now); - - assertNotEquals(first, second); - - second.setForecastTime(now); - - assertEquals(first, second); - - first.setSunriseTime(now); - - assertNotEquals(first, second); - - second.setSunriseTime(now); - - assertEquals(first, second); - - first.setSunsetTime(now); - - assertNotEquals(first, second); - - second.setSunsetTime(now); - - assertEquals(first, second); - - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - - first.setWeatherStates(List.of(weatherState)); - - assertNotEquals(first, second); - - second.setWeatherStates(List.of(weatherState)); - - assertEquals(first, second); - - final Temperature temperature = Temperature.withValue(10, "K"); - - first.setTemperature(temperature); - - assertNotEquals(first, second); - - second.setTemperature(temperature); - - assertEquals(first, second); - - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(22.3); - - first.setAtmosphericPressure(atmosphericPressure); - - assertNotEquals(first, second); - - second.setAtmosphericPressure(atmosphericPressure); - - assertEquals(first, second); - - final Humidity humidity = Humidity.withValue((byte) 10); - - first.setHumidity(humidity); - - assertNotEquals(first, second); - - second.setHumidity(humidity); - - assertEquals(first, second); - - final Wind wind = Wind.withValue(13.2, "m/s"); - - first.setWind(wind); - - assertNotEquals(first, second); - - second.setWind(wind); - - assertEquals(first, second); - - final Clouds clouds = Clouds.withValue((byte) 25); - - first.setClouds(clouds); - - assertNotEquals(first, second); - - second.setClouds(clouds); - - assertEquals(first, second); - - final double uvIndex = 22.4; - - first.setUvIndex(uvIndex); - - assertNotEquals(first, second); - - second.setUvIndex(uvIndex); - - assertEquals(first, second); - - final double vim = 250; - - first.setVisibilityInMetres(vim); - - assertNotEquals(first, second); - - second.setVisibilityInMetres(vim); - - assertEquals(first, second); - - final Rain rain = Rain.withOneHourLevelValue(20.2); - - first.setRain(rain); - - assertNotEquals(first, second); - - second.setRain(rain); - - assertEquals(first, second); - - final Snow snow = Snow.withOneHourLevelValue(25.0); - - first.setSnow(snow); - - assertNotEquals(first, second); - - second.setSnow(snow); - - assertEquals(first, second); - } - - @Test - public void getHashCode() { - final HistoricalWeather first = new HistoricalWeather(); - final HistoricalWeather second = new HistoricalWeather(); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setForecastTime(LocalDateTime.now()); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void getToString() { - final LocalDateTime now = LocalDateTime.now(); - final HistoricalWeather historicalWeather = new HistoricalWeather(); - - historicalWeather.setForecastTime(now); - - assertNotNull(historicalWeather.toString()); - assertNotEquals("", historicalWeather.toString()); - } -} \ No newline at end of file +} 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 deleted file mode 100644 index 57617fb..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/onecall/historical/HourlyHistoricalUnitTest.java +++ /dev/null @@ -1,254 +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.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.AtmosphericPressure; -import com.github.prominence.openweathermap.api.model.onecall.Rain; -import com.github.prominence.openweathermap.api.model.onecall.Snow; -import com.github.prominence.openweathermap.api.model.onecall.Temperature; -import org.junit.jupiter.api.Test; - -import java.time.LocalDateTime; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -public class HourlyHistoricalUnitTest { - @Test - public void getForecastTime() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final LocalDateTime now = LocalDateTime.now(); - hourlyHistorical.setForecastTime(now); - - assertEquals(now, hourlyHistorical.getForecastTime()); - } - - @Test - public void getWeatherState() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - hourlyHistorical.setWeatherStates(List.of(weatherState)); - - assertEquals(weatherState, hourlyHistorical.getWeatherStates().get(0)); - } - - @Test - public void getTemperature() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final Temperature temperature = Temperature.withValue(10, "K"); - hourlyHistorical.setTemperature(temperature); - - assertEquals(temperature, hourlyHistorical.getTemperature()); - } - - @Test - public void getAtmosphericPressure() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(100); - hourlyHistorical.setAtmosphericPressure(atmosphericPressure); - - assertEquals(atmosphericPressure, hourlyHistorical.getAtmosphericPressure()); - } - - @Test - public void getHumidity() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final Humidity humidity = Humidity.withValue((byte) 20); - hourlyHistorical.setHumidity(humidity); - - assertEquals(humidity, hourlyHistorical.getHumidity()); - } - - @Test - public void getClouds() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final Clouds clouds = Clouds.withValue((byte) 60); - hourlyHistorical.setClouds(clouds); - - assertEquals(clouds, hourlyHistorical.getClouds()); - } - - @Test - public void getVisibilityInMetres() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final double vim = 40.0; - hourlyHistorical.setVisibilityInMetres(vim); - - assertEquals(vim, hourlyHistorical.getVisibilityInMetres(), 0.00001); - } - - @Test - public void getWind() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final Wind wind = Wind.withValue(200, "m/s"); - hourlyHistorical.setWind(wind); - - assertEquals(wind, hourlyHistorical.getWind()); - } - - @Test - public void getRain() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final Rain rain = Rain.withOneHourLevelValue(100); - hourlyHistorical.setRain(rain); - - assertEquals(rain, hourlyHistorical.getRain()); - } - - @Test - public void getSnow() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - final Snow snow = Snow.withOneHourLevelValue(29); - hourlyHistorical.setSnow(snow); - - assertEquals(snow, hourlyHistorical.getSnow()); - } - - @Test - public void testEquals() { - final HourlyHistorical first = new HourlyHistorical(); - final HourlyHistorical second = new HourlyHistorical(); - - assertEquals(first, first); - assertNotEquals(first, null); - assertNotEquals(first, new Object()); - - final LocalDateTime forecastTime = LocalDateTime.now(); - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - final Temperature temperature = Temperature.withValue(10, "K"); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(200); - final Humidity humidity = Humidity.withValue((byte) 13); - final Clouds clouds = Clouds.withValue((byte) 20); - final double vim = 20; - final Wind wind = Wind.withValue(20, "m/s"); - final Rain rain = Rain.withOneHourLevelValue(40); - final Snow snow = Snow.withOneHourLevelValue(11); - - assertEquals(first, second); - - first.setForecastTime(forecastTime); - - assertNotEquals(first, second); - - second.setForecastTime(forecastTime); - - assertEquals(first, second); - - first.setWeatherStates(List.of(weatherState)); - - assertNotEquals(first, second); - - second.setWeatherStates(List.of(weatherState)); - - assertEquals(first, second); - - first.setTemperature(temperature); - - assertNotEquals(first, second); - - second.setTemperature(temperature); - - assertEquals(first, second); - - first.setAtmosphericPressure(atmosphericPressure); - - assertNotEquals(first, second); - - second.setAtmosphericPressure(atmosphericPressure); - - assertEquals(first, second); - - first.setHumidity(humidity); - - assertNotEquals(first, second); - - second.setHumidity(humidity); - - assertEquals(first, second); - - first.setClouds(clouds); - - assertNotEquals(first, second); - - second.setClouds(clouds); - - assertEquals(first, second); - - first.setVisibilityInMetres(vim); - - assertNotEquals(first, second); - - second.setVisibilityInMetres(vim); - - assertEquals(first, second); - - first.setWind(wind); - - assertNotEquals(first, second); - - second.setWind(wind); - - assertEquals(first, second); - - first.setRain(rain); - - assertNotEquals(first, second); - - second.setRain(rain); - - assertEquals(first, second); - - first.setSnow(snow); - - assertNotEquals(first, second); - - second.setSnow(snow); - - assertEquals(first, second); - } - - @Test - public void testHashCode() { - final HourlyHistorical first = new HourlyHistorical(); - final HourlyHistorical second = new HourlyHistorical(); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setForecastTime(LocalDateTime.now()); - - assertNotEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void testToString() { - final HourlyHistorical hourlyHistorical = new HourlyHistorical(); - hourlyHistorical.setForecastTime(LocalDateTime.now()); - - assertNotNull(hourlyHistorical.toString()); - assertNotEquals("", hourlyHistorical.toString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskModelTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskModelTest.java new file mode 100644 index 0000000..4cfcfc9 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskModelTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; + +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +class RoadRiskModelTest { + + @Test + void testGetCoordinates_ShouldCreateCoordinatesFromList_WhenValidValuesProvided() { + //given + final RoadRiskModel underTest = new RoadRiskModel(); + final double lat = 42.0; + final double lon = 23.4; + underTest.setCoord(Arrays.asList(lat, lon)); + + //when + final Coordinates actual = underTest.getCoordinates(); + + //then + assertNotNull(actual); + assertEquals(lat, actual.getLatitude()); + assertEquals(lon, actual.getLongitude()); + } + + @Test + void testGetCoordinates_ShouldReturnNull_WhenListIsNull() { + //given + final RoadRiskModel underTest = new RoadRiskModel(); + + //when + final Coordinates actual = underTest.getCoordinates(); + + //then + assertNull(actual); + } +} 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 a93c862..9f3e84a 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,181 +22,42 @@ package com.github.prominence.openweathermap.api.model.weather; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.generic.location.BaseLocation; +import com.github.prominence.openweathermap.api.model.generic.location.SunlightStages; import org.junit.jupiter.api.Test; -import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.time.ZoneOffset; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; public class LocationUnitTest { - @Test - public void whenCreateObjectWithValidArgs_thenObjectIsCreated() { - Location.withValues(33, "test"); - } @Test - public void whenCreateObjectWithoutName_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Location.withValues(33, null)); + public void whenSet_thenValueIsSet() { + final CurrentWeatherModel weatherModel = new CurrentWeatherModel(); + final String name = "Minsk"; + final String country = "by"; + final OffsetDateTime sunrise = OffsetDateTime.now(ZoneOffset.UTC); + final OffsetDateTime sunset = OffsetDateTime.now(ZoneOffset.UTC).plusHours(10); + final int id = 55; + final City city = new City(); + city.setCountryCode(country); + city.setId(id); + city.setSunriseTime(sunrise); + city.setSunsetTime(sunset); + weatherModel.setCity(city); + weatherModel.setCityId(id); + weatherModel.setCityName(name); + + @SuppressWarnings("UnnecessaryLocalVariable") BaseLocation location = weatherModel; + assertEquals(id, location.getCityId()); + assertEquals(country, location.getCountryCode()); + assertEquals(name, location.getCityName()); + + @SuppressWarnings("UnnecessaryLocalVariable") final SunlightStages sunlightStages = weatherModel; + assertEquals(sunrise, sunlightStages.getSunriseTime()); + assertEquals(sunset, sunlightStages.getSunsetTime()); } - @Test - public void whenSetId_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - location.setId(55); - - assertEquals(55, location.getId()); - } - - @Test - public void whenSetName_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - location.setName("city"); - - assertEquals("city", location.getName()); - } - - @Test - public void whenSetCountryCode_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - location.setCountryCode("by"); - - assertEquals("by", location.getCountryCode()); - } - - @Test - public void whenSetSunrise_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - final LocalDateTime now = LocalDateTime.now(); - location.setSunriseTime(now); - - assertEquals(now, location.getSunriseTime()); - } - - @Test - public void whenSetSunset_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - final LocalDateTime now = LocalDateTime.now(); - location.setSunsetTime(now); - - assertEquals(now, location.getSunsetTime()); - } - - @Test - public void whenSetZoneOffset_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - final ZoneOffset offset = ZoneOffset.UTC; - location.setZoneOffset(offset); - - assertEquals(offset, location.getZoneOffset()); - } - - @Test - public void whenSetCoordinate_thenValueIsSet() { - final Location location = Location.withValues(33, "test"); - final Coordinates coordinates = Coordinates.of(33.2, 64.2); - location.setCoordinates(coordinates); - - assertEquals(coordinates, location.getCoordinates()); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final Location location = Location.withValues(44, "test"); - - assertNotEquals("", location.toString()); - - location.setCoordinates(Coordinates.of(33.2, 56.3)); - - assertNotEquals("", location.toString()); - - location.setCountryCode("TN"); - - assertNotEquals("", location.toString()); - assertNotNull(location.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Location one = Location.withValues(44, "test"); - final Location two = Location.withValues(44, "test"); - - assertEquals(one.hashCode(), two.hashCode()); - - two.setName("112"); - - assertNotEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Location one = Location.withValues(44, "test"); - final Location two = Location.withValues(44, "test"); - - assertEquals(one, one); - assertNotEquals(one, new Object()); - - assertEquals(one, two); - - two.setId(23); - - assertNotEquals(one, two); - - one.setId(23); - - assertEquals(one, two); - - one.setName("23"); - - assertNotEquals(one, two); - - two.setName("23"); - - assertEquals(one, two); - - one.setCountryCode("11"); - - assertNotEquals(one, two); - - two.setCountryCode("11"); - - assertEquals(one, two); - - final LocalDateTime now = LocalDateTime.now(); - - one.setSunriseTime(now); - - assertNotEquals(one, two); - - two.setSunriseTime(now); - - assertEquals(one, two); - - one.setSunsetTime(now); - - assertNotEquals(one, two); - - two.setSunsetTime(now); - - assertEquals(one, two); - - one.setZoneOffset(ZoneOffset.UTC); - - assertNotEquals(one, two); - - two.setZoneOffset(ZoneOffset.UTC); - - assertEquals(one, two); - - final Coordinates coordinates = Coordinates.of(33.5, -22.4); - - one.setCoordinates(coordinates); - - assertNotEquals(one, two); - - two.setCoordinates(coordinates); - - assertEquals(one, two); - } } diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/weather/RainUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/weather/RainUnitTest.java deleted file mode 100644 index f27c538..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/weather/RainUnitTest.java +++ /dev/null @@ -1,129 +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.weather; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class RainUnitTest { - @Test - public void whenCreateRainWithValidArgs_thenObjectIsCreated() { - Rain.withValues(2222.3, 324234.3); - Rain.withThreeHourLevelValue(213123.4); - Rain.withOneHourLevelValue(123123.123); - } - - @Test - public void whenSetValues_thenTheyAreSet() { - final Rain rain = Rain.withValues(0, 0); - - rain.setOneHourLevel(33.3); - assertEquals(33.3, rain.getOneHourLevel(), 0.00001); - - rain.setThreeHourLevel(55.5); - assertEquals(55.5, rain.getThreeHourLevel(), 0.00001); - } - - @Test - public void whenCallToString_thenAllIsFine() { - Rain rain = Rain.withThreeHourLevelValue(33.5); - - assertNotNull(rain.toString()); - assertNotEquals("", rain.toString()); - - rain.setOneHourLevel(22.2); - - assertNotNull(rain.toString()); - assertNotEquals("", rain.toString()); - - rain = Rain.withOneHourLevelValue(22.4); - - assertNotNull(rain.toString()); - assertNotEquals("", rain.toString()); - } - - @Test - public void whenSetInvalidOneHourLevelValue_thenFail() { - final Rain rain = Rain.withValues(0, 0); - - assertThrows(IllegalArgumentException.class, () -> rain.setOneHourLevel(-20)); - } - - @Test - public void whenSetInvalidThreeHourLevelValue_thenFail() { - final Rain rain = Rain.withValues(0, 0); - - assertThrows(IllegalArgumentException.class, () -> rain.setThreeHourLevel(-20)); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Rain first = Rain.withValues(0, 0); - final Rain second = Rain.withValues(0, 0); - - assertEquals(first.hashCode(), second.hashCode()); - - second.setThreeHourLevel(11.0); - - assertNotEquals(first.hashCode(), second.hashCode()); - - first.setThreeHourLevel(11.0); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setOneHourLevel(333.2); - - assertNotEquals(first.hashCode(), second.hashCode()); - - second.setOneHourLevel(333.2); - - assertEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Rain first = Rain.withValues(0, 0); - final Rain second = Rain.withValues(0, 0); - - assertEquals(first, second); - assertEquals(first, first); - assertNotEquals(first, new Object()); - - first.setOneHourLevel(0.34); - - assertNotEquals(first, second); - - second.setOneHourLevel(0.34); - - assertEquals(first, second); - - second.setThreeHourLevel(66.7); - - assertNotEquals(first, second); - - first.setThreeHourLevel(66.7); - - assertEquals(first, second); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/model/weather/SnowUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/model/weather/SnowUnitTest.java deleted file mode 100644 index a4cf3fd..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/weather/SnowUnitTest.java +++ /dev/null @@ -1,132 +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.weather; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class SnowUnitTest { - @Test - public void whenCreateSnowWithValidArgs_ObjectIsCreated() { - Snow.withValues(2222.3, 324234.3); - Snow.withThreeHourLevelValue(213123.4); - Snow.withOneHourLevelValue(123123.123); - } - - @Test - public void whenSetValues_thenTheyAreSet() { - final Snow snow = Snow.withValues(0, 0); - - snow.setOneHourLevel(33.3); - assertEquals(33.3, snow.getOneHourLevel(), 0.00001); - - snow.setThreeHourLevel(55.5); - assertEquals(55.5, snow.getThreeHourLevel(), 0.00001); - } - - @Test - public void whenSetInvalidOneHourLevelValue_thenFail() { - final Snow rain = Snow.withValues(0, 0); - assertThrows(IllegalArgumentException.class, () -> rain.setOneHourLevel(-20)); - } - - @Test - public void whenSetInvalidThreeHourLevelValue_thenFail() { - final Snow rain = Snow.withValues(0, 0); - assertThrows(IllegalArgumentException.class, () -> rain.setThreeHourLevel(-20)); - } - - @Test - public void whenCallToString_thenAllIsFine() { - Snow snow = Snow.withOneHourLevelValue(33.5); - - assertNotNull(snow.toString()); - assertNotEquals("", snow.toString()); - - snow.setOneHourLevel(22.2); - - assertNotNull(snow.toString()); - assertNotEquals("", snow.toString()); - - snow.setThreeHourLevel(33.2); - - assertNotNull(snow.toString()); - assertNotEquals("", snow.toString()); - - snow = Snow.withThreeHourLevelValue(33.2); - - assertNotNull(snow.toString()); - assertNotEquals("", snow.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Snow first = Snow.withValues(0, 0); - final Snow second = Snow.withValues(0, 0); - - assertEquals(first.hashCode(), second.hashCode()); - - second.setThreeHourLevel(11.0); - - assertNotEquals(first.hashCode(), second.hashCode()); - - first.setThreeHourLevel(11.0); - - assertEquals(first.hashCode(), second.hashCode()); - - first.setOneHourLevel(333.2); - - assertNotEquals(first.hashCode(), second.hashCode()); - - second.setOneHourLevel(333.2); - - assertEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Snow first = Snow.withValues(0, 0); - final Snow second = Snow.withValues(0, 0); - - assertEquals(first, second); - assertEquals(first, first); - assertNotEquals(first, new Object()); - - first.setOneHourLevel(0.34); - - assertNotEquals(first, second); - - second.setOneHourLevel(0.34); - - assertEquals(first, second); - - second.setThreeHourLevel(66.7); - - assertNotEquals(first, second); - - first.setThreeHourLevel(66.7); - - assertEquals(first, second); - } -} 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 deleted file mode 100644 index 0c9f9e1..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/weather/WeatherUnitTest.java +++ /dev/null @@ -1,276 +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.weather; - -import com.github.prominence.openweathermap.api.model.*; -import org.junit.jupiter.api.Test; - -import java.time.LocalDateTime; -import java.util.Collections; - -import static org.junit.jupiter.api.Assertions.*; - -public class WeatherUnitTest { - @Test - public void whenSetRequestedOn_thenValueIsSet() { - final Weather weather = new Weather(); - final LocalDateTime now = LocalDateTime.now(); - weather.setCalculationTime(now); - - assertEquals(now, weather.getCalculationTime()); - } - - @Test - public void whenSetTemperature_thenValueIsSet() { - final Weather weather = new Weather(); - final Temperature temperature = Temperature.withValue(22.3, "a"); - weather.setTemperature(temperature); - - assertEquals(temperature, weather.getTemperature()); - } - - @Test - public void whenSetPressure_thenValueIsSet() { - final Weather weather = new Weather(); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(33.2); - weather.setAtmosphericPressure(atmosphericPressure); - - assertEquals(atmosphericPressure, weather.getAtmosphericPressure()); - } - - @Test - public void whenSetHumidity_thenValueIsSet() { - final Weather weather = new Weather(); - final Humidity humidity = Humidity.withValue((byte) 44); - weather.setHumidity(humidity); - - assertEquals(humidity, weather.getHumidity()); - } - - @Test - public void whenSetWind_thenValueIsSet() { - final Weather weather = new Weather(); - final Wind wind = Wind.withValue(22.2, "a"); - weather.setWind(wind); - - assertEquals(wind, weather.getWind()); - } - - @Test - public void whenSetRain_thenValueIsSet() { - final Weather weather = new Weather(); - final Rain rain = Rain.withValues(0, 0); - weather.setRain(rain); - - assertEquals(rain, weather.getRain()); - } - - @Test - public void whenSetSnow_thenValueIsSet() { - final Weather weather = new Weather(); - final Snow snow = Snow.withValues(0, 0); - weather.setSnow(snow); - - assertEquals(snow, weather.getSnow()); - } - - @Test - public void whenSetClouds_thenValueIsSet() { - final Weather weather = new Weather(); - final Clouds clouds = Clouds.withValue((byte) 33); - weather.setClouds(clouds); - - assertEquals(clouds, weather.getClouds()); - } - - @Test - public void whenSetLocation_thenValueIsSet() { - final Weather weather = new Weather(); - final Location location = Location.withValues(22, "asd"); - weather.setLocation(location); - - assertEquals(location, weather.getLocation()); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final Weather weather = new Weather(); - final Location location = Location.withValues(12312, "asd"); - final Temperature temperature = Temperature.withValue(33.2, "asd"); - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(44.4); - final Clouds clouds = Clouds.withValue((byte) 55); - final Rain rain = Rain.withOneHourLevelValue(33.2); - final Snow snow = Snow.withOneHourLevelValue(33.1); - - assertEquals("", weather.toString()); - assertNotNull(weather.toString()); - - weather.setLocation(location); - assertNotEquals("", weather.toString()); - assertNotNull(weather.toString()); - - location.setCountryCode("3d"); - assertNotEquals("", weather.toString()); - assertNotNull(weather.toString()); - - weather.setTemperature(temperature); - assertNotEquals("", weather.toString()); - assertNotNull(weather.toString()); - - weather.setAtmosphericPressure(atmosphericPressure); - assertNotEquals("", weather.toString()); - assertNotNull(weather.toString()); - - weather.setClouds(clouds); - assertNotEquals("", weather.toString()); - assertNotNull(weather.toString()); - - weather.setRain(rain); - assertNotEquals("", weather.toString()); - assertNotNull(weather.toString()); - - weather.setRain(Rain.withThreeHourLevelValue(33)); - assertNotEquals("", weather.toString()); - assertNotNull(weather.toString()); - - weather.setSnow(snow); - assertNotEquals("", weather.toString()); - assertNotNull(weather.toString()); - - weather.setSnow(Snow.withThreeHourLevelValue(44)); - assertNotEquals("", weather.toString()); - assertNotNull(weather.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Weather one = new Weather(); - final Weather two = new Weather(); - - assertEquals(one.hashCode(), two.hashCode()); - - two.setCalculationTime(LocalDateTime.now()); - - assertNotEquals(one.hashCode(), two.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Weather one = new Weather(); - final Weather two = new Weather(); - - assertEquals(one, one); - assertNotEquals(one, new Object()); - assertEquals(one, two); - - final LocalDateTime now = LocalDateTime.now(); - one.setCalculationTime(now); - - assertNotEquals(one, two); - - two.setCalculationTime(now); - - assertEquals(one, two); - - final Temperature temperature = Temperature.withValue(33.2, "as"); - one.setTemperature(temperature); - - assertNotEquals(one, two); - - two.setTemperature(temperature); - - assertEquals(one, two); - - final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky"); - one.setWeatherStates(Collections.singletonList(weatherState)); - - assertNotEquals(one, two); - - two.setWeatherStates(Collections.singletonList(weatherState)); - - assertEquals(one, two); - - final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(33.33); - one.setAtmosphericPressure(atmosphericPressure); - - assertNotEquals(one, two); - - two.setAtmosphericPressure(atmosphericPressure); - - assertEquals(one, two); - - final Humidity humidity = Humidity.withValue((byte) 33); - one.setHumidity(humidity); - - assertNotEquals(one, two); - - two.setHumidity(humidity); - - assertEquals(one, two); - - final Wind wind = Wind.withValue(33.6, "asd"); - one.setWind(wind); - - assertNotEquals(one, two); - - two.setWind(wind); - - assertEquals(one, two); - - final Rain rain = Rain.withValues(0, 0); - one.setRain(rain); - - assertNotEquals(one, two); - - two.setRain(rain); - - assertEquals(one, two); - - final Snow snow = Snow.withValues(0, 0); - one.setSnow(snow); - - assertNotEquals(one, two); - - two.setSnow(snow); - - assertEquals(one, two); - - final Clouds clouds = Clouds.withValue((byte) 33); - one.setClouds(clouds); - - assertNotEquals(one, two); - - two.setClouds(clouds); - - assertEquals(one, two); - - final Location location = Location.withValues(231, "asda"); - one.setLocation(location); - - assertNotEquals(one, two); - - two.setLocation(location); - - 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 deleted file mode 100644 index 45f54ba..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/model/weather/WindUnitTest.java +++ /dev/null @@ -1,214 +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.weather; - -import com.github.prominence.openweathermap.api.model.Wind; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class WindUnitTest { - @Test - public void whenCreateWindWithValidArgs_thenValueIsSet() { - assertEquals(44.0, Wind.withValue(44, "ms").getSpeed(), 0.00001); - } - - @Test - public void whenCreateWindWithInvalidSpeedArg_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Wind.withValue(-21, "a")); - } - - @Test - public void whenCreateWindWithInvalidUnitArg_thenThrowAnException() { - assertThrows(IllegalArgumentException.class, () -> Wind.withValue(342, null)); - } - - @Test - public void whenSetValidSpeed_thenValueIsSet() { - final Wind wind = Wind.withValue(33, "as"); - - assertEquals(33, wind.getSpeed(), 0.00001); - - wind.setSpeed(0); - - assertEquals(0, wind.getSpeed(), 0.00001); - - wind.setSpeed(3656); - - assertEquals(3656, wind.getSpeed(), 0.00001); - } - - @Test - public void whenSetInvalidSpeedBelow0_thenThrowAnException() { - final Wind wind = Wind.withValue(33, "as"); - - assertEquals(33, wind.getSpeed(), 0.00001); - - assertThrows(IllegalArgumentException.class, () -> wind.setSpeed(-22)); - } - - @Test - public void whenSetValidDegrees_thenValueIsSet() { - final Wind wind = Wind.withValue(33, "as"); - - assertNull(wind.getDegrees()); - - wind.setDegrees(22); - - assertEquals(22, wind.getDegrees(), 0.00001); - - wind.setDegrees(0); - - assertEquals(0, wind.getDegrees(), 0.00001); - - wind.setDegrees(360); - - assertEquals(360, wind.getDegrees(), 0.00001); - } - - @Test - public void whenSetInvalidDegreesBelow0_thenThrowAnException() { - final Wind wind = Wind.withValue(33, "as"); - - assertThrows(IllegalArgumentException.class, () -> wind.setDegrees(-32)); - } - - @Test - public void whenSetInvalidDegreesAbove360_thenThrowAnException() { - final Wind wind = Wind.withValue(33, "as"); - - assertThrows(IllegalArgumentException.class, () -> wind.setDegrees(378)); - } - - @Test - public void whenSetNonNullUnit_thenValueIsSet() { - final Wind wind = Wind.withValue(33, "as"); - - assertEquals(wind.getUnit(), "as"); - - wind.setUnit("myUnit"); - - assertEquals(wind.getUnit(), "myUnit"); - } - - @Test - public void whenSetNullUnit_thenThrowAnException() { - final Wind wind = Wind.withValue(33, "as"); - - assertThrows(IllegalArgumentException.class, () -> wind.setUnit(null)); - } - - @Test - public void whenSetInvalidGustValue_thenThrowAnException() { - final Wind wind = Wind.withValue(33, "as"); - - assertThrows(IllegalArgumentException.class, () -> wind.setGust(-50)); - } - - @Test - public void whenSetValidGustValue_thenAllIsFine() { - final Wind wind = Wind.withValue(33, "as"); - - wind.setGust(30); - - assertEquals(30, wind.getGust(), 0.00001); - } - - @Test - public void whenCallToString_thenAllIsFine() { - final Wind wind = Wind.withValue(302, "a"); - - assertNotNull(wind.toString()); - - wind.setDegrees(22); - - assertNotNull(wind.toString()); - assertNotEquals("", wind.toString()); - - wind.setGust(20); - assertNotNull(wind.toString()); - assertNotEquals("", wind.toString()); - } - - @Test - public void whenCallHashCode_thenAllIsFine() { - final Wind first = Wind.withValue(22, "a"); - final Wind second = Wind.withValue(22, "b"); - - assertNotEquals(first.hashCode(), second.hashCode()); - - second.setUnit("a"); - - assertEquals(first.hashCode(), second.hashCode()); - - second.setSpeed(33); - - assertNotEquals(first.hashCode(), second.hashCode()); - - first.setSpeed(333); - - assertNotEquals(first.hashCode(), second.hashCode()); - - first.setSpeed(33); - - assertEquals(first.hashCode(), second.hashCode()); - } - - @Test - public void whenCheckEquality_thenAllIsFine() { - final Wind first = Wind.withValue(11, "a"); - final Wind second = Wind.withValue(11, "a"); - - assertEquals(first, second); - assertEquals(first, first); - assertNotEquals(first, new Object()); - - first.setDegrees(34); - - assertNotEquals(first, second); - - second.setDegrees(34); - - assertEquals(first, second); - - second.setUnit("v"); - - assertNotEquals(first, second); - - first.setUnit("v"); - - assertEquals(first, second); - - first.setGust(4); - - assertNotEquals(first, second); - - second.setGust(4); - - assertEquals(first, second); - - first.setSpeed(32); - - assertNotEquals(first, second); - } -} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..6564489 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminatorTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021-present 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.air.pollution; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class AirPollutionAsyncRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final AirPollutionAsyncRequestTerminator underTest = + new AirPollutionAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asXML(UnitSystem.STANDARD).get()); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final AirPollutionAsyncRequestTerminator underTest = + new AirPollutionAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} 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 715baba..440915c 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 @@ -1,51 +1,100 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.air.pollution; import com.github.prominence.openweathermap.api.ApiTest; -import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.OpenWeatherMapClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.core.net.HttpClient; +import com.github.prominence.openweathermap.api.enums.UnitSystem; import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class AirPollutionIntegrationTest extends ApiTest { + + @Test + public void testBuilder_ShouldGenerateExpectedUrl_whenCalledWithValidData() { + //given + final HttpClient httpClient = mock(HttpClient.class); + final ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + final ApiConfiguration configuration = ApiConfiguration.builder().apiKey("apiKeyValue").httpClient(httpClient).build(); + when(httpClient.executeGetRequest(urlCaptor.capture())).thenReturn("{}"); + + //when + final AirPollutionDetails actual = new OpenWeatherMapClient(configuration) + .airPollution() + .current() + .byCoordinates(new Coordinates(53.54, 27.34)) + .retrieve() + .asJava(); + + //then + assertEquals("https://api.openweathermap.org/data/2.5/air_pollution?mode=json&lon=27.34&units=standard&lat=53.54&appid=apiKeyValue", urlCaptor.getValue()); + } + + @Test + public void testBuilder_ShouldGenerateExpectedHistoricalUrl_whenCalledWithValidData() { + //given + final HttpClient httpClient = mock(HttpClient.class); + final ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + final ApiConfiguration configuration = ApiConfiguration.builder().apiKey("apiKeyValue").httpClient(httpClient).build(); + when(httpClient.executeGetRequest(urlCaptor.capture())).thenReturn("{}"); + + //when + final AirPollutionDetails actual = new OpenWeatherMapClient(configuration) + .airPollution() + .historical() + .byCoordinateAndPeriod(new Coordinates(53.54, 27.34), 0, 10) + .retrieve() + .asJava(); + + //then + assertEquals("https://api.openweathermap.org/data/2.5/air_pollution/history?mode=json&appid=apiKeyValue&start=0&lon=27.34&end=10&units=standard&lat=53.54", urlCaptor.getValue()); + } + @Test public void whenRetrieveCurrentAirPollutionResponseAsJava_thenOk() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final AirPollutionDetails airPollutionDetails = getClient() .airPollution() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .retrieve() .asJava(); assertNotNull(airPollutionDetails); - airPollutionDetails.getAirPollutionRecords().forEach(airPollutionRecord -> { + airPollutionDetails.getAirPollutionConcentration().forEach(airPollutionRecord -> { assertNotNull(airPollutionRecord); System.out.println(airPollutionRecord); }); @@ -53,12 +102,13 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveCurrentAirPollutionResponseAsJSON_thenOk() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String jsonString = getClient() .airPollution() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .retrieve() - .asJSON(); + .asJSON(null); assertNotNull(jsonString); System.out.println(jsonString); @@ -66,10 +116,11 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveCurrentAirPollutionAsyncResponseAsJava_thenOk() throws ExecutionException, InterruptedException { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final CompletableFuture pollutionDetailsFuture = getClient() .airPollution() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .retrieveAsync() .asJava(); @@ -79,12 +130,13 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveCurrentAirPollutionAsyncResponseAsJSON_thenOk() throws ExecutionException, InterruptedException { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final CompletableFuture jsonStringFuture = getClient() .airPollution() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .retrieveAsync() - .asJSON(); + .asJSON(UnitSystem.STANDARD); assertNotNull(jsonStringFuture); final String jsonString = jsonStringFuture.get(); @@ -94,15 +146,16 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveForecastAirPollutionResponseAsJava_thenOk() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final AirPollutionDetails airPollutionDetails = getClient() .airPollution() .forecast() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .retrieve() .asJava(); assertNotNull(airPollutionDetails); - airPollutionDetails.getAirPollutionRecords().forEach(airPollutionRecord -> { + airPollutionDetails.getAirPollutionConcentration().forEach(airPollutionRecord -> { assertNotNull(airPollutionRecord); System.out.println(airPollutionRecord); }); @@ -110,12 +163,13 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveForecastAirPollutionResponseAsJSON_thenOk() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String jsonString = getClient() .airPollution() .forecast() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .retrieve() - .asJSON(); + .asJSON(UnitSystem.STANDARD); assertNotNull(jsonString); System.out.println(jsonString); @@ -123,10 +177,11 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveForecastAirPollutionAsyncResponseAsJava_thenOk() throws ExecutionException, InterruptedException { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final CompletableFuture pollutionDetailsFuture = getClient() .airPollution() .forecast() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .retrieveAsync() .asJava(); @@ -136,12 +191,13 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveForecastAirPollutionAsyncResponseAsJSON_thenOk() throws ExecutionException, InterruptedException { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final CompletableFuture jsonStringFuture = getClient() .airPollution() .forecast() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .retrieveAsync() - .asJSON(); + .asJSON(UnitSystem.STANDARD); assertNotNull(jsonStringFuture); final String jsonString = jsonStringFuture.get(); @@ -151,15 +207,16 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveHistoricalAirPollutionResponseAsJava_thenOk() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final AirPollutionDetails airPollutionDetails = getClient() .airPollution() .historical() - .byCoordinateAndPeriod(Coordinates.of(53.54, 27.34), 1606223802, 1606482999) + .byCoordinateAndPeriod(new Coordinates(53.54, 27.34), 1606223802, 1606482999) .retrieve() .asJava(); assertNotNull(airPollutionDetails); - airPollutionDetails.getAirPollutionRecords().forEach(airPollutionRecord -> { + airPollutionDetails.getAirPollutionConcentration().forEach(airPollutionRecord -> { assertNotNull(airPollutionRecord); System.out.println(airPollutionRecord); }); @@ -167,12 +224,13 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveHistoricalAirPollutionResponseAsJSON_thenOk() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String jsonString = getClient() .airPollution() .historical() - .byCoordinateAndPeriod(Coordinates.of(53.54, 27.34), 1606223802, 1606482999) + .byCoordinateAndPeriod(new Coordinates(53.54, 27.34), 1606223802, 1606482999) .retrieve() - .asJSON(); + .asJSON(UnitSystem.STANDARD); assertNotNull(jsonString); System.out.println(jsonString); @@ -180,10 +238,11 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveHistoricalAirPollutionAsyncResponseAsJava_thenOk() throws ExecutionException, InterruptedException { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final CompletableFuture pollutionDetailsFuture = getClient() .airPollution() .historical() - .byCoordinateAndPeriod(Coordinates.of(53.54, 27.34), 1606223802, 1606482999) + .byCoordinateAndPeriod(new Coordinates(53.54, 27.34), 1606223802, 1606482999) .retrieveAsync() .asJava(); @@ -193,12 +252,13 @@ public class AirPollutionIntegrationTest extends ApiTest { @Test public void whenRetrieveHistoricalAirPollutionAsyncResponseAsJSON_thenOk() throws ExecutionException, InterruptedException { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final CompletableFuture jsonStringFuture = getClient() .airPollution() .historical() - .byCoordinateAndPeriod(Coordinates.of(53.54, 27.34), 1606223802, 1606482999) + .byCoordinateAndPeriod(new Coordinates(53.54, 27.34), 1606223802, 1606482999) .retrieveAsync() - .asJSON(); + .asJSON(UnitSystem.STANDARD); assertNotNull(jsonStringFuture); final String jsonString = jsonStringFuture.get(); diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminatorTest.java new file mode 100644 index 0000000..2061aaa --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminatorTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021-present 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.air.pollution; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetailsModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class AirPollutionRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final AirPollutionRequestTerminator underTest = + new AirPollutionRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asXML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final AirPollutionRequestTerminator underTest = + new AirPollutionRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final AirPollutionRequestTerminator underTest = + new AirPollutionRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(AirPollutionDetailsModel.class, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionResponseMapperUnitTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionResponseMapperUnitTest.java index f065062..5f955c7 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionResponseMapperUnitTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionResponseMapperUnitTest.java @@ -1,31 +1,31 @@ /* + * Copyright (c) 2021-present Alexey Zinchenko * - * * 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. + * 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.air.pollution; -import com.github.prominence.openweathermap.api.mapper.AirPollutionResponseMapper; -import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetailsModel; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -35,24 +35,25 @@ public class AirPollutionResponseMapperUnitTest { @Test public void mapToAirPollution_withInvalidJSON() { final String jsonString = "{\"coord\":{lon\":27.34,\"lat\":53.54},\"list\":[{\"main\":{\"aqi\":1},\"components\":{\"co\":243.66,\"no\":0,\"no2\":4.07,\"o3\":62.23,\"so2\":1.77,\"pm2_5\":3.87,\"pm10\":4.58,\"nh3\":2.41},\"dt\":1618610400}]}"; - assertThrows(RuntimeException.class, () -> new AirPollutionResponseMapper().mapToAirPollution(jsonString)); + assertThrows(JsonMappingException.class, () -> new ObjectMapper().readValue(jsonString, AirPollutionDetailsModel.class)); } @Test - public void mapToAirPollution_withCoordinatesVariation() { - String jsonResponse = "{\"coord\":{},\"list\":[{\"main\":{\"aqi\":1},\"components\":{\"co\":243.66,\"no\":0,\"no2\":4.07,\"o3\":62.23,\"so2\":1.77,\"pm2_5\":3.87,\"pm10\":4.58,\"nh3\":2.41},\"dt\":1618610400}]}"; - AirPollutionDetails airPollutionDetails = new AirPollutionResponseMapper().mapToAirPollution(jsonResponse); + public void mapToAirPollution_withCoordinatesVariation() throws JsonProcessingException { + final ObjectMapper objectMapper = new ObjectMapper(); + String jsonString = "{\"coord\":{},\"list\":[{\"main\":{\"aqi\":1},\"components\":{\"co\":243.66,\"no\":0,\"no2\":4.07,\"o3\":62.23,\"so2\":1.77,\"pm2_5\":3.87,\"pm10\":4.58,\"nh3\":2.41},\"dt\":1618610400}]}"; + AirPollutionDetailsModel airPollutionDetails = objectMapper.readValue(jsonString, AirPollutionDetailsModel.class); assertNotNull(airPollutionDetails); - jsonResponse = "{\"coord\":{\"lon\":27.34},\"list\":[{\"main\":{\"aqi\":1},\"components\":{\"co\":243.66,\"no\":0,\"no2\":4.07,\"o3\":62.23,\"so2\":1.77,\"pm2_5\":3.87,\"pm10\":4.58,\"nh3\":2.41},\"dt\":1618610400}]}"; - airPollutionDetails = new AirPollutionResponseMapper().mapToAirPollution(jsonResponse); + jsonString = "{\"coord\":{\"lon\":27.34},\"list\":[{\"main\":{\"aqi\":1},\"components\":{\"co\":243.66,\"no\":0,\"no2\":4.07,\"o3\":62.23,\"so2\":1.77,\"pm2_5\":3.87,\"pm10\":4.58,\"nh3\":2.41},\"dt\":1618610400}]}"; + airPollutionDetails = objectMapper.readValue(jsonString, AirPollutionDetailsModel.class); assertNotNull(airPollutionDetails); - jsonResponse = "{\"coord\":{\"lat\":53.54},\"list\":[{\"main\":{\"aqi\":1},\"components\":{\"co\":243.66,\"no\":0,\"no2\":4.07,\"o3\":62.23,\"so2\":1.77,\"pm2_5\":3.87,\"pm10\":4.58,\"nh3\":2.41},\"dt\":1618610400}]}"; - airPollutionDetails = new AirPollutionResponseMapper().mapToAirPollution(jsonResponse); + jsonString = "{\"coord\":{\"lat\":53.54},\"list\":[{\"main\":{\"aqi\":1},\"components\":{\"co\":243.66,\"no\":0,\"no2\":4.07,\"o3\":62.23,\"so2\":1.77,\"pm2_5\":3.87,\"pm10\":4.58,\"nh3\":2.41},\"dt\":1618610400}]}"; + airPollutionDetails = objectMapper.readValue(jsonString, AirPollutionDetailsModel.class); assertNotNull(airPollutionDetails); } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..c16922b --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastAsyncRequestTerminatorTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.climatic; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class ClimaticForecastAsyncRequestTerminatorTest { + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ClimaticForecastAsyncRequestTerminator underTest = + new ClimaticForecastAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastIntegrationTest.java new file mode 100644 index 0000000..46d74b7 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastIntegrationTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021-present 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.climatic; + +import com.github.prominence.openweathermap.api.OpenWeatherMapClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.core.net.HttpClient; +import com.github.prominence.openweathermap.api.enums.Language; +import com.github.prominence.openweathermap.api.model.forecast.climatic.ThirtyDaysDailyForecast; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class ClimaticForecastIntegrationTest { + + @Test + public void testBuilder_ShouldGenerateExpectedUrl_whenCalledWithValidData() { + //given + final HttpClient httpClient = mock(HttpClient.class); + final ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + final ApiConfiguration configuration = ApiConfiguration.builder().apiKey("apiKeyValue").httpClient(httpClient).build(); + when(httpClient.executeGetRequest(urlCaptor.capture())).thenReturn("{}"); + + //when + final ThirtyDaysDailyForecast actual = new OpenWeatherMapClient(configuration) + .climaticForecast30Days() + .byCoordinates(new Coordinates(53.54, 27.34)) + .language(Language.ENGLISH) + .retrieve() + .asJava(); + + //then + assertEquals("https://pro.openweathermap.org/data/2.5/forecast/climate?mode=json&lon=27.34&units=standard&lang=en&lat=53.54&appid=apiKeyValue", urlCaptor.getValue()); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestTerminatorTest.java new file mode 100644 index 0000000..fa91cd8 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/climatic/ClimaticForecastRequestTerminatorTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021-present 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.climatic; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.climatic.ThirtyDaysDailyForecastModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ClimaticForecastRequestTerminatorTest { + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ClimaticForecastRequestTerminator underTest = + new ClimaticForecastRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ClimaticForecastRequestTerminator underTest = + new ClimaticForecastRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(ThirtyDaysDailyForecastModel.class, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..e004db7 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastAsyncRequestTerminatorTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class DailyForecastAsyncRequestTerminatorTest { + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final DailyForecastAsyncRequestTerminator underTest = + new DailyForecastAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastIntegrationTest.java new file mode 100644 index 0000000..6b1f62f --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastIntegrationTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021-present 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.OpenWeatherMapClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.core.net.HttpClient; +import com.github.prominence.openweathermap.api.enums.Language; +import com.github.prominence.openweathermap.api.model.forecast.daily.SixteenDaysDailyForecast; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class DailyForecastIntegrationTest { + + @Test + public void testBuilder_ShouldGenerateExpectedUrl_whenCalledWithValidData() { + //given + final HttpClient httpClient = mock(HttpClient.class); + final ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + final ApiConfiguration configuration = ApiConfiguration.builder().apiKey("apiKeyValue").httpClient(httpClient).build(); + when(httpClient.executeGetRequest(urlCaptor.capture())).thenReturn("{}"); + + //when + final SixteenDaysDailyForecast actual = new OpenWeatherMapClient(configuration) + .forecastDaily16Days() + .byCoordinates(new Coordinates(53.54, 27.34)) + .language(Language.ENGLISH) + .retrieve() + .asJava(); + + //then + assertEquals("https://api.openweathermap.org/data/2.5/forecast/daily?mode=json&lon=27.34&units=standard&lang=en&lat=53.54&appid=apiKeyValue", urlCaptor.getValue()); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminatorTest.java new file mode 100644 index 0000000..076df06 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/daily/DailyForecastRequestTerminatorTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.daily.SixteenDaysDailyForecastModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class DailyForecastRequestTerminatorTest { + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final DailyForecastRequestTerminator underTest = + new DailyForecastRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final DailyForecastRequestTerminator underTest = + new DailyForecastRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(SixteenDaysDailyForecastModel.class, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..ecc8a29 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminatorTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.free; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class FiveDayThreeHourStepForecastAsyncRequestTerminatorTest { + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final FiveDayThreeHourStepForecastAsyncRequestTerminator underTest = + new FiveDayThreeHourStepForecastAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} 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 6f97eb4..76c77cf 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -24,28 +24,57 @@ package com.github.prominence.openweathermap.api.request.forecast.free; import com.github.prominence.openweathermap.api.ApiTest; import com.github.prominence.openweathermap.api.OpenWeatherMapClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.core.net.HttpClient; 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.Coordinates; -import com.github.prominence.openweathermap.api.model.forecast.free.Forecast; -import com.github.prominence.openweathermap.api.model.forecast.free.WeatherForecast; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecast; +import com.github.prominence.openweathermap.api.model.forecast.free.ThreeHourWeather; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { + + @Test + public void testBuilder_ShouldGenerateExpectedUrl_whenCalledWithValidData() { + //given + final HttpClient httpClient = mock(HttpClient.class); + final ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + final ApiConfiguration configuration = ApiConfiguration.builder().apiKey("apiKeyValue").httpClient(httpClient).build(); + when(httpClient.executeGetRequest(urlCaptor.capture())).thenReturn("{}"); + + //when + final FiveDaysThreeHoursForecast actual = new OpenWeatherMapClient(configuration) + .forecast5Day3HourStep() + .byCoordinates(new Coordinates(53.54, 27.34)) + .language(Language.ENGLISH) + .retrieve() + .asJava(); + + //then + assertEquals("https://api.openweathermap.org/data/2.5/forecast?mode=json&lon=27.34&units=standard&lang=en&lat=53.54&appid=apiKeyValue", urlCaptor.getValue()); + } + @Test public void whenGetForecastByCityNameRequestAsJava_thenReturnNotNull() { - final Forecast forecast = getClient() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + final FiveDaysThreeHoursForecast forecast = getClient() .forecast5Day3HourStep() .byCityName("Minsk") .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .count(15) .retrieve() .asJava(); @@ -53,7 +82,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNotNull(forecast.getWeatherForecasts()); - for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) { + for (ThreeHourWeather weatherForecast : forecast.getWeatherForecasts()) { assertNotNull(weatherForecast.getWeatherStates()); assertNotNull(weatherForecast.getForecastTime()); assertNotNull(weatherForecast.getTemperature()); @@ -65,39 +94,39 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { @Test public void whenGetForecastByCityNameRequestAsJSON_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String forecastJson = getClient() .forecast5Day3HourStep() .byCityName("Minsk") .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .count(15) .retrieve() - .asJSON(); + .asJSON(UnitSystem.METRIC); assertTrue(forecastJson.startsWith("{")); } @Test public void whenGetForecastByCityNameRequestAsXML_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String forecastXml = getClient() .forecast5Day3HourStep() .byCityName("Minsk") .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .count(15) .retrieve() - .asXML(); + .asXML(UnitSystem.METRIC); assertTrue(forecastXml.startsWith("<")); } @Test public void whenGetForecastByCityNameAndCountryCodeRequestAsJava_thenReturnNotNull() { - final Forecast forecast = getClient() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + final FiveDaysThreeHoursForecast forecast = getClient() .forecast5Day3HourStep() - .byCityName("Minsk", "BY") + .byCityName("Minsk") .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .count(15) .retrieve() .asJava(); @@ -105,7 +134,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNotNull(forecast.getWeatherForecasts()); - for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) { + for (ThreeHourWeather weatherForecast : forecast.getWeatherForecasts()) { assertNotNull(weatherForecast.getWeatherStates()); assertNotNull(weatherForecast.getForecastTime()); assertNotNull(weatherForecast.getTemperature()); @@ -117,39 +146,39 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { @Test public void whenGetForecastByCityNameAndCountryCodeRequestAsJSON_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String forecastJson = getClient() .forecast5Day3HourStep() - .byCityName("Minsk", "by") + .byCityName("Minsk") .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .count(15) .retrieve() - .asJSON(); + .asJSON(UnitSystem.METRIC); assertTrue(forecastJson.startsWith("{")); } @Test public void whenGetForecastByCityNameAndCountryCodeRequestAsXML_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String forecastXml = getClient() .forecast5Day3HourStep() - .byCityName("Minsk", "by") + .byCityName("Minsk") .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .count(15) .retrieve() - .asXML(); + .asXML(UnitSystem.METRIC); assertTrue(forecastXml.startsWith("<")); } @Test public void whenGetForecastByCityNameAndStateCodeAndCountryCodeRequestAsJava_thenReturnNotNull() { - final Forecast forecast = getClient() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + final FiveDaysThreeHoursForecast forecast = getClient() .forecast5Day3HourStep() - .byCityName("New York", "NY", "US") + .byCityName("New York") .language(Language.CHINESE_TRADITIONAL) - .unitSystem(UnitSystem.STANDARD) .count(15) .retrieve() .asJava(); @@ -157,7 +186,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNotNull(forecast.getWeatherForecasts()); - for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) { + for (ThreeHourWeather weatherForecast : forecast.getWeatherForecasts()) { assertNotNull(weatherForecast.getWeatherStates()); assertNotNull(weatherForecast.getForecastTime()); assertNotNull(weatherForecast.getTemperature()); @@ -169,89 +198,38 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { @Test public void whenGetForecastByCityNameAndStateCodeAndCountryCodeRequestAsJSON_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String forecastJson = getClient() .forecast5Day3HourStep() - .byCityName("New York", "NY", "US") + .byCityName("New York") .language(Language.SPANISH) - .unitSystem(UnitSystem.IMPERIAL) .count(15) .retrieve() - .asJSON(); + .asJSON(UnitSystem.IMPERIAL); assertTrue(forecastJson.startsWith("{")); } @Test public void whenGetForecastByCityNameAndStateCodeAndCountryCodeRequestAsXML_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String forecastXml = getClient() .forecast5Day3HourStep() - .byCityName("New York", "NY", "US") + .byCityName("New York") .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieve() - .asXML(); - - assertTrue(forecastXml.startsWith("<")); - } - - @Test - public void whenGetForecastByCityIdRequestAsJava_thenReturnNotNull() { - final Forecast forecast = getClient() - .forecast5Day3HourStep() - .byCityId(350001514) - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .count(15) - .retrieve() - .asJava(); - - assertNotNull(forecast); - assertNotNull(forecast.getLocation()); - assertNotNull(forecast.getWeatherForecasts()); - for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) { - assertNotNull(weatherForecast.getWeatherStates()); - assertNotNull(weatherForecast.getForecastTime()); - assertNotNull(weatherForecast.getTemperature()); - assertNotNull(weatherForecast.getAtmosphericPressure()); - assertNotNull(weatherForecast.getHumidity()); - assertNotNull(weatherForecast.getWind()); - } - } - - @Test - public void whenGetForecastByCityIdRequestAsJSON_thenReturnNotNull() { - final String forecastJson = getClient() - .forecast5Day3HourStep() - .byCityId(350001514) - .language(Language.SPANISH) - .unitSystem(UnitSystem.IMPERIAL) - .count(15) - .retrieve() - .asJSON(); - - assertTrue(forecastJson.startsWith("{")); - } - - @Test - public void whenGetForecastByCityIdRequestAsXML_thenReturnNotNull() { - final String forecastXml = getClient() - .forecast5Day3HourStep() - .byCityId(350001514) - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asXML(); + .asXML(UnitSystem.METRIC); assertTrue(forecastXml.startsWith("<")); } @Test public void whenGetForecastByCoordinatesRequestAsJava_thenReturnNotNull() { - final Forecast forecast = getClient() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + final FiveDaysThreeHoursForecast forecast = getClient() .forecast5Day3HourStep() - .byCoordinates(Coordinates.of(5, 5)) + .byCoordinates(new Coordinates(5, 5)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .count(15) .retrieve() .asJava(); @@ -259,7 +237,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNotNull(forecast.getWeatherForecasts()); - for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) { + for (ThreeHourWeather weatherForecast : forecast.getWeatherForecasts()) { assertNotNull(weatherForecast.getWeatherStates()); assertNotNull(weatherForecast.getForecastTime()); assertNotNull(weatherForecast.getTemperature()); @@ -271,140 +249,38 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { @Test public void whenGetForecastByCoordinatesRequestAsJSON_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String forecastJson = getClient() .forecast5Day3HourStep() - .byCoordinates(Coordinates.of(5, 5)) + .byCoordinates(new Coordinates(5, 5)) .language(Language.SPANISH) - .unitSystem(UnitSystem.IMPERIAL) .count(15) .retrieve() - .asJSON(); + .asJSON(UnitSystem.IMPERIAL); assertTrue(forecastJson.startsWith("{")); } @Test public void whenGetForecastByCoordinatesRequestAsXML_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String forecastXml = getClient() .forecast5Day3HourStep() - .byCoordinates(Coordinates.of(5, 5)) + .byCoordinates(new Coordinates(5, 5)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieve() - .asXML(); - - assertTrue(forecastXml.startsWith("<")); - } - - @Test - public void whenGetForecastByZipCodeInUSARequestAsJava_thenReturnNotNull() { - final Forecast forecast = getClient() - .forecast5Day3HourStep() - .byZipCodeInUSA("10005") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .count(15) - .retrieve() - .asJava(); - - assertNotNull(forecast); - assertNotNull(forecast.getLocation()); - assertNotNull(forecast.getWeatherForecasts()); - for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) { - assertNotNull(weatherForecast.getWeatherStates()); - assertNotNull(weatherForecast.getForecastTime()); - assertNotNull(weatherForecast.getTemperature()); - assertNotNull(weatherForecast.getAtmosphericPressure()); - assertNotNull(weatherForecast.getHumidity()); - assertNotNull(weatherForecast.getWind()); - } - } - - @Test - public void whenGetForecastByZipCodeInUSARequestAsJSON_thenReturnNotNull() { - final String forecastJson = getClient() - .forecast5Day3HourStep() - .byZipCodeInUSA("10005") - .language(Language.SPANISH) - .unitSystem(UnitSystem.IMPERIAL) - .count(15) - .retrieve() - .asJSON(); - - assertTrue(forecastJson.startsWith("{")); - } - - @Test - public void whenGetForecastByZipCodeInUSARequestAsXML_thenReturnNotNull() { - final String forecastXml = getClient() - .forecast5Day3HourStep() - .byZipCodeInUSA("10005") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asXML(); - - assertTrue(forecastXml.startsWith("<")); - } - - @Test - public void whenGetForecastByZipCodeAndCountryCodeRequestAsJava_thenReturnNotNull() { - final Forecast forecast = getClient() - .forecast5Day3HourStep() - .byZipCodeAndCountry("220015", "by") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .count(15) - .retrieve() - .asJava(); - - assertNotNull(forecast); - assertNotNull(forecast.getLocation()); - assertNotNull(forecast.getWeatherForecasts()); - for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) { - assertNotNull(weatherForecast.getWeatherStates()); - assertNotNull(weatherForecast.getForecastTime()); - assertNotNull(weatherForecast.getTemperature()); - assertNotNull(weatherForecast.getAtmosphericPressure()); - assertNotNull(weatherForecast.getHumidity()); - assertNotNull(weatherForecast.getWind()); - } - } - - @Test - public void whenGetForecastByZipCodeAndCountryCodeRequestAsJSON_thenReturnNotNull() { - final String forecastJson = getClient() - .forecast5Day3HourStep() - .byZipCodeAndCountry("220015", "by") - .language(Language.SPANISH) - .unitSystem(UnitSystem.IMPERIAL) - .count(15) - .retrieve() - .asJSON(); - - assertTrue(forecastJson.startsWith("{")); - } - - @Test - public void whenGetForecastByZipCodeAndCountryCodeRequestAsXML_thenReturnNotNull() { - final String forecastXml = getClient() - .forecast5Day3HourStep() - .byZipCodeAndCountry("220015", "by") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asXML(); + .asXML(UnitSystem.METRIC); assertTrue(forecastXml.startsWith("<")); } @Test public void whenGetForecastByCityNameAsyncRequestAsJava_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture forecastFuture = getClient() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + final CompletableFuture forecastFuture = getClient() .forecast5Day3HourStep() .byCityName("Minsk") .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .count(15) .retrieveAsync() .asJava(); @@ -413,50 +289,9 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest { System.out.println(forecastFuture.get()); } - @Test - public void whenGetForecastByCityNameAsyncRequestAsJSON_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture forecastFuture = getClient() - .forecast5Day3HourStep() - .byCityId(350001514) - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .count(15) - .retrieveAsync() - .asJSON(); - - assertNotNull(forecastFuture); - System.out.println(forecastFuture.get()); - } - - @Test - public void whenGetForecastByCityNameAsyncRequestAsXML_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture forecastFuture = getClient() - .forecast5Day3HourStep() - .byCityId(350001514) - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .count(15) - .retrieveAsync() - .asXML(); - - assertNotNull(forecastFuture); - System.out.println(forecastFuture.get()); - } - - @Test - public void whenRequestCurrentWeatherWithInvalidApiKey_thenThrowAnException() { - OpenWeatherMapClient client = new OpenWeatherMapClient("invalidKey"); - assertThrows(InvalidAuthTokenException.class, () -> - client - .forecast5Day3HourStep() - .byCityId(350001514) - .retrieve() - .asJSON() - ); - } - @Test public void whenRequestCurrentWeatherForInvalidLocation_thenThrowAnException() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); assertThrows(NoDataFoundException.class, () -> getClient() .forecast5Day3HourStep() diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminatorTest.java new file mode 100644 index 0000000..fc0d74f --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminatorTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021-present 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.free; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecastModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class FiveDayThreeHourStepForecastRequestTerminatorTest { + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final FiveDayThreeHourStepForecastRequestTerminator underTest = + new FiveDayThreeHourStepForecastRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final FiveDayThreeHourStepForecastRequestTerminator underTest = + new FiveDayThreeHourStepForecastRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(FiveDaysThreeHoursForecastModel.class, actual); + } +} 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 f29a53b..17fe853 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,36 +22,43 @@ 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.free.Forecast; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.prominence.openweathermap.api.model.forecast.free.FiveDaysThreeHoursForecastModel; +import com.github.prominence.openweathermap.api.model.generic.precipitation.PrecipitationValues; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.math.BigDecimal; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; public class FiveDayThreeHourStepForecastResponseMapperUnitTest { @Test public void mapToForecast_invalidJSON() { final String jsonString = "{\"cod\":\"200\",\"message:0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619},\"country\":\"BY\",\"population\":0,\"timezone\":10800,\"sunrise\":1617938579,\"sunset\":1617987553}}"; - assertThrows(RuntimeException.class, () -> new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.IMPERIAL).mapToForecast(jsonString)); + assertThrows(JsonProcessingException.class, () -> new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class)); } @Test - public void mapToForecast_whenSysNodeIsNotSet() { + public void mapToForecast_whenSysNodeIsNotSet() throws JsonProcessingException { final String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619},\"country\":\"BY\",\"population\":0,\"timezone\":10800,\"sunrise\":1617938579,\"sunset\":1617987553}}"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + final FiveDaysThreeHoursForecastModel forecast = new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNotNull(forecast.getWeatherForecasts()); - forecast.getWeatherForecasts().forEach(weatherForecast -> assertNull(weatherForecast.getDayTime())); + forecast.getWeatherForecasts().forEach(weatherForecast -> assertNull(weatherForecast.getPartOfDay())); } @Test - public void mapToForest_whenWeatherStateIsNotSet() { + public void mapToForest_whenWeatherStateIsNotSet() throws JsonProcessingException { final String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619},\"country\":\"BY\",\"population\":0,\"timezone\":10800,\"sunrise\":1617938579,\"sunset\":1617987553}}"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + final FiveDaysThreeHoursForecastModel forecast = new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); @@ -60,9 +67,9 @@ public class FiveDayThreeHourStepForecastResponseMapperUnitTest { } @Test - public void mapToForest_withTemperatureVariants() { + public void mapToForest_withTemperatureVariants() throws JsonProcessingException { final String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619},\"country\":\"BY\",\"population\":0,\"timezone\":10800,\"sunrise\":1617938579,\"sunset\":1617987553}}"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + final FiveDaysThreeHoursForecastModel forecast = new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); @@ -71,9 +78,9 @@ public class FiveDayThreeHourStepForecastResponseMapperUnitTest { } @Test - public void mapToForest_withPressureVariants() { + public void mapToForest_withPressureVariants() throws JsonProcessingException { final String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619},\"country\":\"BY\",\"population\":0,\"timezone\":10800,\"sunrise\":1617938579,\"sunset\":1617987553}}"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + final FiveDaysThreeHoursForecastModel forecast = new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); @@ -82,9 +89,9 @@ public class FiveDayThreeHourStepForecastResponseMapperUnitTest { } @Test - public void mapToForest_withWindVariants() { + public void mapToForest_withWindVariants() throws JsonProcessingException { final String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619},\"country\":\"BY\",\"population\":0,\"timezone\":10800,\"sunrise\":1617938579,\"sunset\":1617987553}}"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + final FiveDaysThreeHoursForecastModel forecast = new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); @@ -93,45 +100,49 @@ public class FiveDayThreeHourStepForecastResponseMapperUnitTest { } @Test - public void mapToForest_withRainVariants() { + public void mapToForest_withRainVariants() throws JsonProcessingException { final String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"rain\":{\"3h\":2.44},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"rain\":{},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619},\"country\":\"BY\",\"population\":0,\"timezone\":10800,\"sunrise\":1617938579,\"sunset\":1617987553}}"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + final FiveDaysThreeHoursForecastModel forecast = new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNotNull(forecast.getWeatherForecasts()); - assertEquals(2.44, forecast.getWeatherForecasts().get(0).getRain().getThreeHourLevel(), 0.00001); - forecast.getWeatherForecasts().stream().skip(1).forEach(weatherForecast -> assertNull(weatherForecast.getRain())); + assertEquals(BigDecimal.valueOf(2.44), forecast.getWeatherForecasts().get(0).getThreeHoursPrecipitation().getRain()); + forecast.getWeatherForecasts().stream().skip(1) + .forEach(weatherForecast -> assertNull(Optional.ofNullable(weatherForecast.getThreeHoursPrecipitation()) + .map(PrecipitationValues::getRain).orElse(null))); } @Test - public void mapToForest_withSnowVariants() { + public void mapToForest_withSnowVariants() throws JsonProcessingException { final String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"snow\":{\"3h\":2.44},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"snow\":{},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619},\"country\":\"BY\",\"population\":0,\"timezone\":10800,\"sunrise\":1617938579,\"sunset\":1617987553}}"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + final FiveDaysThreeHoursForecastModel forecast = new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNotNull(forecast.getWeatherForecasts()); - assertEquals(2.44, forecast.getWeatherForecasts().get(0).getSnow().getThreeHourLevel(), 0.00001); - forecast.getWeatherForecasts().stream().skip(1).forEach(weatherForecast -> assertNull(weatherForecast.getSnow())); + assertEquals(BigDecimal.valueOf(2.44), forecast.getWeatherForecasts().get(0).getThreeHoursPrecipitation().getSnow()); + forecast.getWeatherForecasts().stream().skip(1) + .forEach(weatherForecast -> assertNull(Optional.ofNullable(weatherForecast.getThreeHoursPrecipitation()) + .map(PrecipitationValues::getSnow).orElse(null))); } @Test - public void mapToForest_withCloudsVariants() { + public void mapToForest_withCloudsVariants() throws JsonProcessingException { final String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619},\"country\":\"BY\",\"population\":0,\"timezone\":10800,\"sunrise\":1617938579,\"sunset\":1617987553}}"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + final FiveDaysThreeHoursForecastModel forecast = new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNotNull(forecast.getWeatherForecasts()); - assertNull(forecast.getWeatherForecasts().get(0).getClouds()); + assertNull(forecast.getWeatherForecasts().get(0).getClouds().getCoveragePercentage()); forecast.getWeatherForecasts().stream().skip(1).forEach(weatherForecast -> assertNotNull(weatherForecast.getClouds())); } @Test - public void mapToForest_withLocationVariants() { + public void mapToForest_withLocationVariants() throws JsonProcessingException { final String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\"}}"; - final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + final FiveDaysThreeHoursForecastModel forecast = new ObjectMapper().readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); @@ -139,33 +150,20 @@ public class FiveDayThreeHourStepForecastResponseMapperUnitTest { } @Test - public void mapToForest_withCoordinateVariants() { + public void mapToForest_withCoordinateVariants() throws JsonProcessingException { + final ObjectMapper objectMapper = new ObjectMapper(); String jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023,\"lon\":27.5619}}}"; - Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + FiveDaysThreeHoursForecastModel forecast = objectMapper.readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNotNull(forecast.getLocation().getCoordinates()); - jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lon\":27.5619}}}"; - forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); - - assertNotNull(forecast); - assertNotNull(forecast.getLocation()); - assertNull(forecast.getLocation().getCoordinates()); - - jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{\"lat\":53.9023}}}"; - forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); - - assertNotNull(forecast); - assertNotNull(forecast.getLocation()); - assertNull(forecast.getLocation().getCoordinates()); - - jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\",\"coord\":{}}}"; - forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonString); + jsonString = "{\"cod\":\"200\",\"message\":0,\"cnt\":15,\"list\":[{\"dt\":1618002000,\"main\":{\"temp\":3.77,\"feels_like\":-0.66,\"temp_min\":3.59,\"temp_max\":3.77,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":64,\"temp_kf\":0.18},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03n\"}],\"clouds\":{\"all\":47},\"wind\":{\"speed\":5.99,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-09 21:00:00\"},{\"dt\":1618012800,\"main\":{\"temp\":3.12,\"feels_like\":-1.31,\"temp_min\":2.89,\"temp_max\":3.12,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":994,\"humidity\":69,\"temp_kf\":0.23},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":77},\"wind\":{\"speed\":5.61,\"deg\":192},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 00:00:00\"},{\"dt\":1618023600,\"main\":{\"temp\":2.13,\"feels_like\":-2.49,\"temp_min\":2.01,\"temp_max\":2.13,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":75,\"temp_kf\":0.12},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":94},\"wind\":{\"speed\":5.46,\"deg\":188},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 03:00:00\"},{\"dt\":1618034400,\"main\":{\"temp\":3.74,\"feels_like\":-1.01,\"temp_min\":3.74,\"temp_max\":3.74,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":70,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":6.75,\"deg\":189},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 06:00:00\"},{\"dt\":1618045200,\"main\":{\"temp\":8.81,\"feels_like\":5.15,\"temp_min\":8.81,\"temp_max\":8.81,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":993,\"humidity\":53,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":61},\"wind\":{\"speed\":7.91,\"deg\":198},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 09:00:00\"},{\"dt\":1618056000,\"main\":{\"temp\":11.76,\"feels_like\":10.19,\"temp_min\":11.76,\"temp_max\":11.76,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":46,\"temp_kf\":0},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":64},\"wind\":{\"speed\":8.24,\"deg\":210},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 12:00:00\"},{\"dt\":1618066800,\"main\":{\"temp\":11.48,\"feels_like\":10.09,\"temp_min\":11.48,\"temp_max\":11.48,\"pressure\":1018,\"sea_level\":1018,\"grnd_level\":993,\"humidity\":54,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":86},\"wind\":{\"speed\":5.45,\"deg\":213},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-10 15:00:00\"},{\"dt\":1618077600,\"main\":{\"temp\":9.1,\"feels_like\":7.02,\"temp_min\":9.1,\"temp_max\":9.1,\"pressure\":1019,\"sea_level\":1019,\"grnd_level\":994,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":3.74,\"deg\":186},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 18:00:00\"},{\"dt\":1618088400,\"main\":{\"temp\":7.53,\"feels_like\":5.06,\"temp_min\":7.53,\"temp_max\":7.53,\"pressure\":1020,\"sea_level\":1020,\"grnd_level\":995,\"humidity\":71,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":95},\"wind\":{\"speed\":3.83,\"deg\":199},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-10 21:00:00\"},{\"dt\":1618099200,\"main\":{\"temp\":6.68,\"feels_like\":4.64,\"temp_min\":6.68,\"temp_max\":6.68,\"pressure\":1022,\"sea_level\":1022,\"grnd_level\":996,\"humidity\":77,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":92},\"wind\":{\"speed\":2.84,\"deg\":206},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 00:00:00\"},{\"dt\":1618110000,\"main\":{\"temp\":5.83,\"feels_like\":3.27,\"temp_min\":5.83,\"temp_max\":5.83,\"pressure\":1023,\"sea_level\":1023,\"grnd_level\":997,\"humidity\":81,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"clouds\":{\"all\":96},\"wind\":{\"speed\":3.34,\"deg\":186},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2021-04-11 03:00:00\"},{\"dt\":1618120800,\"main\":{\"temp\":7.31,\"feels_like\":4.64,\"temp_min\":7.31,\"temp_max\":7.31,\"pressure\":1024,\"sea_level\":1024,\"grnd_level\":998,\"humidity\":76,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":98},\"wind\":{\"speed\":4.12,\"deg\":196},\"visibility\":10000,\"pop\":0.02,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 06:00:00\"},{\"dt\":1618131600,\"main\":{\"temp\":11,\"feels_like\":9.83,\"temp_min\":11,\"temp_max\":11,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":64,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":4.69,\"deg\":194},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 09:00:00\"},{\"dt\":1618142400,\"main\":{\"temp\":14.78,\"feels_like\":13.59,\"temp_min\":14.78,\"temp_max\":14.78,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":49,\"temp_kf\":0},\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":100},\"wind\":{\"speed\":5.6,\"deg\":190},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 12:00:00\"},{\"dt\":1618153200,\"main\":{\"temp\":14.58,\"feels_like\":13.4,\"temp_min\":14.58,\"temp_max\":14.58,\"pressure\":1025,\"sea_level\":1025,\"grnd_level\":1000,\"humidity\":50,\"temp_kf\":0},\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"clouds\":{\"all\":30},\"wind\":{\"speed\":4.77,\"deg\":177},\"visibility\":10000,\"pop\":0,\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2021-04-11 15:00:00\"}],\"city\":{\"id\":350001514,\"name\":\"Minsk\"}}"; + forecast = objectMapper.readValue(jsonString, FiveDaysThreeHoursForecastModel.class); assertNotNull(forecast); assertNotNull(forecast.getLocation()); assertNull(forecast.getLocation().getCoordinates()); } -} \ No newline at end of file +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..9025de7 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastAsyncRequestTerminatorTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class FourDaysHourlyForecastAsyncRequestTerminatorTest { + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final FourDaysHourlyForecastAsyncRequestTerminator underTest = + new FourDaysHourlyForecastAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminatorTest.java new file mode 100644 index 0000000..9bad174 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/FourDaysHourlyForecastRequestTerminatorTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.forecast.hourly.FourDaysHourlyForecastModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class FourDaysHourlyForecastRequestTerminatorTest { + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final FourDaysHourlyForecastRequestTerminator underTest = + new FourDaysHourlyForecastRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final FourDaysHourlyForecastRequestTerminator underTest = + new FourDaysHourlyForecastRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(FourDaysHourlyForecastModel.class, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/HourlyForecastIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/HourlyForecastIntegrationTest.java new file mode 100644 index 0000000..7ebf4a0 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/hourly/HourlyForecastIntegrationTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021-present 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.OpenWeatherMapClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.core.net.HttpClient; +import com.github.prominence.openweathermap.api.enums.Language; +import com.github.prominence.openweathermap.api.model.forecast.hourly.FourDaysHourlyForecast; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class HourlyForecastIntegrationTest { + + @Test + public void testBuilder_ShouldGenerateExpectedUrl_whenCalledWithValidData() { + //given + final HttpClient httpClient = mock(HttpClient.class); + final ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + final ApiConfiguration configuration = ApiConfiguration.builder().apiKey("apiKeyValue").httpClient(httpClient).build(); + when(httpClient.executeGetRequest(urlCaptor.capture())).thenReturn("{}"); + + //when + final FourDaysHourlyForecast actual = new OpenWeatherMapClient(configuration) + .forecastHourly4Days() + .byCoordinates(new Coordinates(53.54, 27.34)) + .language(Language.ENGLISH) + .retrieve() + .asJava(); + + //then + assertEquals("https://pro.openweathermap.org/data/2.5/forecast/hourly?mode=json&lon=27.34&units=standard&lang=en&lat=53.54&appid=apiKeyValue", urlCaptor.getValue()); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/generic/GenericListRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/generic/GenericListRequestTerminatorTest.java new file mode 100644 index 0000000..28d84b5 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/generic/GenericListRequestTerminatorTest.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.ResponseType; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.exception.ApiPayloadParseException; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.clouds.Clouds; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Test; +import org.mockito.InOrder; + +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.spy; + +class GenericListRequestTerminatorTest { + + private static final String ALL_50 = "[{\"all\":50}]"; + + @Test + void testAsJava_ShouldMapRawResponseToJavObject_WhenRawResponseExists() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final GenericListRequestTerminator underTest = + new GenericListRequestTerminator(requestSettings) { + @Override + protected Class getValueType() { + return CloudCoverage.class; + } + + @Override + protected Class getInnerType() { + return Clouds.class; + } + + + @Override + protected String getRawResponse() { + return ALL_50; + } + }; + + //when + final List actual = underTest.asJava(); + + //then + assertIterableEquals(Collections.singletonList(new Clouds(50)), actual); + } + + @Test + void testAsJava_ShouldThrowApiPayloadParseException_WhenRawResponseCannotBeMapped() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final GenericListRequestTerminator underTest = + new GenericListRequestTerminator(requestSettings) { + @Override + protected Class getValueType() { + return CloudCoverage.class; + } + + @Override + protected Class getInnerType() { + return Clouds.class; + } + + + @Override + protected String getRawResponse() { + return "INVALID"; + } + }; + + //when + assertThrows(ApiPayloadParseException.class, underTest::asJava); + + //then + exception + } + + @Test + void testAsJava_ShouldSetUnitSystemToStandard_WhenTheRequestIsPrepared() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + requestSettings.setUnitSystem(UnitSystem.IMPERIAL); + RequestSettings spyRequestSettings = spy(requestSettings); + final GenericListRequestTerminator underTest = + spy(new GenericListRequestTerminator(spyRequestSettings) { + @Override + protected Class getValueType() { + return CloudCoverage.class; + } + + @Override + protected Class getInnerType() { + return Clouds.class; + } + + + @Override + protected String getRawResponse() { + return ALL_50; + } + }); + + //when + underTest.asJava(); + + //then + final InOrder inOrder = inOrder(spyRequestSettings, underTest); + inOrder.verify(spyRequestSettings).setUnitSystem(eq(UnitSystem.STANDARD)); + inOrder.verify(underTest).getRawResponse(); + } + + @Test + void testAsJson_ShouldSetTheUnitSystemAndTheResponseType_WhenTheRequestIsPrepared() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + requestSettings.setUnitSystem(UnitSystem.IMPERIAL); + RequestSettings spyRequestSettings = spy(requestSettings); + final GenericListRequestTerminator underTest = + spy(new GenericListRequestTerminator(spyRequestSettings) { + @Override + protected Class getValueType() { + return CloudCoverage.class; + } + + @Override + protected Class getInnerType() { + return Clouds.class; + } + + + @Override + protected String getRawResponse() { + return ALL_50; + } + }); + + //when + final String actual = underTest.asJSON(UnitSystem.METRIC); + + //then + assertEquals(ALL_50, actual); + final InOrder inOrder = inOrder(spyRequestSettings, underTest); + inOrder.verify(spyRequestSettings).setUnitSystem(UnitSystem.METRIC); + inOrder.verify(spyRequestSettings).setResponseType(ResponseType.JSON); + inOrder.verify(underTest).getRawResponse(); + } + + @Test + void testAsXml_ShouldSetTheUnitSystemAndTheResponseType_WhenTheRequestIsPrepared() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + requestSettings.setUnitSystem(UnitSystem.IMPERIAL); + RequestSettings spyRequestSettings = spy(requestSettings); + final GenericListRequestTerminator underTest = + spy(new GenericListRequestTerminator(spyRequestSettings) { + @Override + protected Class getValueType() { + return CloudCoverage.class; + } + + @Override + protected Class getInnerType() { + return Clouds.class; + } + + + @Override + protected String getRawResponse() { + return ALL_50; + } + }); + + //when + final String actual = underTest.asXML(UnitSystem.METRIC); + + //then + assertEquals(ALL_50, actual); + final InOrder inOrder = inOrder(spyRequestSettings, underTest); + inOrder.verify(spyRequestSettings).setUnitSystem(UnitSystem.METRIC); + inOrder.verify(spyRequestSettings).setResponseType(ResponseType.XML); + inOrder.verify(underTest).getRawResponse(); + } + + @Test + void testAsHtml_ShouldSetTheUnitSystemAndTheResponseType_WhenTheRequestIsPrepared() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + requestSettings.setUnitSystem(UnitSystem.IMPERIAL); + RequestSettings spyRequestSettings = spy(requestSettings); + final GenericListRequestTerminator underTest = + spy(new GenericListRequestTerminator(spyRequestSettings) { + @Override + protected Class getValueType() { + return CloudCoverage.class; + } + + @Override + protected Class getInnerType() { + return Clouds.class; + } + + + @Override + protected String getRawResponse() { + return ALL_50; + } + }); + + //when + final String actual = underTest.asHTML(UnitSystem.METRIC); + + //then + assertEquals(ALL_50, actual); + final InOrder inOrder = inOrder(spyRequestSettings, underTest); + inOrder.verify(spyRequestSettings).setUnitSystem(UnitSystem.METRIC); + inOrder.verify(spyRequestSettings).setResponseType(ResponseType.HTML); + inOrder.verify(underTest).getRawResponse(); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/generic/GenericRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/generic/GenericRequestTerminatorTest.java new file mode 100644 index 0000000..533a6d2 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/generic/GenericRequestTerminatorTest.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2021-present 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.generic; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.ResponseType; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.exception.ApiPayloadParseException; +import com.github.prominence.openweathermap.api.model.generic.clouds.CloudCoverage; +import com.github.prominence.openweathermap.api.model.generic.clouds.Clouds; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Test; +import org.mockito.InOrder; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.spy; + +class GenericRequestTerminatorTest { + + private static final String ALL_50 = "{\"all\":50}"; + + @Test + void testAsJava_ShouldMapRawResponseToJavObject_WhenRawResponseExists() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + GenericRequestTerminator underTest = new GenericRequestTerminator(requestSettings) { + @Override + protected Class getValueType() { + return Clouds.class; + } + + @Override + protected String getRawResponse() { + return ALL_50; + } + }; + + //when + final CloudCoverage actual = underTest.asJava(); + + //then + assertEquals(new Clouds(50), actual); + } + + @Test + void testAsJava_ShouldThrowApiPayloadParseException_WhenRawResponseCannotBeMapped() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + GenericRequestTerminator underTest = new GenericRequestTerminator(requestSettings) { + @Override + protected Class getValueType() { + return Clouds.class; + } + + @Override + protected String getRawResponse() { + return "{\"all\":\"-\"}"; + } + }; + + //when + assertThrows(ApiPayloadParseException.class, underTest::asJava); + + //then + exception + } + + @Test + void testAsJava_ShouldSetUnitSystemToStandard_WhenTheRequestIsPrepared() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + requestSettings.setUnitSystem(UnitSystem.IMPERIAL); + RequestSettings spyRequestSettings = spy(requestSettings); + GenericRequestTerminator underTest = + spy(new GenericRequestTerminator(spyRequestSettings) { + @Override + protected Class getValueType() { + return Clouds.class; + } + + @Override + protected String getRawResponse() { + return ALL_50; + } + }); + + //when + underTest.asJava(); + + //then + final InOrder inOrder = inOrder(spyRequestSettings, underTest); + inOrder.verify(spyRequestSettings).setUnitSystem(eq(UnitSystem.STANDARD)); + inOrder.verify(underTest).getRawResponse(); + } + + @Test + void testAsJson_ShouldSetTheUnitSystemAndTheResponseType_WhenTheRequestIsPrepared() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + requestSettings.setUnitSystem(UnitSystem.IMPERIAL); + RequestSettings spyRequestSettings = spy(requestSettings); + GenericRequestTerminator underTest = + spy(new GenericRequestTerminator(spyRequestSettings) { + @Override + protected Class getValueType() { + return Clouds.class; + } + + @Override + protected String getRawResponse() { + return ALL_50; + } + }); + + //when + final String actual = underTest.asJSON(UnitSystem.METRIC); + + //then + assertEquals(ALL_50, actual); + final InOrder inOrder = inOrder(spyRequestSettings, underTest); + inOrder.verify(spyRequestSettings).setUnitSystem(UnitSystem.METRIC); + inOrder.verify(spyRequestSettings).setResponseType(ResponseType.JSON); + inOrder.verify(underTest).getRawResponse(); + } + + @Test + void testAsXml_ShouldSetTheUnitSystemAndTheResponseType_WhenTheRequestIsPrepared() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + requestSettings.setUnitSystem(UnitSystem.IMPERIAL); + RequestSettings spyRequestSettings = spy(requestSettings); + GenericRequestTerminator underTest = + spy(new GenericRequestTerminator(spyRequestSettings) { + @Override + protected Class getValueType() { + return Clouds.class; + } + + @Override + protected String getRawResponse() { + return ALL_50; + } + }); + + //when + final String actual = underTest.asXML(UnitSystem.METRIC); + + //then + assertEquals(ALL_50, actual); + final InOrder inOrder = inOrder(spyRequestSettings, underTest); + inOrder.verify(spyRequestSettings).setUnitSystem(UnitSystem.METRIC); + inOrder.verify(spyRequestSettings).setResponseType(ResponseType.XML); + inOrder.verify(underTest).getRawResponse(); + } + + @Test + void testAsHtml_ShouldSetTheUnitSystemAndTheResponseType_WhenTheRequestIsPrepared() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + requestSettings.setUnitSystem(UnitSystem.IMPERIAL); + RequestSettings spyRequestSettings = spy(requestSettings); + GenericRequestTerminator underTest = + spy(new GenericRequestTerminator(spyRequestSettings) { + @Override + protected Class getValueType() { + return Clouds.class; + } + + @Override + protected String getRawResponse() { + return ALL_50; + } + }); + + //when + final String actual = underTest.asHTML(UnitSystem.METRIC); + + //then + assertEquals(ALL_50, actual); + final InOrder inOrder = inOrder(spyRequestSettings, underTest); + inOrder.verify(spyRequestSettings).setUnitSystem(UnitSystem.METRIC); + inOrder.verify(spyRequestSettings).setResponseType(ResponseType.HTML); + inOrder.verify(underTest).getRawResponse(); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..9552a6f --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingAsyncRequestTerminatorTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class DirectGeocodingAsyncRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final DirectGeocodingAsyncRequestTerminator underTest = + new DirectGeocodingAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asXML(UnitSystem.STANDARD).get()); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final DirectGeocodingAsyncRequestTerminator underTest = + new DirectGeocodingAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestTerminatorTest.java new file mode 100644 index 0000000..3679191 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/DirectGeocodingRequestTerminatorTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.geocoding.Geocoding; +import com.github.prominence.openweathermap.api.model.geocoding.GeocodingModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class DirectGeocodingRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final DirectGeocodingRequestTerminator underTest = + new DirectGeocodingRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asXML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final DirectGeocodingRequestTerminator underTest = + new DirectGeocodingRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final DirectGeocodingRequestTerminator underTest = + new DirectGeocodingRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(Geocoding.class, actual); + } + + @Test + void testGetInnerType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final DirectGeocodingRequestTerminator underTest = + new DirectGeocodingRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getInnerType(); + + //then + assertEquals(GeocodingModel.class, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..d517ffe --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingAsyncRequestTerminatorTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class ZipCodeGeocodingAsyncRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ZipCodeGeocodingAsyncRequestTerminator underTest = + new ZipCodeGeocodingAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asXML(UnitSystem.STANDARD).get()); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ZipCodeGeocodingAsyncRequestTerminator underTest = + new ZipCodeGeocodingAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingRequestTerminatorTest.java new file mode 100644 index 0000000..2c25dba --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/direct/ZipCodeGeocodingRequestTerminatorTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ZipCodeGeocodingRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ZipCodeGeocodingRequestTerminator underTest = + new ZipCodeGeocodingRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asXML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ZipCodeGeocodingRequestTerminator underTest = + new ZipCodeGeocodingRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ZipCodeGeocodingRequestTerminator underTest = + new ZipCodeGeocodingRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(ZipCodeGeocodingModel.class, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..79c36f9 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingAsyncRequestTerminatorTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class ReverseGeocodingAsyncRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ReverseGeocodingAsyncRequestTerminator underTest = + new ReverseGeocodingAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asXML(UnitSystem.STANDARD).get()); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ReverseGeocodingAsyncRequestTerminator underTest = + new ReverseGeocodingAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestTerminatorTest.java new file mode 100644 index 0000000..6293400 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/geocoding/reverse/ReverseGeocodingRequestTerminatorTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.geocoding.Geocoding; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ReverseGeocodingRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ReverseGeocodingRequestTerminator underTest = + new ReverseGeocodingRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asXML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ReverseGeocodingRequestTerminator underTest = + new ReverseGeocodingRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final ReverseGeocodingRequestTerminator underTest = + new ReverseGeocodingRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(Geocoding.class, actual); + } +} 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 268b577..fb6d554 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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,65 +22,79 @@ package com.github.prominence.openweathermap.api.request.onecall; -import com.github.prominence.openweathermap.api.enums.UnitSystem; -import com.github.prominence.openweathermap.api.mapper.OneCallWeatherResponseMapper; -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.Assertions; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.prominence.openweathermap.api.model.onecall.current.OneCallCurrentForecastModel; +import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeather; +import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.io.IOException; +import java.math.BigDecimal; +import java.nio.charset.StandardCharsets; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; public class OneCallWeatherResponseMapperUnitTest { @Test public void mapToCurrent_withInvalidJSON() { - final String jsonString = "{\"lat\":53.54,\"lon\":27.34,timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"hourly\":[{\"dt\":1618048800,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":7.72,\"wind_deg\":200,\"wind_gust\":10.55,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618052400,\"temp\":11.6,\"feels_like\":9.96,\"pressure\":1018,\"humidity\":44,\"dew_point\":-0.2,\"uvi\":3.22,\"clouds\":32,\"visibility\":10000,\"wind_speed\":7.76,\"wind_deg\":202,\"wind_gust\":10.75,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618056000,\"temp\":12.26,\"feels_like\":10.72,\"pressure\":1018,\"humidity\":45,\"dew_point\":0.68,\"uvi\":2.67,\"clouds\":49,\"visibility\":10000,\"wind_speed\":7.66,\"wind_deg\":205,\"wind_gust\":10.76,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618059600,\"temp\":12.86,\"feels_like\":11.4,\"pressure\":1018,\"humidity\":46,\"dew_point\":1.53,\"uvi\":1.22,\"clouds\":19,\"visibility\":10000,\"wind_speed\":7.15,\"wind_deg\":210,\"wind_gust\":9.99,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618063200,\"temp\":13.04,\"feels_like\":11.68,\"pressure\":1018,\"humidity\":49,\"dew_point\":2.58,\"uvi\":0.7,\"clouds\":50,\"visibility\":10000,\"wind_speed\":5.95,\"wind_deg\":210,\"wind_gust\":9.4,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618066800,\"temp\":12.53,\"feels_like\":11.2,\"pressure\":1018,\"humidity\":52,\"dew_point\":3.07,\"uvi\":0.32,\"clouds\":48,\"visibility\":10000,\"wind_speed\":5.43,\"wind_deg\":209,\"wind_gust\":9.32,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618070400,\"temp\":11.02,\"feels_like\":9.72,\"pressure\":1018,\"humidity\":59,\"dew_point\":3.37,\"uvi\":0.12,\"clouds\":51,\"visibility\":10000,\"wind_speed\":4.22,\"wind_deg\":200,\"wind_gust\":8.94,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618074000,\"temp\":8.81,\"feels_like\":6.7,\"pressure\":1019,\"humidity\":67,\"dew_point\":3.23,\"uvi\":0,\"clouds\":55,\"visibility\":10000,\"wind_speed\":3.67,\"wind_deg\":184,\"wind_gust\":8.41,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618077600,\"temp\":7.94,\"feels_like\":5.47,\"pressure\":1020,\"humidity\":71,\"dew_point\":3.06,\"uvi\":0,\"clouds\":59,\"visibility\":10000,\"wind_speed\":4,\"wind_deg\":177,\"wind_gust\":10.47,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618081200,\"temp\":7.68,\"feels_like\":4.81,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.92,\"uvi\":0,\"clouds\":79,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":179,\"wind_gust\":12.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618084800,\"temp\":7.78,\"feels_like\":4.76,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.89,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":5.12,\"wind_deg\":185,\"wind_gust\":13.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618088400,\"temp\":7.45,\"feels_like\":4.33,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.77,\"uvi\":0,\"clouds\":86,\"visibility\":10000,\"wind_speed\":5.17,\"wind_deg\":190,\"wind_gust\":13.37,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618092000,\"temp\":6.97,\"feels_like\":3.85,\"pressure\":1021,\"humidity\":74,\"dew_point\":2.67,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":4.89,\"wind_deg\":192,\"wind_gust\":12.68,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618095600,\"temp\":6.46,\"feels_like\":3.4,\"pressure\":1021,\"humidity\":76,\"dew_point\":2.7,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":191,\"wind_gust\":11.89,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618099200,\"temp\":5.96,\"feels_like\":2.9,\"pressure\":1021,\"humidity\":79,\"dew_point\":2.65,\"uvi\":0,\"clouds\":91,\"visibility\":10000,\"wind_speed\":4.26,\"wind_deg\":188,\"wind_gust\":11.23,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618102800,\"temp\":5.31,\"feels_like\":2.22,\"pressure\":1022,\"humidity\":81,\"dew_point\":2.47,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.04,\"wind_deg\":186,\"wind_gust\":10.72,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618106400,\"temp\":5.2,\"feels_like\":2.18,\"pressure\":1022,\"humidity\":82,\"dew_point\":2.41,\"uvi\":0,\"clouds\":95,\"visibility\":10000,\"wind_speed\":3.87,\"wind_deg\":190,\"wind_gust\":10.92,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618110000,\"temp\":4.56,\"feels_like\":1.51,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.29,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":3.69,\"wind_deg\":186,\"wind_gust\":10.33,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618113600,\"temp\":4.51,\"feels_like\":1.64,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.33,\"uvi\":0,\"clouds\":84,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":191,\"wind_gust\":10.18,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618117200,\"temp\":6.05,\"feels_like\":3.41,\"pressure\":1024,\"humidity\":80,\"dew_point\":2.89,\"uvi\":0.15,\"clouds\":80,\"visibility\":10000,\"wind_speed\":3.55,\"wind_deg\":193,\"wind_gust\":10.09,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618120800,\"temp\":7.96,\"feels_like\":5.31,\"pressure\":1024,\"humidity\":72,\"dew_point\":3.29,\"uvi\":0.38,\"clouds\":80,\"visibility\":10000,\"wind_speed\":4.39,\"wind_deg\":197,\"wind_gust\":8.53,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618124400,\"temp\":9.61,\"feels_like\":7.3,\"pressure\":1024,\"humidity\":67,\"dew_point\":3.88,\"uvi\":1.01,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":197,\"wind_gust\":7.77,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618128000,\"temp\":11.14,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":62,\"dew_point\":4.27,\"uvi\":1.54,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":198,\"wind_gust\":7.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618131600,\"temp\":12.8,\"feels_like\":11.62,\"pressure\":1025,\"humidity\":57,\"dew_point\":4.57,\"uvi\":1.97,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.87,\"wind_deg\":196,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618135200,\"temp\":14.03,\"feels_like\":12.87,\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"uvi\":3.09,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.11,\"wind_deg\":194,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618138800,\"temp\":14.82,\"feels_like\":13.66,\"pressure\":1025,\"humidity\":50,\"dew_point\":4.62,\"uvi\":2.96,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.32,\"wind_deg\":191,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618142400,\"temp\":15.64,\"feels_like\":14.49,\"pressure\":1025,\"humidity\":47,\"dew_point\":4.48,\"uvi\":2.45,\"clouds\":94,\"visibility\":10000,\"wind_speed\":5.42,\"wind_deg\":192,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618146000,\"temp\":15.81,\"feels_like\":14.62,\"pressure\":1024,\"humidity\":45,\"dew_point\":4.15,\"uvi\":2.02,\"clouds\":24,\"visibility\":10000,\"wind_speed\":5.15,\"wind_deg\":193,\"wind_gust\":6.3,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618149600,\"temp\":15.71,\"feels_like\":14.51,\"pressure\":1025,\"humidity\":45,\"dew_point\":3.87,\"uvi\":1.17,\"clouds\":48,\"visibility\":10000,\"wind_speed\":4.79,\"wind_deg\":188,\"wind_gust\":6.01,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618153200,\"temp\":14.79,\"feels_like\":13.63,\"pressure\":1024,\"humidity\":50,\"dew_point\":4.71,\"uvi\":0.53,\"clouds\":63,\"visibility\":10000,\"wind_speed\":3.73,\"wind_deg\":177,\"wind_gust\":6.35,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618156800,\"temp\":12.85,\"feels_like\":11.73,\"pressure\":1024,\"humidity\":59,\"dew_point\":5.18,\"uvi\":0.17,\"clouds\":72,\"visibility\":10000,\"wind_speed\":3.05,\"wind_deg\":159,\"wind_gust\":6.38,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618160400,\"temp\":10.92,\"feels_like\":9.71,\"pressure\":1025,\"humidity\":63,\"dew_point\":4.26,\"uvi\":0,\"clouds\":78,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":152,\"wind_gust\":6.64,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618164000,\"temp\":9.65,\"feels_like\":7.72,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.66,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":3.68,\"wind_deg\":148,\"wind_gust\":9.04,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618167600,\"temp\":8.82,\"feels_like\":6.59,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.05,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.92,\"wind_deg\":147,\"wind_gust\":11.02,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618171200,\"temp\":8.07,\"feels_like\":5.87,\"pressure\":1026,\"humidity\":67,\"dew_point\":2.43,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.54,\"wind_deg\":154,\"wind_gust\":11.12,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618174800,\"temp\":7.24,\"feels_like\":4.99,\"pressure\":1027,\"humidity\":68,\"dew_point\":1.96,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.32,\"wind_deg\":154,\"wind_gust\":10.55,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618178400,\"temp\":6.58,\"feels_like\":4.31,\"pressure\":1027,\"humidity\":70,\"dew_point\":1.65,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.14,\"wind_deg\":154,\"wind_gust\":9.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618182000,\"temp\":6.03,\"feels_like\":3.57,\"pressure\":1027,\"humidity\":71,\"dew_point\":1.26,\"uvi\":0,\"clouds\":82,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":150,\"wind_gust\":8.44,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618185600,\"temp\":5.51,\"feels_like\":2.94,\"pressure\":1027,\"humidity\":72,\"dew_point\":0.95,\"uvi\":0,\"clouds\":71,\"visibility\":10000,\"wind_speed\":3.26,\"wind_deg\":150,\"wind_gust\":8.58,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618189200,\"temp\":5,\"feels_like\":2.29,\"pressure\":1027,\"humidity\":74,\"dew_point\":0.72,\"uvi\":0,\"clouds\":9,\"visibility\":10000,\"wind_speed\":3.3,\"wind_deg\":147,\"wind_gust\":8.63,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"pop\":0},{\"dt\":1618192800,\"temp\":4.47,\"feels_like\":1.69,\"pressure\":1027,\"humidity\":75,\"dew_point\":0.52,\"uvi\":0,\"clouds\":14,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":145,\"wind_gust\":8.14,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618196400,\"temp\":4.03,\"feels_like\":1.08,\"pressure\":1026,\"humidity\":76,\"dew_point\":0.22,\"uvi\":0,\"clouds\":12,\"visibility\":10000,\"wind_speed\":3.36,\"wind_deg\":138,\"wind_gust\":8.13,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618200000,\"temp\":4,\"feels_like\":0.9,\"pressure\":1026,\"humidity\":75,\"dew_point\":0.13,\"uvi\":0.08,\"clouds\":10,\"visibility\":10000,\"wind_speed\":3.57,\"wind_deg\":131,\"wind_gust\":9.24,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618203600,\"temp\":5.73,\"feels_like\":2.73,\"pressure\":1026,\"humidity\":68,\"dew_point\":0.52,\"uvi\":0.33,\"clouds\":8,\"visibility\":10000,\"wind_speed\":4.05,\"wind_deg\":138,\"wind_gust\":10.36,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618207200,\"temp\":7.87,\"feels_like\":4.9,\"pressure\":1025,\"humidity\":59,\"dew_point\":0.53,\"uvi\":0.84,\"clouds\":7,\"visibility\":10000,\"wind_speed\":5.05,\"wind_deg\":145,\"wind_gust\":10.48,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618210800,\"temp\":9.9,\"feels_like\":7.29,\"pressure\":1025,\"humidity\":53,\"dew_point\":0.8,\"uvi\":1.56,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.48,\"wind_deg\":147,\"wind_gust\":9.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618214400,\"temp\":11.5,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":47,\"dew_point\":0.86,\"uvi\":2.37,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.94,\"wind_deg\":152,\"wind_gust\":8.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618218000,\"temp\":12.64,\"feels_like\":11.08,\"pressure\":1024,\"humidity\":43,\"dew_point\":0.68,\"uvi\":3.04,\"clouds\":0,\"visibility\":10000,\"wind_speed\":6.25,\"wind_deg\":151,\"wind_gust\":8.5,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0}],\"daily\":[{\"dt\":1618048800,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":{\"day\":11.84,\"min\":1.69,\"max\":13.04,\"night\":7.78,\"eve\":11.02,\"morn\":1.69},\"feels_like\":{\"day\":10.12,\"night\":-2.86,\"eve\":9.72,\"morn\":-2.86},\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"wind_speed\":7.72,\"wind_deg\":200,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.36},{\"dt\":1618135200,\"sunrise\":1618111186,\"sunset\":1618160588,\"temp\":{\"day\":14.03,\"min\":4.51,\"max\":15.81,\"night\":8.07,\"eve\":12.85,\"morn\":4.51},\"feels_like\":{\"day\":12.87,\"night\":1.64,\"eve\":11.73,\"morn\":1.64},\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"wind_speed\":5.11,\"wind_deg\":194,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":100,\"pop\":0,\"uvi\":3.09},{\"dt\":1618221600,\"sunrise\":1618197445,\"sunset\":1618247098,\"temp\":{\"day\":13.62,\"min\":4,\"max\":14.94,\"night\":7.62,\"eve\":12.21,\"morn\":4},\"feels_like\":{\"day\":12.08,\"night\":0.9,\"eve\":10.87,\"morn\":0.9},\"pressure\":1024,\"humidity\":40,\"dew_point\":0.58,\"wind_speed\":6.09,\"wind_deg\":152,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.11},{\"dt\":1618308000,\"sunrise\":1618283705,\"sunset\":1618333607,\"temp\":{\"day\":14.42,\"min\":4.45,\"max\":16.91,\"night\":11.72,\"eve\":16.64,\"morn\":4.45},\"feels_like\":{\"day\":13.17,\"night\":2.28,\"eve\":15.43,\"morn\":2.28},\"pressure\":1019,\"humidity\":48,\"dew_point\":3.67,\"wind_speed\":3.07,\"wind_deg\":153,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":8,\"pop\":0,\"uvi\":3.53},{\"dt\":1618394400,\"sunrise\":1618369965,\"sunset\":1618420117,\"temp\":{\"day\":10.12,\"min\":7.84,\"max\":10.7,\"night\":8.87,\"eve\":9.78,\"morn\":7.84},\"feels_like\":{\"day\":9.54,\"night\":6.26,\"eve\":8.02,\"morn\":6.26},\"pressure\":1012,\"humidity\":90,\"dew_point\":8.65,\"wind_speed\":3.6,\"wind_deg\":129,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.98,\"rain\":2.37,\"uvi\":2.7},{\"dt\":1618480800,\"sunrise\":1618456226,\"sunset\":1618506627,\"temp\":{\"day\":8.88,\"min\":6.86,\"max\":10.63,\"night\":8.88,\"eve\":10.63,\"morn\":6.86},\"feels_like\":{\"day\":7.04,\"night\":5.16,\"eve\":9.81,\"morn\":5.16},\"pressure\":1011,\"humidity\":86,\"dew_point\":6.85,\"wind_speed\":3.22,\"wind_deg\":98,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.91,\"rain\":4.23,\"uvi\":3},{\"dt\":1618567200,\"sunrise\":1618542488,\"sunset\":1618593137,\"temp\":{\"day\":5.06,\"min\":4.81,\"max\":8.16,\"night\":4.84,\"eve\":7.24,\"morn\":5.39},\"feels_like\":{\"day\":2.81,\"night\":1.18,\"eve\":6.67,\"morn\":1.18},\"pressure\":1010,\"humidity\":91,\"dew_point\":3.81,\"wind_speed\":2.69,\"wind_deg\":101,\"weather\":[{\"id\":501,\"main\":\"Rain\",\"description\":\"moderate rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":1,\"rain\":15.37,\"uvi\":3},{\"dt\":1618653600,\"sunrise\":1618628751,\"sunset\":1618679646,\"temp\":{\"day\":3.07,\"min\":1.88,\"max\":5.32,\"night\":1.88,\"eve\":2.04,\"morn\":4.62},\"feels_like\":{\"day\":-0.42,\"night\":1.75,\"eve\":-1.74,\"morn\":1.75},\"pressure\":1010,\"humidity\":97,\"dew_point\":2.74,\"wind_speed\":3.86,\"wind_deg\":287,\"weather\":[{\"id\":616,\"main\":\"Snow\",\"description\":\"rain and snow\",\"icon\":\"13d\"}],\"clouds\":100,\"pop\":1,\"rain\":6.67,\"snow\":8.83,\"uvi\":3}]}"; - assertThrows(RuntimeException.class, () -> new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToCurrent(jsonString)); + final String jsonString = + "{\"lat\":53.54,\"lon\":27.34,timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"hourly\":[{\"dt\":1618048800,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":7.72,\"wind_deg\":200,\"wind_gust\":10.55,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618052400,\"temp\":11.6,\"feels_like\":9.96,\"pressure\":1018,\"humidity\":44,\"dew_point\":-0.2,\"uvi\":3.22,\"clouds\":32,\"visibility\":10000,\"wind_speed\":7.76,\"wind_deg\":202,\"wind_gust\":10.75,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618056000,\"temp\":12.26,\"feels_like\":10.72,\"pressure\":1018,\"humidity\":45,\"dew_point\":0.68,\"uvi\":2.67,\"clouds\":49,\"visibility\":10000,\"wind_speed\":7.66,\"wind_deg\":205,\"wind_gust\":10.76,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618059600,\"temp\":12.86,\"feels_like\":11.4,\"pressure\":1018,\"humidity\":46,\"dew_point\":1.53,\"uvi\":1.22,\"clouds\":19,\"visibility\":10000,\"wind_speed\":7.15,\"wind_deg\":210,\"wind_gust\":9.99,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618063200,\"temp\":13.04,\"feels_like\":11.68,\"pressure\":1018,\"humidity\":49,\"dew_point\":2.58,\"uvi\":0.7,\"clouds\":50,\"visibility\":10000,\"wind_speed\":5.95,\"wind_deg\":210,\"wind_gust\":9.4,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618066800,\"temp\":12.53,\"feels_like\":11.2,\"pressure\":1018,\"humidity\":52,\"dew_point\":3.07,\"uvi\":0.32,\"clouds\":48,\"visibility\":10000,\"wind_speed\":5.43,\"wind_deg\":209,\"wind_gust\":9.32,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618070400,\"temp\":11.02,\"feels_like\":9.72,\"pressure\":1018,\"humidity\":59,\"dew_point\":3.37,\"uvi\":0.12,\"clouds\":51,\"visibility\":10000,\"wind_speed\":4.22,\"wind_deg\":200,\"wind_gust\":8.94,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618074000,\"temp\":8.81,\"feels_like\":6.7,\"pressure\":1019,\"humidity\":67,\"dew_point\":3.23,\"uvi\":0,\"clouds\":55,\"visibility\":10000,\"wind_speed\":3.67,\"wind_deg\":184,\"wind_gust\":8.41,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618077600,\"temp\":7.94,\"feels_like\":5.47,\"pressure\":1020,\"humidity\":71,\"dew_point\":3.06,\"uvi\":0,\"clouds\":59,\"visibility\":10000,\"wind_speed\":4,\"wind_deg\":177,\"wind_gust\":10.47,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618081200,\"temp\":7.68,\"feels_like\":4.81,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.92,\"uvi\":0,\"clouds\":79,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":179,\"wind_gust\":12.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618084800,\"temp\":7.78,\"feels_like\":4.76,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.89,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":5.12,\"wind_deg\":185,\"wind_gust\":13.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618088400,\"temp\":7.45,\"feels_like\":4.33,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.77,\"uvi\":0,\"clouds\":86,\"visibility\":10000,\"wind_speed\":5.17,\"wind_deg\":190,\"wind_gust\":13.37,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618092000,\"temp\":6.97,\"feels_like\":3.85,\"pressure\":1021,\"humidity\":74,\"dew_point\":2.67,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":4.89,\"wind_deg\":192,\"wind_gust\":12.68,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618095600,\"temp\":6.46,\"feels_like\":3.4,\"pressure\":1021,\"humidity\":76,\"dew_point\":2.7,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":191,\"wind_gust\":11.89,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618099200,\"temp\":5.96,\"feels_like\":2.9,\"pressure\":1021,\"humidity\":79,\"dew_point\":2.65,\"uvi\":0,\"clouds\":91,\"visibility\":10000,\"wind_speed\":4.26,\"wind_deg\":188,\"wind_gust\":11.23,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618102800,\"temp\":5.31,\"feels_like\":2.22,\"pressure\":1022,\"humidity\":81,\"dew_point\":2.47,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.04,\"wind_deg\":186,\"wind_gust\":10.72,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618106400,\"temp\":5.2,\"feels_like\":2.18,\"pressure\":1022,\"humidity\":82,\"dew_point\":2.41,\"uvi\":0,\"clouds\":95,\"visibility\":10000,\"wind_speed\":3.87,\"wind_deg\":190,\"wind_gust\":10.92,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618110000,\"temp\":4.56,\"feels_like\":1.51,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.29,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":3.69,\"wind_deg\":186,\"wind_gust\":10.33,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618113600,\"temp\":4.51,\"feels_like\":1.64,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.33,\"uvi\":0,\"clouds\":84,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":191,\"wind_gust\":10.18,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618117200,\"temp\":6.05,\"feels_like\":3.41,\"pressure\":1024,\"humidity\":80,\"dew_point\":2.89,\"uvi\":0.15,\"clouds\":80,\"visibility\":10000,\"wind_speed\":3.55,\"wind_deg\":193,\"wind_gust\":10.09,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618120800,\"temp\":7.96,\"feels_like\":5.31,\"pressure\":1024,\"humidity\":72,\"dew_point\":3.29,\"uvi\":0.38,\"clouds\":80,\"visibility\":10000,\"wind_speed\":4.39,\"wind_deg\":197,\"wind_gust\":8.53,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618124400,\"temp\":9.61,\"feels_like\":7.3,\"pressure\":1024,\"humidity\":67,\"dew_point\":3.88,\"uvi\":1.01,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":197,\"wind_gust\":7.77,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618128000,\"temp\":11.14,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":62,\"dew_point\":4.27,\"uvi\":1.54,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":198,\"wind_gust\":7.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618131600,\"temp\":12.8,\"feels_like\":11.62,\"pressure\":1025,\"humidity\":57,\"dew_point\":4.57,\"uvi\":1.97,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.87,\"wind_deg\":196,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618135200,\"temp\":14.03,\"feels_like\":12.87,\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"uvi\":3.09,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.11,\"wind_deg\":194,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618138800,\"temp\":14.82,\"feels_like\":13.66,\"pressure\":1025,\"humidity\":50,\"dew_point\":4.62,\"uvi\":2.96,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.32,\"wind_deg\":191,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618142400,\"temp\":15.64,\"feels_like\":14.49,\"pressure\":1025,\"humidity\":47,\"dew_point\":4.48,\"uvi\":2.45,\"clouds\":94,\"visibility\":10000,\"wind_speed\":5.42,\"wind_deg\":192,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618146000,\"temp\":15.81,\"feels_like\":14.62,\"pressure\":1024,\"humidity\":45,\"dew_point\":4.15,\"uvi\":2.02,\"clouds\":24,\"visibility\":10000,\"wind_speed\":5.15,\"wind_deg\":193,\"wind_gust\":6.3,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618149600,\"temp\":15.71,\"feels_like\":14.51,\"pressure\":1025,\"humidity\":45,\"dew_point\":3.87,\"uvi\":1.17,\"clouds\":48,\"visibility\":10000,\"wind_speed\":4.79,\"wind_deg\":188,\"wind_gust\":6.01,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618153200,\"temp\":14.79,\"feels_like\":13.63,\"pressure\":1024,\"humidity\":50,\"dew_point\":4.71,\"uvi\":0.53,\"clouds\":63,\"visibility\":10000,\"wind_speed\":3.73,\"wind_deg\":177,\"wind_gust\":6.35,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618156800,\"temp\":12.85,\"feels_like\":11.73,\"pressure\":1024,\"humidity\":59,\"dew_point\":5.18,\"uvi\":0.17,\"clouds\":72,\"visibility\":10000,\"wind_speed\":3.05,\"wind_deg\":159,\"wind_gust\":6.38,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618160400,\"temp\":10.92,\"feels_like\":9.71,\"pressure\":1025,\"humidity\":63,\"dew_point\":4.26,\"uvi\":0,\"clouds\":78,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":152,\"wind_gust\":6.64,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618164000,\"temp\":9.65,\"feels_like\":7.72,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.66,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":3.68,\"wind_deg\":148,\"wind_gust\":9.04,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618167600,\"temp\":8.82,\"feels_like\":6.59,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.05,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.92,\"wind_deg\":147,\"wind_gust\":11.02,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618171200,\"temp\":8.07,\"feels_like\":5.87,\"pressure\":1026,\"humidity\":67,\"dew_point\":2.43,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.54,\"wind_deg\":154,\"wind_gust\":11.12,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618174800,\"temp\":7.24,\"feels_like\":4.99,\"pressure\":1027,\"humidity\":68,\"dew_point\":1.96,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.32,\"wind_deg\":154,\"wind_gust\":10.55,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618178400,\"temp\":6.58,\"feels_like\":4.31,\"pressure\":1027,\"humidity\":70,\"dew_point\":1.65,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.14,\"wind_deg\":154,\"wind_gust\":9.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618182000,\"temp\":6.03,\"feels_like\":3.57,\"pressure\":1027,\"humidity\":71,\"dew_point\":1.26,\"uvi\":0,\"clouds\":82,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":150,\"wind_gust\":8.44,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618185600,\"temp\":5.51,\"feels_like\":2.94,\"pressure\":1027,\"humidity\":72,\"dew_point\":0.95,\"uvi\":0,\"clouds\":71,\"visibility\":10000,\"wind_speed\":3.26,\"wind_deg\":150,\"wind_gust\":8.58,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618189200,\"temp\":5,\"feels_like\":2.29,\"pressure\":1027,\"humidity\":74,\"dew_point\":0.72,\"uvi\":0,\"clouds\":9,\"visibility\":10000,\"wind_speed\":3.3,\"wind_deg\":147,\"wind_gust\":8.63,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"pop\":0},{\"dt\":1618192800,\"temp\":4.47,\"feels_like\":1.69,\"pressure\":1027,\"humidity\":75,\"dew_point\":0.52,\"uvi\":0,\"clouds\":14,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":145,\"wind_gust\":8.14,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618196400,\"temp\":4.03,\"feels_like\":1.08,\"pressure\":1026,\"humidity\":76,\"dew_point\":0.22,\"uvi\":0,\"clouds\":12,\"visibility\":10000,\"wind_speed\":3.36,\"wind_deg\":138,\"wind_gust\":8.13,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618200000,\"temp\":4,\"feels_like\":0.9,\"pressure\":1026,\"humidity\":75,\"dew_point\":0.13,\"uvi\":0.08,\"clouds\":10,\"visibility\":10000,\"wind_speed\":3.57,\"wind_deg\":131,\"wind_gust\":9.24,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618203600,\"temp\":5.73,\"feels_like\":2.73,\"pressure\":1026,\"humidity\":68,\"dew_point\":0.52,\"uvi\":0.33,\"clouds\":8,\"visibility\":10000,\"wind_speed\":4.05,\"wind_deg\":138,\"wind_gust\":10.36,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618207200,\"temp\":7.87,\"feels_like\":4.9,\"pressure\":1025,\"humidity\":59,\"dew_point\":0.53,\"uvi\":0.84,\"clouds\":7,\"visibility\":10000,\"wind_speed\":5.05,\"wind_deg\":145,\"wind_gust\":10.48,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618210800,\"temp\":9.9,\"feels_like\":7.29,\"pressure\":1025,\"humidity\":53,\"dew_point\":0.8,\"uvi\":1.56,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.48,\"wind_deg\":147,\"wind_gust\":9.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618214400,\"temp\":11.5,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":47,\"dew_point\":0.86,\"uvi\":2.37,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.94,\"wind_deg\":152,\"wind_gust\":8.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618218000,\"temp\":12.64,\"feels_like\":11.08,\"pressure\":1024,\"humidity\":43,\"dew_point\":0.68,\"uvi\":3.04,\"clouds\":0,\"visibility\":10000,\"wind_speed\":6.25,\"wind_deg\":151,\"wind_gust\":8.5,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0}],\"daily\":[{\"dt\":1618048800,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":{\"day\":11.84,\"min\":1.69,\"max\":13.04,\"night\":7.78,\"eve\":11.02,\"morn\":1.69},\"feels_like\":{\"day\":10.12,\"night\":-2.86,\"eve\":9.72,\"morn\":-2.86},\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"wind_speed\":7.72,\"wind_deg\":200,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.36},{\"dt\":1618135200,\"sunrise\":1618111186,\"sunset\":1618160588,\"temp\":{\"day\":14.03,\"min\":4.51,\"max\":15.81,\"night\":8.07,\"eve\":12.85,\"morn\":4.51},\"feels_like\":{\"day\":12.87,\"night\":1.64,\"eve\":11.73,\"morn\":1.64},\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"wind_speed\":5.11,\"wind_deg\":194,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":100,\"pop\":0,\"uvi\":3.09},{\"dt\":1618221600,\"sunrise\":1618197445,\"sunset\":1618247098,\"temp\":{\"day\":13.62,\"min\":4,\"max\":14.94,\"night\":7.62,\"eve\":12.21,\"morn\":4},\"feels_like\":{\"day\":12.08,\"night\":0.9,\"eve\":10.87,\"morn\":0.9},\"pressure\":1024,\"humidity\":40,\"dew_point\":0.58,\"wind_speed\":6.09,\"wind_deg\":152,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.11},{\"dt\":1618308000,\"sunrise\":1618283705,\"sunset\":1618333607,\"temp\":{\"day\":14.42,\"min\":4.45,\"max\":16.91,\"night\":11.72,\"eve\":16.64,\"morn\":4.45},\"feels_like\":{\"day\":13.17,\"night\":2.28,\"eve\":15.43,\"morn\":2.28},\"pressure\":1019,\"humidity\":48,\"dew_point\":3.67,\"wind_speed\":3.07,\"wind_deg\":153,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":8,\"pop\":0,\"uvi\":3.53},{\"dt\":1618394400,\"sunrise\":1618369965,\"sunset\":1618420117,\"temp\":{\"day\":10.12,\"min\":7.84,\"max\":10.7,\"night\":8.87,\"eve\":9.78,\"morn\":7.84},\"feels_like\":{\"day\":9.54,\"night\":6.26,\"eve\":8.02,\"morn\":6.26},\"pressure\":1012,\"humidity\":90,\"dew_point\":8.65,\"wind_speed\":3.6,\"wind_deg\":129,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.98,\"rain\":2.37,\"uvi\":2.7},{\"dt\":1618480800,\"sunrise\":1618456226,\"sunset\":1618506627,\"temp\":{\"day\":8.88,\"min\":6.86,\"max\":10.63,\"night\":8.88,\"eve\":10.63,\"morn\":6.86},\"feels_like\":{\"day\":7.04,\"night\":5.16,\"eve\":9.81,\"morn\":5.16},\"pressure\":1011,\"humidity\":86,\"dew_point\":6.85,\"wind_speed\":3.22,\"wind_deg\":98,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.91,\"rain\":4.23,\"uvi\":3},{\"dt\":1618567200,\"sunrise\":1618542488,\"sunset\":1618593137,\"temp\":{\"day\":5.06,\"min\":4.81,\"max\":8.16,\"night\":4.84,\"eve\":7.24,\"morn\":5.39},\"feels_like\":{\"day\":2.81,\"night\":1.18,\"eve\":6.67,\"morn\":1.18},\"pressure\":1010,\"humidity\":91,\"dew_point\":3.81,\"wind_speed\":2.69,\"wind_deg\":101,\"weather\":[{\"id\":501,\"main\":\"Rain\",\"description\":\"moderate rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":1,\"rain\":15.37,\"uvi\":3},{\"dt\":1618653600,\"sunrise\":1618628751,\"sunset\":1618679646,\"temp\":{\"day\":3.07,\"min\":1.88,\"max\":5.32,\"night\":1.88,\"eve\":2.04,\"morn\":4.62},\"feels_like\":{\"day\":-0.42,\"night\":1.75,\"eve\":-1.74,\"morn\":1.75},\"pressure\":1010,\"humidity\":97,\"dew_point\":2.74,\"wind_speed\":3.86,\"wind_deg\":287,\"weather\":[{\"id\":616,\"main\":\"Snow\",\"description\":\"rain and snow\",\"icon\":\"13d\"}],\"clouds\":100,\"pop\":1,\"rain\":6.67,\"snow\":8.83,\"uvi\":3}]}"; + assertThrows(JsonParseException.class, () -> new ObjectMapper().readValue(jsonString, OneCallCurrentForecastModel.class)); } @Test - public void mapToCurrent_withCurrentVariants() { - final String jsonString = "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"hourly\":[{\"dt\":1618048800,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":7.72,\"wind_deg\":200,\"wind_gust\":10.55,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618052400,\"temp\":11.6,\"feels_like\":9.96,\"pressure\":1018,\"humidity\":44,\"dew_point\":-0.2,\"uvi\":3.22,\"clouds\":32,\"visibility\":10000,\"wind_speed\":7.76,\"wind_deg\":202,\"wind_gust\":10.75,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618056000,\"temp\":12.26,\"feels_like\":10.72,\"pressure\":1018,\"humidity\":45,\"dew_point\":0.68,\"uvi\":2.67,\"clouds\":49,\"visibility\":10000,\"wind_speed\":7.66,\"wind_deg\":205,\"wind_gust\":10.76,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618059600,\"temp\":12.86,\"feels_like\":11.4,\"pressure\":1018,\"humidity\":46,\"dew_point\":1.53,\"uvi\":1.22,\"clouds\":19,\"visibility\":10000,\"wind_speed\":7.15,\"wind_deg\":210,\"wind_gust\":9.99,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618063200,\"temp\":13.04,\"feels_like\":11.68,\"pressure\":1018,\"humidity\":49,\"dew_point\":2.58,\"uvi\":0.7,\"clouds\":50,\"visibility\":10000,\"wind_speed\":5.95,\"wind_deg\":210,\"wind_gust\":9.4,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618066800,\"temp\":12.53,\"feels_like\":11.2,\"pressure\":1018,\"humidity\":52,\"dew_point\":3.07,\"uvi\":0.32,\"clouds\":48,\"visibility\":10000,\"wind_speed\":5.43,\"wind_deg\":209,\"wind_gust\":9.32,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618070400,\"temp\":11.02,\"feels_like\":9.72,\"pressure\":1018,\"humidity\":59,\"dew_point\":3.37,\"uvi\":0.12,\"clouds\":51,\"visibility\":10000,\"wind_speed\":4.22,\"wind_deg\":200,\"wind_gust\":8.94,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618074000,\"temp\":8.81,\"feels_like\":6.7,\"pressure\":1019,\"humidity\":67,\"dew_point\":3.23,\"uvi\":0,\"clouds\":55,\"visibility\":10000,\"wind_speed\":3.67,\"wind_deg\":184,\"wind_gust\":8.41,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618077600,\"temp\":7.94,\"feels_like\":5.47,\"pressure\":1020,\"humidity\":71,\"dew_point\":3.06,\"uvi\":0,\"clouds\":59,\"visibility\":10000,\"wind_speed\":4,\"wind_deg\":177,\"wind_gust\":10.47,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618081200,\"temp\":7.68,\"feels_like\":4.81,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.92,\"uvi\":0,\"clouds\":79,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":179,\"wind_gust\":12.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618084800,\"temp\":7.78,\"feels_like\":4.76,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.89,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":5.12,\"wind_deg\":185,\"wind_gust\":13.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618088400,\"temp\":7.45,\"feels_like\":4.33,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.77,\"uvi\":0,\"clouds\":86,\"visibility\":10000,\"wind_speed\":5.17,\"wind_deg\":190,\"wind_gust\":13.37,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618092000,\"temp\":6.97,\"feels_like\":3.85,\"pressure\":1021,\"humidity\":74,\"dew_point\":2.67,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":4.89,\"wind_deg\":192,\"wind_gust\":12.68,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618095600,\"temp\":6.46,\"feels_like\":3.4,\"pressure\":1021,\"humidity\":76,\"dew_point\":2.7,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":191,\"wind_gust\":11.89,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618099200,\"temp\":5.96,\"feels_like\":2.9,\"pressure\":1021,\"humidity\":79,\"dew_point\":2.65,\"uvi\":0,\"clouds\":91,\"visibility\":10000,\"wind_speed\":4.26,\"wind_deg\":188,\"wind_gust\":11.23,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618102800,\"temp\":5.31,\"feels_like\":2.22,\"pressure\":1022,\"humidity\":81,\"dew_point\":2.47,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.04,\"wind_deg\":186,\"wind_gust\":10.72,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618106400,\"temp\":5.2,\"feels_like\":2.18,\"pressure\":1022,\"humidity\":82,\"dew_point\":2.41,\"uvi\":0,\"clouds\":95,\"visibility\":10000,\"wind_speed\":3.87,\"wind_deg\":190,\"wind_gust\":10.92,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618110000,\"temp\":4.56,\"feels_like\":1.51,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.29,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":3.69,\"wind_deg\":186,\"wind_gust\":10.33,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618113600,\"temp\":4.51,\"feels_like\":1.64,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.33,\"uvi\":0,\"clouds\":84,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":191,\"wind_gust\":10.18,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618117200,\"temp\":6.05,\"feels_like\":3.41,\"pressure\":1024,\"humidity\":80,\"dew_point\":2.89,\"uvi\":0.15,\"clouds\":80,\"visibility\":10000,\"wind_speed\":3.55,\"wind_deg\":193,\"wind_gust\":10.09,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618120800,\"temp\":7.96,\"feels_like\":5.31,\"pressure\":1024,\"humidity\":72,\"dew_point\":3.29,\"uvi\":0.38,\"clouds\":80,\"visibility\":10000,\"wind_speed\":4.39,\"wind_deg\":197,\"wind_gust\":8.53,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618124400,\"temp\":9.61,\"feels_like\":7.3,\"pressure\":1024,\"humidity\":67,\"dew_point\":3.88,\"uvi\":1.01,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":197,\"wind_gust\":7.77,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618128000,\"temp\":11.14,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":62,\"dew_point\":4.27,\"uvi\":1.54,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":198,\"wind_gust\":7.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618131600,\"temp\":12.8,\"feels_like\":11.62,\"pressure\":1025,\"humidity\":57,\"dew_point\":4.57,\"uvi\":1.97,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.87,\"wind_deg\":196,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618135200,\"temp\":14.03,\"feels_like\":12.87,\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"uvi\":3.09,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.11,\"wind_deg\":194,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618138800,\"temp\":14.82,\"feels_like\":13.66,\"pressure\":1025,\"humidity\":50,\"dew_point\":4.62,\"uvi\":2.96,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.32,\"wind_deg\":191,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618142400,\"temp\":15.64,\"feels_like\":14.49,\"pressure\":1025,\"humidity\":47,\"dew_point\":4.48,\"uvi\":2.45,\"clouds\":94,\"visibility\":10000,\"wind_speed\":5.42,\"wind_deg\":192,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618146000,\"temp\":15.81,\"feels_like\":14.62,\"pressure\":1024,\"humidity\":45,\"dew_point\":4.15,\"uvi\":2.02,\"clouds\":24,\"visibility\":10000,\"wind_speed\":5.15,\"wind_deg\":193,\"wind_gust\":6.3,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618149600,\"temp\":15.71,\"feels_like\":14.51,\"pressure\":1025,\"humidity\":45,\"dew_point\":3.87,\"uvi\":1.17,\"clouds\":48,\"visibility\":10000,\"wind_speed\":4.79,\"wind_deg\":188,\"wind_gust\":6.01,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618153200,\"temp\":14.79,\"feels_like\":13.63,\"pressure\":1024,\"humidity\":50,\"dew_point\":4.71,\"uvi\":0.53,\"clouds\":63,\"visibility\":10000,\"wind_speed\":3.73,\"wind_deg\":177,\"wind_gust\":6.35,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618156800,\"temp\":12.85,\"feels_like\":11.73,\"pressure\":1024,\"humidity\":59,\"dew_point\":5.18,\"uvi\":0.17,\"clouds\":72,\"visibility\":10000,\"wind_speed\":3.05,\"wind_deg\":159,\"wind_gust\":6.38,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618160400,\"temp\":10.92,\"feels_like\":9.71,\"pressure\":1025,\"humidity\":63,\"dew_point\":4.26,\"uvi\":0,\"clouds\":78,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":152,\"wind_gust\":6.64,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618164000,\"temp\":9.65,\"feels_like\":7.72,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.66,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":3.68,\"wind_deg\":148,\"wind_gust\":9.04,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618167600,\"temp\":8.82,\"feels_like\":6.59,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.05,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.92,\"wind_deg\":147,\"wind_gust\":11.02,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618171200,\"temp\":8.07,\"feels_like\":5.87,\"pressure\":1026,\"humidity\":67,\"dew_point\":2.43,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.54,\"wind_deg\":154,\"wind_gust\":11.12,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618174800,\"temp\":7.24,\"feels_like\":4.99,\"pressure\":1027,\"humidity\":68,\"dew_point\":1.96,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.32,\"wind_deg\":154,\"wind_gust\":10.55,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618178400,\"temp\":6.58,\"feels_like\":4.31,\"pressure\":1027,\"humidity\":70,\"dew_point\":1.65,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.14,\"wind_deg\":154,\"wind_gust\":9.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618182000,\"temp\":6.03,\"feels_like\":3.57,\"pressure\":1027,\"humidity\":71,\"dew_point\":1.26,\"uvi\":0,\"clouds\":82,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":150,\"wind_gust\":8.44,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618185600,\"temp\":5.51,\"feels_like\":2.94,\"pressure\":1027,\"humidity\":72,\"dew_point\":0.95,\"uvi\":0,\"clouds\":71,\"visibility\":10000,\"wind_speed\":3.26,\"wind_deg\":150,\"wind_gust\":8.58,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618189200,\"temp\":5,\"feels_like\":2.29,\"pressure\":1027,\"humidity\":74,\"dew_point\":0.72,\"uvi\":0,\"clouds\":9,\"visibility\":10000,\"wind_speed\":3.3,\"wind_deg\":147,\"wind_gust\":8.63,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"pop\":0},{\"dt\":1618192800,\"temp\":4.47,\"feels_like\":1.69,\"pressure\":1027,\"humidity\":75,\"dew_point\":0.52,\"uvi\":0,\"clouds\":14,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":145,\"wind_gust\":8.14,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618196400,\"temp\":4.03,\"feels_like\":1.08,\"pressure\":1026,\"humidity\":76,\"dew_point\":0.22,\"uvi\":0,\"clouds\":12,\"visibility\":10000,\"wind_speed\":3.36,\"wind_deg\":138,\"wind_gust\":8.13,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618200000,\"temp\":4,\"feels_like\":0.9,\"pressure\":1026,\"humidity\":75,\"dew_point\":0.13,\"uvi\":0.08,\"clouds\":10,\"visibility\":10000,\"wind_speed\":3.57,\"wind_deg\":131,\"wind_gust\":9.24,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618203600,\"temp\":5.73,\"feels_like\":2.73,\"pressure\":1026,\"humidity\":68,\"dew_point\":0.52,\"uvi\":0.33,\"clouds\":8,\"visibility\":10000,\"wind_speed\":4.05,\"wind_deg\":138,\"wind_gust\":10.36,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618207200,\"temp\":7.87,\"feels_like\":4.9,\"pressure\":1025,\"humidity\":59,\"dew_point\":0.53,\"uvi\":0.84,\"clouds\":7,\"visibility\":10000,\"wind_speed\":5.05,\"wind_deg\":145,\"wind_gust\":10.48,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618210800,\"temp\":9.9,\"feels_like\":7.29,\"pressure\":1025,\"humidity\":53,\"dew_point\":0.8,\"uvi\":1.56,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.48,\"wind_deg\":147,\"wind_gust\":9.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618214400,\"temp\":11.5,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":47,\"dew_point\":0.86,\"uvi\":2.37,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.94,\"wind_deg\":152,\"wind_gust\":8.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618218000,\"temp\":12.64,\"feels_like\":11.08,\"pressure\":1024,\"humidity\":43,\"dew_point\":0.68,\"uvi\":3.04,\"clouds\":0,\"visibility\":10000,\"wind_speed\":6.25,\"wind_deg\":151,\"wind_gust\":8.5,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0}],\"daily\":[{\"dt\":1618048800,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":{\"day\":11.84,\"min\":1.69,\"max\":13.04,\"night\":7.78,\"eve\":11.02,\"morn\":1.69},\"feels_like\":{\"day\":10.12,\"night\":-2.86,\"eve\":9.72,\"morn\":-2.86},\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"wind_speed\":7.72,\"wind_deg\":200,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.36},{\"dt\":1618135200,\"sunrise\":1618111186,\"sunset\":1618160588,\"temp\":{\"day\":14.03,\"min\":4.51,\"max\":15.81,\"night\":8.07,\"eve\":12.85,\"morn\":4.51},\"feels_like\":{\"day\":12.87,\"night\":1.64,\"eve\":11.73,\"morn\":1.64},\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"wind_speed\":5.11,\"wind_deg\":194,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":100,\"pop\":0,\"uvi\":3.09},{\"dt\":1618221600,\"sunrise\":1618197445,\"sunset\":1618247098,\"temp\":{\"day\":13.62,\"min\":4,\"max\":14.94,\"night\":7.62,\"eve\":12.21,\"morn\":4},\"feels_like\":{\"day\":12.08,\"night\":0.9,\"eve\":10.87,\"morn\":0.9},\"pressure\":1024,\"humidity\":40,\"dew_point\":0.58,\"wind_speed\":6.09,\"wind_deg\":152,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.11},{\"dt\":1618308000,\"sunrise\":1618283705,\"sunset\":1618333607,\"temp\":{\"day\":14.42,\"min\":4.45,\"max\":16.91,\"night\":11.72,\"eve\":16.64,\"morn\":4.45},\"feels_like\":{\"day\":13.17,\"night\":2.28,\"eve\":15.43,\"morn\":2.28},\"pressure\":1019,\"humidity\":48,\"dew_point\":3.67,\"wind_speed\":3.07,\"wind_deg\":153,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":8,\"pop\":0,\"uvi\":3.53},{\"dt\":1618394400,\"sunrise\":1618369965,\"sunset\":1618420117,\"temp\":{\"day\":10.12,\"min\":7.84,\"max\":10.7,\"night\":8.87,\"eve\":9.78,\"morn\":7.84},\"feels_like\":{\"day\":9.54,\"night\":6.26,\"eve\":8.02,\"morn\":6.26},\"pressure\":1012,\"humidity\":90,\"dew_point\":8.65,\"wind_speed\":3.6,\"wind_deg\":129,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.98,\"rain\":2.37,\"uvi\":2.7},{\"dt\":1618480800,\"sunrise\":1618456226,\"sunset\":1618506627,\"temp\":{\"day\":8.88,\"min\":6.86,\"max\":10.63,\"night\":8.88,\"eve\":10.63,\"morn\":6.86},\"feels_like\":{\"day\":7.04,\"night\":5.16,\"eve\":9.81,\"morn\":5.16},\"pressure\":1011,\"humidity\":86,\"dew_point\":6.85,\"wind_speed\":3.22,\"wind_deg\":98,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.91,\"rain\":4.23,\"uvi\":3},{\"dt\":1618567200,\"sunrise\":1618542488,\"sunset\":1618593137,\"temp\":{\"day\":5.06,\"min\":4.81,\"max\":8.16,\"night\":4.84,\"eve\":7.24,\"morn\":5.39},\"feels_like\":{\"day\":2.81,\"night\":1.18,\"eve\":6.67,\"morn\":1.18},\"pressure\":1010,\"humidity\":91,\"dew_point\":3.81,\"wind_speed\":2.69,\"wind_deg\":101,\"weather\":[{\"id\":501,\"main\":\"Rain\",\"description\":\"moderate rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":1,\"rain\":15.37,\"uvi\":3},{\"dt\":1618653600,\"sunrise\":1618628751,\"sunset\":1618679646,\"temp\":{\"day\":3.07,\"min\":1.88,\"max\":5.32,\"night\":1.88,\"eve\":2.04,\"morn\":4.62},\"feels_like\":{\"day\":-0.42,\"night\":1.75,\"eve\":-1.74,\"morn\":1.75},\"pressure\":1010,\"humidity\":97,\"dew_point\":2.74,\"wind_speed\":3.86,\"wind_deg\":287,\"weather\":[{\"id\":616,\"main\":\"Snow\",\"description\":\"rain and snow\",\"icon\":\"13d\"}],\"clouds\":100,\"pop\":1,\"rain\":6.67,\"snow\":8.83,\"uvi\":3}]}"; - final CurrentWeatherData currentWeatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToCurrent(jsonString); + public void mapToCurrent_withCurrentVariants() throws JsonProcessingException { + final String jsonString = + "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"hourly\":[{\"dt\":1618048800,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":7.72,\"wind_deg\":200,\"wind_gust\":10.55,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618052400,\"temp\":11.6,\"feels_like\":9.96,\"pressure\":1018,\"humidity\":44,\"dew_point\":-0.2,\"uvi\":3.22,\"clouds\":32,\"visibility\":10000,\"wind_speed\":7.76,\"wind_deg\":202,\"wind_gust\":10.75,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618056000,\"temp\":12.26,\"feels_like\":10.72,\"pressure\":1018,\"humidity\":45,\"dew_point\":0.68,\"uvi\":2.67,\"clouds\":49,\"visibility\":10000,\"wind_speed\":7.66,\"wind_deg\":205,\"wind_gust\":10.76,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618059600,\"temp\":12.86,\"feels_like\":11.4,\"pressure\":1018,\"humidity\":46,\"dew_point\":1.53,\"uvi\":1.22,\"clouds\":19,\"visibility\":10000,\"wind_speed\":7.15,\"wind_deg\":210,\"wind_gust\":9.99,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618063200,\"temp\":13.04,\"feels_like\":11.68,\"pressure\":1018,\"humidity\":49,\"dew_point\":2.58,\"uvi\":0.7,\"clouds\":50,\"visibility\":10000,\"wind_speed\":5.95,\"wind_deg\":210,\"wind_gust\":9.4,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618066800,\"temp\":12.53,\"feels_like\":11.2,\"pressure\":1018,\"humidity\":52,\"dew_point\":3.07,\"uvi\":0.32,\"clouds\":48,\"visibility\":10000,\"wind_speed\":5.43,\"wind_deg\":209,\"wind_gust\":9.32,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618070400,\"temp\":11.02,\"feels_like\":9.72,\"pressure\":1018,\"humidity\":59,\"dew_point\":3.37,\"uvi\":0.12,\"clouds\":51,\"visibility\":10000,\"wind_speed\":4.22,\"wind_deg\":200,\"wind_gust\":8.94,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618074000,\"temp\":8.81,\"feels_like\":6.7,\"pressure\":1019,\"humidity\":67,\"dew_point\":3.23,\"uvi\":0,\"clouds\":55,\"visibility\":10000,\"wind_speed\":3.67,\"wind_deg\":184,\"wind_gust\":8.41,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618077600,\"temp\":7.94,\"feels_like\":5.47,\"pressure\":1020,\"humidity\":71,\"dew_point\":3.06,\"uvi\":0,\"clouds\":59,\"visibility\":10000,\"wind_speed\":4,\"wind_deg\":177,\"wind_gust\":10.47,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618081200,\"temp\":7.68,\"feels_like\":4.81,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.92,\"uvi\":0,\"clouds\":79,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":179,\"wind_gust\":12.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618084800,\"temp\":7.78,\"feels_like\":4.76,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.89,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":5.12,\"wind_deg\":185,\"wind_gust\":13.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618088400,\"temp\":7.45,\"feels_like\":4.33,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.77,\"uvi\":0,\"clouds\":86,\"visibility\":10000,\"wind_speed\":5.17,\"wind_deg\":190,\"wind_gust\":13.37,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618092000,\"temp\":6.97,\"feels_like\":3.85,\"pressure\":1021,\"humidity\":74,\"dew_point\":2.67,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":4.89,\"wind_deg\":192,\"wind_gust\":12.68,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618095600,\"temp\":6.46,\"feels_like\":3.4,\"pressure\":1021,\"humidity\":76,\"dew_point\":2.7,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":191,\"wind_gust\":11.89,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618099200,\"temp\":5.96,\"feels_like\":2.9,\"pressure\":1021,\"humidity\":79,\"dew_point\":2.65,\"uvi\":0,\"clouds\":91,\"visibility\":10000,\"wind_speed\":4.26,\"wind_deg\":188,\"wind_gust\":11.23,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618102800,\"temp\":5.31,\"feels_like\":2.22,\"pressure\":1022,\"humidity\":81,\"dew_point\":2.47,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.04,\"wind_deg\":186,\"wind_gust\":10.72,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618106400,\"temp\":5.2,\"feels_like\":2.18,\"pressure\":1022,\"humidity\":82,\"dew_point\":2.41,\"uvi\":0,\"clouds\":95,\"visibility\":10000,\"wind_speed\":3.87,\"wind_deg\":190,\"wind_gust\":10.92,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618110000,\"temp\":4.56,\"feels_like\":1.51,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.29,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":3.69,\"wind_deg\":186,\"wind_gust\":10.33,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618113600,\"temp\":4.51,\"feels_like\":1.64,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.33,\"uvi\":0,\"clouds\":84,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":191,\"wind_gust\":10.18,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618117200,\"temp\":6.05,\"feels_like\":3.41,\"pressure\":1024,\"humidity\":80,\"dew_point\":2.89,\"uvi\":0.15,\"clouds\":80,\"visibility\":10000,\"wind_speed\":3.55,\"wind_deg\":193,\"wind_gust\":10.09,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618120800,\"temp\":7.96,\"feels_like\":5.31,\"pressure\":1024,\"humidity\":72,\"dew_point\":3.29,\"uvi\":0.38,\"clouds\":80,\"visibility\":10000,\"wind_speed\":4.39,\"wind_deg\":197,\"wind_gust\":8.53,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618124400,\"temp\":9.61,\"feels_like\":7.3,\"pressure\":1024,\"humidity\":67,\"dew_point\":3.88,\"uvi\":1.01,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":197,\"wind_gust\":7.77,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618128000,\"temp\":11.14,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":62,\"dew_point\":4.27,\"uvi\":1.54,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":198,\"wind_gust\":7.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618131600,\"temp\":12.8,\"feels_like\":11.62,\"pressure\":1025,\"humidity\":57,\"dew_point\":4.57,\"uvi\":1.97,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.87,\"wind_deg\":196,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618135200,\"temp\":14.03,\"feels_like\":12.87,\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"uvi\":3.09,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.11,\"wind_deg\":194,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618138800,\"temp\":14.82,\"feels_like\":13.66,\"pressure\":1025,\"humidity\":50,\"dew_point\":4.62,\"uvi\":2.96,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.32,\"wind_deg\":191,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618142400,\"temp\":15.64,\"feels_like\":14.49,\"pressure\":1025,\"humidity\":47,\"dew_point\":4.48,\"uvi\":2.45,\"clouds\":94,\"visibility\":10000,\"wind_speed\":5.42,\"wind_deg\":192,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618146000,\"temp\":15.81,\"feels_like\":14.62,\"pressure\":1024,\"humidity\":45,\"dew_point\":4.15,\"uvi\":2.02,\"clouds\":24,\"visibility\":10000,\"wind_speed\":5.15,\"wind_deg\":193,\"wind_gust\":6.3,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618149600,\"temp\":15.71,\"feels_like\":14.51,\"pressure\":1025,\"humidity\":45,\"dew_point\":3.87,\"uvi\":1.17,\"clouds\":48,\"visibility\":10000,\"wind_speed\":4.79,\"wind_deg\":188,\"wind_gust\":6.01,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618153200,\"temp\":14.79,\"feels_like\":13.63,\"pressure\":1024,\"humidity\":50,\"dew_point\":4.71,\"uvi\":0.53,\"clouds\":63,\"visibility\":10000,\"wind_speed\":3.73,\"wind_deg\":177,\"wind_gust\":6.35,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618156800,\"temp\":12.85,\"feels_like\":11.73,\"pressure\":1024,\"humidity\":59,\"dew_point\":5.18,\"uvi\":0.17,\"clouds\":72,\"visibility\":10000,\"wind_speed\":3.05,\"wind_deg\":159,\"wind_gust\":6.38,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618160400,\"temp\":10.92,\"feels_like\":9.71,\"pressure\":1025,\"humidity\":63,\"dew_point\":4.26,\"uvi\":0,\"clouds\":78,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":152,\"wind_gust\":6.64,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618164000,\"temp\":9.65,\"feels_like\":7.72,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.66,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":3.68,\"wind_deg\":148,\"wind_gust\":9.04,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618167600,\"temp\":8.82,\"feels_like\":6.59,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.05,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.92,\"wind_deg\":147,\"wind_gust\":11.02,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618171200,\"temp\":8.07,\"feels_like\":5.87,\"pressure\":1026,\"humidity\":67,\"dew_point\":2.43,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.54,\"wind_deg\":154,\"wind_gust\":11.12,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618174800,\"temp\":7.24,\"feels_like\":4.99,\"pressure\":1027,\"humidity\":68,\"dew_point\":1.96,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.32,\"wind_deg\":154,\"wind_gust\":10.55,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618178400,\"temp\":6.58,\"feels_like\":4.31,\"pressure\":1027,\"humidity\":70,\"dew_point\":1.65,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.14,\"wind_deg\":154,\"wind_gust\":9.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618182000,\"temp\":6.03,\"feels_like\":3.57,\"pressure\":1027,\"humidity\":71,\"dew_point\":1.26,\"uvi\":0,\"clouds\":82,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":150,\"wind_gust\":8.44,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618185600,\"temp\":5.51,\"feels_like\":2.94,\"pressure\":1027,\"humidity\":72,\"dew_point\":0.95,\"uvi\":0,\"clouds\":71,\"visibility\":10000,\"wind_speed\":3.26,\"wind_deg\":150,\"wind_gust\":8.58,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618189200,\"temp\":5,\"feels_like\":2.29,\"pressure\":1027,\"humidity\":74,\"dew_point\":0.72,\"uvi\":0,\"clouds\":9,\"visibility\":10000,\"wind_speed\":3.3,\"wind_deg\":147,\"wind_gust\":8.63,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"pop\":0},{\"dt\":1618192800,\"temp\":4.47,\"feels_like\":1.69,\"pressure\":1027,\"humidity\":75,\"dew_point\":0.52,\"uvi\":0,\"clouds\":14,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":145,\"wind_gust\":8.14,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618196400,\"temp\":4.03,\"feels_like\":1.08,\"pressure\":1026,\"humidity\":76,\"dew_point\":0.22,\"uvi\":0,\"clouds\":12,\"visibility\":10000,\"wind_speed\":3.36,\"wind_deg\":138,\"wind_gust\":8.13,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618200000,\"temp\":4,\"feels_like\":0.9,\"pressure\":1026,\"humidity\":75,\"dew_point\":0.13,\"uvi\":0.08,\"clouds\":10,\"visibility\":10000,\"wind_speed\":3.57,\"wind_deg\":131,\"wind_gust\":9.24,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618203600,\"temp\":5.73,\"feels_like\":2.73,\"pressure\":1026,\"humidity\":68,\"dew_point\":0.52,\"uvi\":0.33,\"clouds\":8,\"visibility\":10000,\"wind_speed\":4.05,\"wind_deg\":138,\"wind_gust\":10.36,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618207200,\"temp\":7.87,\"feels_like\":4.9,\"pressure\":1025,\"humidity\":59,\"dew_point\":0.53,\"uvi\":0.84,\"clouds\":7,\"visibility\":10000,\"wind_speed\":5.05,\"wind_deg\":145,\"wind_gust\":10.48,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618210800,\"temp\":9.9,\"feels_like\":7.29,\"pressure\":1025,\"humidity\":53,\"dew_point\":0.8,\"uvi\":1.56,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.48,\"wind_deg\":147,\"wind_gust\":9.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618214400,\"temp\":11.5,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":47,\"dew_point\":0.86,\"uvi\":2.37,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.94,\"wind_deg\":152,\"wind_gust\":8.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618218000,\"temp\":12.64,\"feels_like\":11.08,\"pressure\":1024,\"humidity\":43,\"dew_point\":0.68,\"uvi\":3.04,\"clouds\":0,\"visibility\":10000,\"wind_speed\":6.25,\"wind_deg\":151,\"wind_gust\":8.5,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0}],\"daily\":[{\"dt\":1618048800,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":{\"day\":11.84,\"min\":1.69,\"max\":13.04,\"night\":7.78,\"eve\":11.02,\"morn\":1.69},\"feels_like\":{\"day\":10.12,\"night\":-2.86,\"eve\":9.72,\"morn\":-2.86},\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"wind_speed\":7.72,\"wind_deg\":200,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.36},{\"dt\":1618135200,\"sunrise\":1618111186,\"sunset\":1618160588,\"temp\":{\"day\":14.03,\"min\":4.51,\"max\":15.81,\"night\":8.07,\"eve\":12.85,\"morn\":4.51},\"feels_like\":{\"day\":12.87,\"night\":1.64,\"eve\":11.73,\"morn\":1.64},\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"wind_speed\":5.11,\"wind_deg\":194,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":100,\"pop\":0,\"uvi\":3.09},{\"dt\":1618221600,\"sunrise\":1618197445,\"sunset\":1618247098,\"temp\":{\"day\":13.62,\"min\":4,\"max\":14.94,\"night\":7.62,\"eve\":12.21,\"morn\":4},\"feels_like\":{\"day\":12.08,\"night\":0.9,\"eve\":10.87,\"morn\":0.9},\"pressure\":1024,\"humidity\":40,\"dew_point\":0.58,\"wind_speed\":6.09,\"wind_deg\":152,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.11},{\"dt\":1618308000,\"sunrise\":1618283705,\"sunset\":1618333607,\"temp\":{\"day\":14.42,\"min\":4.45,\"max\":16.91,\"night\":11.72,\"eve\":16.64,\"morn\":4.45},\"feels_like\":{\"day\":13.17,\"night\":2.28,\"eve\":15.43,\"morn\":2.28},\"pressure\":1019,\"humidity\":48,\"dew_point\":3.67,\"wind_speed\":3.07,\"wind_deg\":153,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":8,\"pop\":0,\"uvi\":3.53},{\"dt\":1618394400,\"sunrise\":1618369965,\"sunset\":1618420117,\"temp\":{\"day\":10.12,\"min\":7.84,\"max\":10.7,\"night\":8.87,\"eve\":9.78,\"morn\":7.84},\"feels_like\":{\"day\":9.54,\"night\":6.26,\"eve\":8.02,\"morn\":6.26},\"pressure\":1012,\"humidity\":90,\"dew_point\":8.65,\"wind_speed\":3.6,\"wind_deg\":129,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.98,\"rain\":2.37,\"uvi\":2.7},{\"dt\":1618480800,\"sunrise\":1618456226,\"sunset\":1618506627,\"temp\":{\"day\":8.88,\"min\":6.86,\"max\":10.63,\"night\":8.88,\"eve\":10.63,\"morn\":6.86},\"feels_like\":{\"day\":7.04,\"night\":5.16,\"eve\":9.81,\"morn\":5.16},\"pressure\":1011,\"humidity\":86,\"dew_point\":6.85,\"wind_speed\":3.22,\"wind_deg\":98,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.91,\"rain\":4.23,\"uvi\":3},{\"dt\":1618567200,\"sunrise\":1618542488,\"sunset\":1618593137,\"temp\":{\"day\":5.06,\"min\":4.81,\"max\":8.16,\"night\":4.84,\"eve\":7.24,\"morn\":5.39},\"feels_like\":{\"day\":2.81,\"night\":1.18,\"eve\":6.67,\"morn\":1.18},\"pressure\":1010,\"humidity\":91,\"dew_point\":3.81,\"wind_speed\":2.69,\"wind_deg\":101,\"weather\":[{\"id\":501,\"main\":\"Rain\",\"description\":\"moderate rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":1,\"rain\":15.37,\"uvi\":3},{\"dt\":1618653600,\"sunrise\":1618628751,\"sunset\":1618679646,\"temp\":{\"day\":3.07,\"min\":1.88,\"max\":5.32,\"night\":1.88,\"eve\":2.04,\"morn\":4.62},\"feels_like\":{\"day\":-0.42,\"night\":1.75,\"eve\":-1.74,\"morn\":1.75},\"pressure\":1010,\"humidity\":97,\"dew_point\":2.74,\"wind_speed\":3.86,\"wind_deg\":287,\"weather\":[{\"id\":616,\"main\":\"Snow\",\"description\":\"rain and snow\",\"icon\":\"13d\"}],\"clouds\":100,\"pop\":1,\"rain\":6.67,\"snow\":8.83,\"uvi\":3}]}"; + final OneCallCurrentForecastModel currentWeatherData = new ObjectMapper().readValue(jsonString, OneCallCurrentForecastModel.class); assertNotNull(currentWeatherData); assertNotNull(currentWeatherData.getCurrent()); - assertNull(currentWeatherData.getCurrent().getVisibilityInMetres()); + assertNull(currentWeatherData.getCurrent().getVisibility()); } @Test - public void mapToCurrent_withoutHourlyListNode() { - final String jsonString = "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"snow\":{},\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"daily\":[{\"dt\":1618048800,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":{\"day\":11.84,\"min\":1.69,\"max\":13.04,\"night\":7.78,\"eve\":11.02,\"morn\":1.69},\"feels_like\":{\"day\":10.12,\"night\":-2.86,\"eve\":9.72,\"morn\":-2.86},\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"wind_speed\":7.72,\"wind_deg\":200,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.36},{\"dt\":1618135200,\"sunrise\":1618111186,\"sunset\":1618160588,\"temp\":{\"day\":14.03,\"min\":4.51,\"max\":15.81,\"night\":8.07,\"eve\":12.85,\"morn\":4.51},\"feels_like\":{\"day\":12.87,\"night\":1.64,\"eve\":11.73,\"morn\":1.64},\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"wind_speed\":5.11,\"wind_deg\":194,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":100,\"pop\":0,\"uvi\":3.09},{\"dt\":1618221600,\"sunrise\":1618197445,\"sunset\":1618247098,\"temp\":{\"day\":13.62,\"min\":4,\"max\":14.94,\"night\":7.62,\"eve\":12.21,\"morn\":4},\"feels_like\":{\"day\":12.08,\"night\":0.9,\"eve\":10.87,\"morn\":0.9},\"pressure\":1024,\"humidity\":40,\"dew_point\":0.58,\"wind_speed\":6.09,\"wind_deg\":152,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.11},{\"dt\":1618308000,\"sunrise\":1618283705,\"sunset\":1618333607,\"temp\":{\"day\":14.42,\"min\":4.45,\"max\":16.91,\"night\":11.72,\"eve\":16.64,\"morn\":4.45},\"feels_like\":{\"day\":13.17,\"night\":2.28,\"eve\":15.43,\"morn\":2.28},\"pressure\":1019,\"humidity\":48,\"dew_point\":3.67,\"wind_speed\":3.07,\"wind_deg\":153,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":8,\"pop\":0,\"uvi\":3.53},{\"dt\":1618394400,\"sunrise\":1618369965,\"sunset\":1618420117,\"temp\":{\"day\":10.12,\"min\":7.84,\"max\":10.7,\"night\":8.87,\"eve\":9.78,\"morn\":7.84},\"feels_like\":{\"day\":9.54,\"night\":6.26,\"eve\":8.02,\"morn\":6.26},\"pressure\":1012,\"humidity\":90,\"dew_point\":8.65,\"wind_speed\":3.6,\"wind_deg\":129,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.98,\"rain\":2.37,\"uvi\":2.7},{\"dt\":1618480800,\"sunrise\":1618456226,\"sunset\":1618506627,\"temp\":{\"day\":8.88,\"min\":6.86,\"max\":10.63,\"night\":8.88,\"eve\":10.63,\"morn\":6.86},\"feels_like\":{\"day\":7.04,\"night\":5.16,\"eve\":9.81,\"morn\":5.16},\"pressure\":1011,\"humidity\":86,\"dew_point\":6.85,\"wind_speed\":3.22,\"wind_deg\":98,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.91,\"rain\":4.23,\"uvi\":3},{\"dt\":1618567200,\"sunrise\":1618542488,\"sunset\":1618593137,\"temp\":{\"day\":5.06,\"min\":4.81,\"max\":8.16,\"night\":4.84,\"eve\":7.24,\"morn\":5.39},\"feels_like\":{\"day\":2.81,\"night\":1.18,\"eve\":6.67,\"morn\":1.18},\"pressure\":1010,\"humidity\":91,\"dew_point\":3.81,\"wind_speed\":2.69,\"wind_deg\":101,\"weather\":[{\"id\":501,\"main\":\"Rain\",\"description\":\"moderate rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":1,\"rain\":15.37,\"uvi\":3},{\"dt\":1618653600,\"sunrise\":1618628751,\"sunset\":1618679646,\"temp\":{\"day\":3.07,\"min\":1.88,\"max\":5.32,\"night\":1.88,\"eve\":2.04,\"morn\":4.62},\"feels_like\":{\"day\":-0.42,\"night\":1.75,\"eve\":-1.74,\"morn\":1.75},\"pressure\":1010,\"humidity\":97,\"dew_point\":2.74,\"wind_speed\":3.86,\"wind_deg\":287,\"weather\":[{\"id\":616,\"main\":\"Snow\",\"description\":\"rain and snow\",\"icon\":\"13d\"}],\"clouds\":100,\"pop\":1,\"rain\":6.67,\"snow\":8.83,\"uvi\":3}]}"; - final CurrentWeatherData currentWeatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToCurrent(jsonString); + public void mapToCurrent_withoutHourlyListNode() throws JsonProcessingException { + final String jsonString = + "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"snow\":{},\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"daily\":[{\"dt\":1618048800,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":{\"day\":11.84,\"min\":1.69,\"max\":13.04,\"night\":7.78,\"eve\":11.02,\"morn\":1.69},\"feels_like\":{\"day\":10.12,\"night\":-2.86,\"eve\":9.72,\"morn\":-2.86},\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"wind_speed\":7.72,\"wind_deg\":200,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.36},{\"dt\":1618135200,\"sunrise\":1618111186,\"sunset\":1618160588,\"temp\":{\"day\":14.03,\"min\":4.51,\"max\":15.81,\"night\":8.07,\"eve\":12.85,\"morn\":4.51},\"feels_like\":{\"day\":12.87,\"night\":1.64,\"eve\":11.73,\"morn\":1.64},\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"wind_speed\":5.11,\"wind_deg\":194,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":100,\"pop\":0,\"uvi\":3.09},{\"dt\":1618221600,\"sunrise\":1618197445,\"sunset\":1618247098,\"temp\":{\"day\":13.62,\"min\":4,\"max\":14.94,\"night\":7.62,\"eve\":12.21,\"morn\":4},\"feels_like\":{\"day\":12.08,\"night\":0.9,\"eve\":10.87,\"morn\":0.9},\"pressure\":1024,\"humidity\":40,\"dew_point\":0.58,\"wind_speed\":6.09,\"wind_deg\":152,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.11},{\"dt\":1618308000,\"sunrise\":1618283705,\"sunset\":1618333607,\"temp\":{\"day\":14.42,\"min\":4.45,\"max\":16.91,\"night\":11.72,\"eve\":16.64,\"morn\":4.45},\"feels_like\":{\"day\":13.17,\"night\":2.28,\"eve\":15.43,\"morn\":2.28},\"pressure\":1019,\"humidity\":48,\"dew_point\":3.67,\"wind_speed\":3.07,\"wind_deg\":153,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":8,\"pop\":0,\"uvi\":3.53},{\"dt\":1618394400,\"sunrise\":1618369965,\"sunset\":1618420117,\"temp\":{\"day\":10.12,\"min\":7.84,\"max\":10.7,\"night\":8.87,\"eve\":9.78,\"morn\":7.84},\"feels_like\":{\"day\":9.54,\"night\":6.26,\"eve\":8.02,\"morn\":6.26},\"pressure\":1012,\"humidity\":90,\"dew_point\":8.65,\"wind_speed\":3.6,\"wind_deg\":129,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.98,\"rain\":2.37,\"uvi\":2.7},{\"dt\":1618480800,\"sunrise\":1618456226,\"sunset\":1618506627,\"temp\":{\"day\":8.88,\"min\":6.86,\"max\":10.63,\"night\":8.88,\"eve\":10.63,\"morn\":6.86},\"feels_like\":{\"day\":7.04,\"night\":5.16,\"eve\":9.81,\"morn\":5.16},\"pressure\":1011,\"humidity\":86,\"dew_point\":6.85,\"wind_speed\":3.22,\"wind_deg\":98,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.91,\"rain\":4.23,\"uvi\":3},{\"dt\":1618567200,\"sunrise\":1618542488,\"sunset\":1618593137,\"temp\":{\"day\":5.06,\"min\":4.81,\"max\":8.16,\"night\":4.84,\"eve\":7.24,\"morn\":5.39},\"feels_like\":{\"day\":2.81,\"night\":1.18,\"eve\":6.67,\"morn\":1.18},\"pressure\":1010,\"humidity\":91,\"dew_point\":3.81,\"wind_speed\":2.69,\"wind_deg\":101,\"weather\":[{\"id\":501,\"main\":\"Rain\",\"description\":\"moderate rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":1,\"rain\":15.37,\"uvi\":3},{\"dt\":1618653600,\"sunrise\":1618628751,\"sunset\":1618679646,\"temp\":{\"day\":3.07,\"min\":1.88,\"max\":5.32,\"night\":1.88,\"eve\":2.04,\"morn\":4.62},\"feels_like\":{\"day\":-0.42,\"night\":1.75,\"eve\":-1.74,\"morn\":1.75},\"pressure\":1010,\"humidity\":97,\"dew_point\":2.74,\"wind_speed\":3.86,\"wind_deg\":287,\"weather\":[{\"id\":616,\"main\":\"Snow\",\"description\":\"rain and snow\",\"icon\":\"13d\"}],\"clouds\":100,\"pop\":1,\"rain\":6.67,\"snow\":8.83,\"uvi\":3}]}"; + final OneCallCurrentForecastModel currentWeatherData = new ObjectMapper().readValue(jsonString, OneCallCurrentForecastModel.class); assertNotNull(currentWeatherData); assertNull(currentWeatherData.getHourlyList()); } @Test - public void mapToCurrent_withHourlyVariations() { - final String jsonString = "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"rain\":{},\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"hourly\":[{\"dt\":1618048800,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"clouds\":0,\"wind_speed\":7.72,\"wind_deg\":200,\"wind_gust\":10.55,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},{\"dt\":1618052400,\"temp\":11.6,\"feels_like\":9.96,\"pressure\":1018,\"humidity\":44,\"dew_point\":-0.2,\"uvi\":3.22,\"clouds\":32,\"visibility\":10000,\"wind_speed\":7.76,\"wind_deg\":202,\"wind_gust\":10.75,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618056000,\"temp\":12.26,\"feels_like\":10.72,\"pressure\":1018,\"humidity\":45,\"dew_point\":0.68,\"uvi\":2.67,\"clouds\":49,\"visibility\":10000,\"wind_speed\":7.66,\"wind_deg\":205,\"wind_gust\":10.76,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618059600,\"temp\":12.86,\"feels_like\":11.4,\"pressure\":1018,\"humidity\":46,\"dew_point\":1.53,\"uvi\":1.22,\"clouds\":19,\"visibility\":10000,\"wind_speed\":7.15,\"wind_deg\":210,\"wind_gust\":9.99,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618063200,\"temp\":13.04,\"feels_like\":11.68,\"pressure\":1018,\"humidity\":49,\"dew_point\":2.58,\"uvi\":0.7,\"clouds\":50,\"visibility\":10000,\"wind_speed\":5.95,\"wind_deg\":210,\"wind_gust\":9.4,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618066800,\"temp\":12.53,\"feels_like\":11.2,\"pressure\":1018,\"humidity\":52,\"dew_point\":3.07,\"uvi\":0.32,\"clouds\":48,\"visibility\":10000,\"wind_speed\":5.43,\"wind_deg\":209,\"wind_gust\":9.32,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618070400,\"temp\":11.02,\"feels_like\":9.72,\"pressure\":1018,\"humidity\":59,\"dew_point\":3.37,\"uvi\":0.12,\"clouds\":51,\"visibility\":10000,\"wind_speed\":4.22,\"wind_deg\":200,\"wind_gust\":8.94,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618074000,\"temp\":8.81,\"feels_like\":6.7,\"pressure\":1019,\"humidity\":67,\"dew_point\":3.23,\"uvi\":0,\"clouds\":55,\"visibility\":10000,\"wind_speed\":3.67,\"wind_deg\":184,\"wind_gust\":8.41,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618077600,\"temp\":7.94,\"feels_like\":5.47,\"pressure\":1020,\"humidity\":71,\"dew_point\":3.06,\"uvi\":0,\"clouds\":59,\"visibility\":10000,\"wind_speed\":4,\"wind_deg\":177,\"wind_gust\":10.47,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618081200,\"temp\":7.68,\"feels_like\":4.81,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.92,\"uvi\":0,\"clouds\":79,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":179,\"wind_gust\":12.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618084800,\"temp\":7.78,\"feels_like\":4.76,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.89,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":5.12,\"wind_deg\":185,\"wind_gust\":13.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618088400,\"temp\":7.45,\"feels_like\":4.33,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.77,\"uvi\":0,\"clouds\":86,\"visibility\":10000,\"wind_speed\":5.17,\"wind_deg\":190,\"wind_gust\":13.37,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618092000,\"temp\":6.97,\"feels_like\":3.85,\"pressure\":1021,\"humidity\":74,\"dew_point\":2.67,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":4.89,\"wind_deg\":192,\"wind_gust\":12.68,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618095600,\"temp\":6.46,\"feels_like\":3.4,\"pressure\":1021,\"humidity\":76,\"dew_point\":2.7,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":191,\"wind_gust\":11.89,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618099200,\"temp\":5.96,\"feels_like\":2.9,\"pressure\":1021,\"humidity\":79,\"dew_point\":2.65,\"uvi\":0,\"clouds\":91,\"visibility\":10000,\"wind_speed\":4.26,\"wind_deg\":188,\"wind_gust\":11.23,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618102800,\"temp\":5.31,\"feels_like\":2.22,\"pressure\":1022,\"humidity\":81,\"dew_point\":2.47,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.04,\"wind_deg\":186,\"wind_gust\":10.72,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618106400,\"temp\":5.2,\"feels_like\":2.18,\"pressure\":1022,\"humidity\":82,\"dew_point\":2.41,\"uvi\":0,\"clouds\":95,\"visibility\":10000,\"wind_speed\":3.87,\"wind_deg\":190,\"wind_gust\":10.92,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618110000,\"temp\":4.56,\"feels_like\":1.51,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.29,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":3.69,\"wind_deg\":186,\"wind_gust\":10.33,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618113600,\"temp\":4.51,\"feels_like\":1.64,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.33,\"uvi\":0,\"clouds\":84,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":191,\"wind_gust\":10.18,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618117200,\"temp\":6.05,\"feels_like\":3.41,\"pressure\":1024,\"humidity\":80,\"dew_point\":2.89,\"uvi\":0.15,\"clouds\":80,\"visibility\":10000,\"wind_speed\":3.55,\"wind_deg\":193,\"wind_gust\":10.09,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618120800,\"temp\":7.96,\"feels_like\":5.31,\"pressure\":1024,\"humidity\":72,\"dew_point\":3.29,\"uvi\":0.38,\"clouds\":80,\"visibility\":10000,\"wind_speed\":4.39,\"wind_deg\":197,\"wind_gust\":8.53,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618124400,\"temp\":9.61,\"feels_like\":7.3,\"pressure\":1024,\"humidity\":67,\"dew_point\":3.88,\"uvi\":1.01,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":197,\"wind_gust\":7.77,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618128000,\"temp\":11.14,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":62,\"dew_point\":4.27,\"uvi\":1.54,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":198,\"wind_gust\":7.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618131600,\"temp\":12.8,\"feels_like\":11.62,\"pressure\":1025,\"humidity\":57,\"dew_point\":4.57,\"uvi\":1.97,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.87,\"wind_deg\":196,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618135200,\"temp\":14.03,\"feels_like\":12.87,\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"uvi\":3.09,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.11,\"wind_deg\":194,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618138800,\"temp\":14.82,\"feels_like\":13.66,\"pressure\":1025,\"humidity\":50,\"dew_point\":4.62,\"uvi\":2.96,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.32,\"wind_deg\":191,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618142400,\"temp\":15.64,\"feels_like\":14.49,\"pressure\":1025,\"humidity\":47,\"dew_point\":4.48,\"uvi\":2.45,\"clouds\":94,\"visibility\":10000,\"wind_speed\":5.42,\"wind_deg\":192,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618146000,\"temp\":15.81,\"feels_like\":14.62,\"pressure\":1024,\"humidity\":45,\"dew_point\":4.15,\"uvi\":2.02,\"clouds\":24,\"visibility\":10000,\"wind_speed\":5.15,\"wind_deg\":193,\"wind_gust\":6.3,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618149600,\"temp\":15.71,\"feels_like\":14.51,\"pressure\":1025,\"humidity\":45,\"dew_point\":3.87,\"uvi\":1.17,\"clouds\":48,\"visibility\":10000,\"wind_speed\":4.79,\"wind_deg\":188,\"wind_gust\":6.01,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618153200,\"temp\":14.79,\"feels_like\":13.63,\"pressure\":1024,\"humidity\":50,\"dew_point\":4.71,\"uvi\":0.53,\"clouds\":63,\"visibility\":10000,\"wind_speed\":3.73,\"wind_deg\":177,\"wind_gust\":6.35,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618156800,\"temp\":12.85,\"feels_like\":11.73,\"pressure\":1024,\"humidity\":59,\"dew_point\":5.18,\"uvi\":0.17,\"clouds\":72,\"visibility\":10000,\"wind_speed\":3.05,\"wind_deg\":159,\"wind_gust\":6.38,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618160400,\"temp\":10.92,\"feels_like\":9.71,\"pressure\":1025,\"humidity\":63,\"dew_point\":4.26,\"uvi\":0,\"clouds\":78,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":152,\"wind_gust\":6.64,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618164000,\"temp\":9.65,\"feels_like\":7.72,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.66,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":3.68,\"wind_deg\":148,\"wind_gust\":9.04,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618167600,\"temp\":8.82,\"feels_like\":6.59,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.05,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.92,\"wind_deg\":147,\"wind_gust\":11.02,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618171200,\"temp\":8.07,\"feels_like\":5.87,\"pressure\":1026,\"humidity\":67,\"dew_point\":2.43,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.54,\"wind_deg\":154,\"wind_gust\":11.12,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618174800,\"temp\":7.24,\"feels_like\":4.99,\"pressure\":1027,\"humidity\":68,\"dew_point\":1.96,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.32,\"wind_deg\":154,\"wind_gust\":10.55,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618178400,\"temp\":6.58,\"feels_like\":4.31,\"pressure\":1027,\"humidity\":70,\"dew_point\":1.65,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.14,\"wind_deg\":154,\"wind_gust\":9.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618182000,\"temp\":6.03,\"feels_like\":3.57,\"pressure\":1027,\"humidity\":71,\"dew_point\":1.26,\"uvi\":0,\"clouds\":82,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":150,\"wind_gust\":8.44,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618185600,\"temp\":5.51,\"feels_like\":2.94,\"pressure\":1027,\"humidity\":72,\"dew_point\":0.95,\"uvi\":0,\"clouds\":71,\"visibility\":10000,\"wind_speed\":3.26,\"wind_deg\":150,\"wind_gust\":8.58,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618189200,\"temp\":5,\"feels_like\":2.29,\"pressure\":1027,\"humidity\":74,\"dew_point\":0.72,\"uvi\":0,\"clouds\":9,\"visibility\":10000,\"wind_speed\":3.3,\"wind_deg\":147,\"wind_gust\":8.63,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"pop\":0},{\"dt\":1618192800,\"temp\":4.47,\"feels_like\":1.69,\"pressure\":1027,\"humidity\":75,\"dew_point\":0.52,\"uvi\":0,\"clouds\":14,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":145,\"wind_gust\":8.14,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618196400,\"temp\":4.03,\"feels_like\":1.08,\"pressure\":1026,\"humidity\":76,\"dew_point\":0.22,\"uvi\":0,\"clouds\":12,\"visibility\":10000,\"wind_speed\":3.36,\"wind_deg\":138,\"wind_gust\":8.13,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618200000,\"temp\":4,\"feels_like\":0.9,\"pressure\":1026,\"humidity\":75,\"dew_point\":0.13,\"uvi\":0.08,\"clouds\":10,\"visibility\":10000,\"wind_speed\":3.57,\"wind_deg\":131,\"wind_gust\":9.24,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618203600,\"temp\":5.73,\"feels_like\":2.73,\"pressure\":1026,\"humidity\":68,\"dew_point\":0.52,\"uvi\":0.33,\"clouds\":8,\"visibility\":10000,\"wind_speed\":4.05,\"wind_deg\":138,\"wind_gust\":10.36,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618207200,\"temp\":7.87,\"feels_like\":4.9,\"pressure\":1025,\"humidity\":59,\"dew_point\":0.53,\"uvi\":0.84,\"clouds\":7,\"visibility\":10000,\"wind_speed\":5.05,\"wind_deg\":145,\"wind_gust\":10.48,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618210800,\"temp\":9.9,\"feels_like\":7.29,\"pressure\":1025,\"humidity\":53,\"dew_point\":0.8,\"uvi\":1.56,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.48,\"wind_deg\":147,\"wind_gust\":9.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618214400,\"temp\":11.5,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":47,\"dew_point\":0.86,\"uvi\":2.37,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.94,\"wind_deg\":152,\"wind_gust\":8.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618218000,\"temp\":12.64,\"feels_like\":11.08,\"pressure\":1024,\"humidity\":43,\"dew_point\":0.68,\"uvi\":3.04,\"clouds\":0,\"visibility\":10000,\"wind_speed\":6.25,\"wind_deg\":151,\"wind_gust\":8.5,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0}],\"daily\":[{\"dt\":1618048800,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":{\"day\":11.84,\"min\":1.69,\"max\":13.04,\"night\":7.78,\"eve\":11.02,\"morn\":1.69},\"feels_like\":{\"day\":10.12,\"night\":-2.86,\"eve\":9.72,\"morn\":-2.86},\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"wind_speed\":7.72,\"wind_deg\":200,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.36},{\"dt\":1618135200,\"sunrise\":1618111186,\"sunset\":1618160588,\"temp\":{\"day\":14.03,\"min\":4.51,\"max\":15.81,\"night\":8.07,\"eve\":12.85,\"morn\":4.51},\"feels_like\":{\"day\":12.87,\"night\":1.64,\"eve\":11.73,\"morn\":1.64},\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"wind_speed\":5.11,\"wind_deg\":194,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":100,\"pop\":0,\"uvi\":3.09},{\"dt\":1618221600,\"sunrise\":1618197445,\"sunset\":1618247098,\"temp\":{\"day\":13.62,\"min\":4,\"max\":14.94,\"night\":7.62,\"eve\":12.21,\"morn\":4},\"feels_like\":{\"day\":12.08,\"night\":0.9,\"eve\":10.87,\"morn\":0.9},\"pressure\":1024,\"humidity\":40,\"dew_point\":0.58,\"wind_speed\":6.09,\"wind_deg\":152,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.11},{\"dt\":1618308000,\"sunrise\":1618283705,\"sunset\":1618333607,\"temp\":{\"day\":14.42,\"min\":4.45,\"max\":16.91,\"night\":11.72,\"eve\":16.64,\"morn\":4.45},\"feels_like\":{\"day\":13.17,\"night\":2.28,\"eve\":15.43,\"morn\":2.28},\"pressure\":1019,\"humidity\":48,\"dew_point\":3.67,\"wind_speed\":3.07,\"wind_deg\":153,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":8,\"pop\":0,\"uvi\":3.53},{\"dt\":1618394400,\"sunrise\":1618369965,\"sunset\":1618420117,\"temp\":{\"day\":10.12,\"min\":7.84,\"max\":10.7,\"night\":8.87,\"eve\":9.78,\"morn\":7.84},\"feels_like\":{\"day\":9.54,\"night\":6.26,\"eve\":8.02,\"morn\":6.26},\"pressure\":1012,\"humidity\":90,\"dew_point\":8.65,\"wind_speed\":3.6,\"wind_deg\":129,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.98,\"rain\":2.37,\"uvi\":2.7},{\"dt\":1618480800,\"sunrise\":1618456226,\"sunset\":1618506627,\"temp\":{\"day\":8.88,\"min\":6.86,\"max\":10.63,\"night\":8.88,\"eve\":10.63,\"morn\":6.86},\"feels_like\":{\"day\":7.04,\"night\":5.16,\"eve\":9.81,\"morn\":5.16},\"pressure\":1011,\"humidity\":86,\"dew_point\":6.85,\"wind_speed\":3.22,\"wind_deg\":98,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.91,\"rain\":4.23,\"uvi\":3},{\"dt\":1618567200,\"sunrise\":1618542488,\"sunset\":1618593137,\"temp\":{\"day\":5.06,\"min\":4.81,\"max\":8.16,\"night\":4.84,\"eve\":7.24,\"morn\":5.39},\"feels_like\":{\"day\":2.81,\"night\":1.18,\"eve\":6.67,\"morn\":1.18},\"pressure\":1010,\"humidity\":91,\"dew_point\":3.81,\"wind_speed\":2.69,\"wind_deg\":101,\"weather\":[{\"id\":501,\"main\":\"Rain\",\"description\":\"moderate rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":1,\"rain\":15.37,\"uvi\":3},{\"dt\":1618653600,\"sunrise\":1618628751,\"sunset\":1618679646,\"temp\":{\"day\":3.07,\"min\":1.88,\"max\":5.32,\"night\":1.88,\"eve\":2.04,\"morn\":4.62},\"feels_like\":{\"day\":-0.42,\"night\":1.75,\"eve\":-1.74,\"morn\":1.75},\"pressure\":1010,\"humidity\":97,\"dew_point\":2.74,\"wind_speed\":3.86,\"wind_deg\":287,\"weather\":[{\"id\":616,\"main\":\"Snow\",\"description\":\"rain and snow\",\"icon\":\"13d\"}],\"clouds\":100,\"pop\":1,\"rain\":6.67,\"snow\":8.83,\"uvi\":3}]}"; - final CurrentWeatherData currentWeatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToCurrent(jsonString); + public void mapToCurrent_withHourlyVariations() throws JsonProcessingException { + final String jsonString = + "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"rain\":{},\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"hourly\":[{\"dt\":1618048800,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"clouds\":0,\"wind_speed\":7.72,\"wind_deg\":200,\"wind_gust\":10.55,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},{\"dt\":1618052400,\"temp\":11.6,\"feels_like\":9.96,\"pressure\":1018,\"humidity\":44,\"dew_point\":-0.2,\"uvi\":3.22,\"clouds\":32,\"visibility\":10000,\"wind_speed\":7.76,\"wind_deg\":202,\"wind_gust\":10.75,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618056000,\"temp\":12.26,\"feels_like\":10.72,\"pressure\":1018,\"humidity\":45,\"dew_point\":0.68,\"uvi\":2.67,\"clouds\":49,\"visibility\":10000,\"wind_speed\":7.66,\"wind_deg\":205,\"wind_gust\":10.76,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618059600,\"temp\":12.86,\"feels_like\":11.4,\"pressure\":1018,\"humidity\":46,\"dew_point\":1.53,\"uvi\":1.22,\"clouds\":19,\"visibility\":10000,\"wind_speed\":7.15,\"wind_deg\":210,\"wind_gust\":9.99,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618063200,\"temp\":13.04,\"feels_like\":11.68,\"pressure\":1018,\"humidity\":49,\"dew_point\":2.58,\"uvi\":0.7,\"clouds\":50,\"visibility\":10000,\"wind_speed\":5.95,\"wind_deg\":210,\"wind_gust\":9.4,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618066800,\"temp\":12.53,\"feels_like\":11.2,\"pressure\":1018,\"humidity\":52,\"dew_point\":3.07,\"uvi\":0.32,\"clouds\":48,\"visibility\":10000,\"wind_speed\":5.43,\"wind_deg\":209,\"wind_gust\":9.32,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618070400,\"temp\":11.02,\"feels_like\":9.72,\"pressure\":1018,\"humidity\":59,\"dew_point\":3.37,\"uvi\":0.12,\"clouds\":51,\"visibility\":10000,\"wind_speed\":4.22,\"wind_deg\":200,\"wind_gust\":8.94,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618074000,\"temp\":8.81,\"feels_like\":6.7,\"pressure\":1019,\"humidity\":67,\"dew_point\":3.23,\"uvi\":0,\"clouds\":55,\"visibility\":10000,\"wind_speed\":3.67,\"wind_deg\":184,\"wind_gust\":8.41,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618077600,\"temp\":7.94,\"feels_like\":5.47,\"pressure\":1020,\"humidity\":71,\"dew_point\":3.06,\"uvi\":0,\"clouds\":59,\"visibility\":10000,\"wind_speed\":4,\"wind_deg\":177,\"wind_gust\":10.47,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618081200,\"temp\":7.68,\"feels_like\":4.81,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.92,\"uvi\":0,\"clouds\":79,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":179,\"wind_gust\":12.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618084800,\"temp\":7.78,\"feels_like\":4.76,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.89,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":5.12,\"wind_deg\":185,\"wind_gust\":13.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618088400,\"temp\":7.45,\"feels_like\":4.33,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.77,\"uvi\":0,\"clouds\":86,\"visibility\":10000,\"wind_speed\":5.17,\"wind_deg\":190,\"wind_gust\":13.37,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618092000,\"temp\":6.97,\"feels_like\":3.85,\"pressure\":1021,\"humidity\":74,\"dew_point\":2.67,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":4.89,\"wind_deg\":192,\"wind_gust\":12.68,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618095600,\"temp\":6.46,\"feels_like\":3.4,\"pressure\":1021,\"humidity\":76,\"dew_point\":2.7,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":191,\"wind_gust\":11.89,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618099200,\"temp\":5.96,\"feels_like\":2.9,\"pressure\":1021,\"humidity\":79,\"dew_point\":2.65,\"uvi\":0,\"clouds\":91,\"visibility\":10000,\"wind_speed\":4.26,\"wind_deg\":188,\"wind_gust\":11.23,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618102800,\"temp\":5.31,\"feels_like\":2.22,\"pressure\":1022,\"humidity\":81,\"dew_point\":2.47,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.04,\"wind_deg\":186,\"wind_gust\":10.72,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618106400,\"temp\":5.2,\"feels_like\":2.18,\"pressure\":1022,\"humidity\":82,\"dew_point\":2.41,\"uvi\":0,\"clouds\":95,\"visibility\":10000,\"wind_speed\":3.87,\"wind_deg\":190,\"wind_gust\":10.92,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618110000,\"temp\":4.56,\"feels_like\":1.51,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.29,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":3.69,\"wind_deg\":186,\"wind_gust\":10.33,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618113600,\"temp\":4.51,\"feels_like\":1.64,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.33,\"uvi\":0,\"clouds\":84,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":191,\"wind_gust\":10.18,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618117200,\"temp\":6.05,\"feels_like\":3.41,\"pressure\":1024,\"humidity\":80,\"dew_point\":2.89,\"uvi\":0.15,\"clouds\":80,\"visibility\":10000,\"wind_speed\":3.55,\"wind_deg\":193,\"wind_gust\":10.09,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618120800,\"temp\":7.96,\"feels_like\":5.31,\"pressure\":1024,\"humidity\":72,\"dew_point\":3.29,\"uvi\":0.38,\"clouds\":80,\"visibility\":10000,\"wind_speed\":4.39,\"wind_deg\":197,\"wind_gust\":8.53,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618124400,\"temp\":9.61,\"feels_like\":7.3,\"pressure\":1024,\"humidity\":67,\"dew_point\":3.88,\"uvi\":1.01,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":197,\"wind_gust\":7.77,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618128000,\"temp\":11.14,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":62,\"dew_point\":4.27,\"uvi\":1.54,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":198,\"wind_gust\":7.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618131600,\"temp\":12.8,\"feels_like\":11.62,\"pressure\":1025,\"humidity\":57,\"dew_point\":4.57,\"uvi\":1.97,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.87,\"wind_deg\":196,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618135200,\"temp\":14.03,\"feels_like\":12.87,\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"uvi\":3.09,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.11,\"wind_deg\":194,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618138800,\"temp\":14.82,\"feels_like\":13.66,\"pressure\":1025,\"humidity\":50,\"dew_point\":4.62,\"uvi\":2.96,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.32,\"wind_deg\":191,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618142400,\"temp\":15.64,\"feels_like\":14.49,\"pressure\":1025,\"humidity\":47,\"dew_point\":4.48,\"uvi\":2.45,\"clouds\":94,\"visibility\":10000,\"wind_speed\":5.42,\"wind_deg\":192,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618146000,\"temp\":15.81,\"feels_like\":14.62,\"pressure\":1024,\"humidity\":45,\"dew_point\":4.15,\"uvi\":2.02,\"clouds\":24,\"visibility\":10000,\"wind_speed\":5.15,\"wind_deg\":193,\"wind_gust\":6.3,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618149600,\"temp\":15.71,\"feels_like\":14.51,\"pressure\":1025,\"humidity\":45,\"dew_point\":3.87,\"uvi\":1.17,\"clouds\":48,\"visibility\":10000,\"wind_speed\":4.79,\"wind_deg\":188,\"wind_gust\":6.01,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618153200,\"temp\":14.79,\"feels_like\":13.63,\"pressure\":1024,\"humidity\":50,\"dew_point\":4.71,\"uvi\":0.53,\"clouds\":63,\"visibility\":10000,\"wind_speed\":3.73,\"wind_deg\":177,\"wind_gust\":6.35,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618156800,\"temp\":12.85,\"feels_like\":11.73,\"pressure\":1024,\"humidity\":59,\"dew_point\":5.18,\"uvi\":0.17,\"clouds\":72,\"visibility\":10000,\"wind_speed\":3.05,\"wind_deg\":159,\"wind_gust\":6.38,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618160400,\"temp\":10.92,\"feels_like\":9.71,\"pressure\":1025,\"humidity\":63,\"dew_point\":4.26,\"uvi\":0,\"clouds\":78,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":152,\"wind_gust\":6.64,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618164000,\"temp\":9.65,\"feels_like\":7.72,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.66,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":3.68,\"wind_deg\":148,\"wind_gust\":9.04,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618167600,\"temp\":8.82,\"feels_like\":6.59,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.05,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.92,\"wind_deg\":147,\"wind_gust\":11.02,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618171200,\"temp\":8.07,\"feels_like\":5.87,\"pressure\":1026,\"humidity\":67,\"dew_point\":2.43,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.54,\"wind_deg\":154,\"wind_gust\":11.12,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618174800,\"temp\":7.24,\"feels_like\":4.99,\"pressure\":1027,\"humidity\":68,\"dew_point\":1.96,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.32,\"wind_deg\":154,\"wind_gust\":10.55,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618178400,\"temp\":6.58,\"feels_like\":4.31,\"pressure\":1027,\"humidity\":70,\"dew_point\":1.65,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.14,\"wind_deg\":154,\"wind_gust\":9.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618182000,\"temp\":6.03,\"feels_like\":3.57,\"pressure\":1027,\"humidity\":71,\"dew_point\":1.26,\"uvi\":0,\"clouds\":82,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":150,\"wind_gust\":8.44,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618185600,\"temp\":5.51,\"feels_like\":2.94,\"pressure\":1027,\"humidity\":72,\"dew_point\":0.95,\"uvi\":0,\"clouds\":71,\"visibility\":10000,\"wind_speed\":3.26,\"wind_deg\":150,\"wind_gust\":8.58,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618189200,\"temp\":5,\"feels_like\":2.29,\"pressure\":1027,\"humidity\":74,\"dew_point\":0.72,\"uvi\":0,\"clouds\":9,\"visibility\":10000,\"wind_speed\":3.3,\"wind_deg\":147,\"wind_gust\":8.63,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"pop\":0},{\"dt\":1618192800,\"temp\":4.47,\"feels_like\":1.69,\"pressure\":1027,\"humidity\":75,\"dew_point\":0.52,\"uvi\":0,\"clouds\":14,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":145,\"wind_gust\":8.14,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618196400,\"temp\":4.03,\"feels_like\":1.08,\"pressure\":1026,\"humidity\":76,\"dew_point\":0.22,\"uvi\":0,\"clouds\":12,\"visibility\":10000,\"wind_speed\":3.36,\"wind_deg\":138,\"wind_gust\":8.13,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618200000,\"temp\":4,\"feels_like\":0.9,\"pressure\":1026,\"humidity\":75,\"dew_point\":0.13,\"uvi\":0.08,\"clouds\":10,\"visibility\":10000,\"wind_speed\":3.57,\"wind_deg\":131,\"wind_gust\":9.24,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618203600,\"temp\":5.73,\"feels_like\":2.73,\"pressure\":1026,\"humidity\":68,\"dew_point\":0.52,\"uvi\":0.33,\"clouds\":8,\"visibility\":10000,\"wind_speed\":4.05,\"wind_deg\":138,\"wind_gust\":10.36,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618207200,\"temp\":7.87,\"feels_like\":4.9,\"pressure\":1025,\"humidity\":59,\"dew_point\":0.53,\"uvi\":0.84,\"clouds\":7,\"visibility\":10000,\"wind_speed\":5.05,\"wind_deg\":145,\"wind_gust\":10.48,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618210800,\"temp\":9.9,\"feels_like\":7.29,\"pressure\":1025,\"humidity\":53,\"dew_point\":0.8,\"uvi\":1.56,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.48,\"wind_deg\":147,\"wind_gust\":9.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618214400,\"temp\":11.5,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":47,\"dew_point\":0.86,\"uvi\":2.37,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.94,\"wind_deg\":152,\"wind_gust\":8.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618218000,\"temp\":12.64,\"feels_like\":11.08,\"pressure\":1024,\"humidity\":43,\"dew_point\":0.68,\"uvi\":3.04,\"clouds\":0,\"visibility\":10000,\"wind_speed\":6.25,\"wind_deg\":151,\"wind_gust\":8.5,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0}],\"daily\":[{\"dt\":1618048800,\"sunrise\":1618024927,\"sunset\":1618074079,\"temp\":{\"day\":11.84,\"min\":1.69,\"max\":13.04,\"night\":7.78,\"eve\":11.02,\"morn\":1.69},\"feels_like\":{\"day\":10.12,\"night\":-2.86,\"eve\":9.72,\"morn\":-2.86},\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"wind_speed\":7.72,\"wind_deg\":200,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.36},{\"dt\":1618135200,\"sunrise\":1618111186,\"sunset\":1618160588,\"temp\":{\"day\":14.03,\"min\":4.51,\"max\":15.81,\"night\":8.07,\"eve\":12.85,\"morn\":4.51},\"feels_like\":{\"day\":12.87,\"night\":1.64,\"eve\":11.73,\"morn\":1.64},\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"wind_speed\":5.11,\"wind_deg\":194,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"clouds\":100,\"pop\":0,\"uvi\":3.09},{\"dt\":1618221600,\"sunrise\":1618197445,\"sunset\":1618247098,\"temp\":{\"day\":13.62,\"min\":4,\"max\":14.94,\"night\":7.62,\"eve\":12.21,\"morn\":4},\"feels_like\":{\"day\":12.08,\"night\":0.9,\"eve\":10.87,\"morn\":0.9},\"pressure\":1024,\"humidity\":40,\"dew_point\":0.58,\"wind_speed\":6.09,\"wind_deg\":152,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":0,\"pop\":0,\"uvi\":3.11},{\"dt\":1618308000,\"sunrise\":1618283705,\"sunset\":1618333607,\"temp\":{\"day\":14.42,\"min\":4.45,\"max\":16.91,\"night\":11.72,\"eve\":16.64,\"morn\":4.45},\"feels_like\":{\"day\":13.17,\"night\":2.28,\"eve\":15.43,\"morn\":2.28},\"pressure\":1019,\"humidity\":48,\"dew_point\":3.67,\"wind_speed\":3.07,\"wind_deg\":153,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":8,\"pop\":0,\"uvi\":3.53},{\"dt\":1618394400,\"sunrise\":1618369965,\"sunset\":1618420117,\"temp\":{\"day\":10.12,\"min\":7.84,\"max\":10.7,\"night\":8.87,\"eve\":9.78,\"morn\":7.84},\"feels_like\":{\"day\":9.54,\"night\":6.26,\"eve\":8.02,\"morn\":6.26},\"pressure\":1012,\"humidity\":90,\"dew_point\":8.65,\"wind_speed\":3.6,\"wind_deg\":129,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.98,\"rain\":2.37,\"uvi\":2.7},{\"dt\":1618480800,\"sunrise\":1618456226,\"sunset\":1618506627,\"temp\":{\"day\":8.88,\"min\":6.86,\"max\":10.63,\"night\":8.88,\"eve\":10.63,\"morn\":6.86},\"feels_like\":{\"day\":7.04,\"night\":5.16,\"eve\":9.81,\"morn\":5.16},\"pressure\":1011,\"humidity\":86,\"dew_point\":6.85,\"wind_speed\":3.22,\"wind_deg\":98,\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":0.91,\"rain\":4.23,\"uvi\":3},{\"dt\":1618567200,\"sunrise\":1618542488,\"sunset\":1618593137,\"temp\":{\"day\":5.06,\"min\":4.81,\"max\":8.16,\"night\":4.84,\"eve\":7.24,\"morn\":5.39},\"feels_like\":{\"day\":2.81,\"night\":1.18,\"eve\":6.67,\"morn\":1.18},\"pressure\":1010,\"humidity\":91,\"dew_point\":3.81,\"wind_speed\":2.69,\"wind_deg\":101,\"weather\":[{\"id\":501,\"main\":\"Rain\",\"description\":\"moderate rain\",\"icon\":\"10d\"}],\"clouds\":100,\"pop\":1,\"rain\":15.37,\"uvi\":3},{\"dt\":1618653600,\"sunrise\":1618628751,\"sunset\":1618679646,\"temp\":{\"day\":3.07,\"min\":1.88,\"max\":5.32,\"night\":1.88,\"eve\":2.04,\"morn\":4.62},\"feels_like\":{\"day\":-0.42,\"night\":1.75,\"eve\":-1.74,\"morn\":1.75},\"pressure\":1010,\"humidity\":97,\"dew_point\":2.74,\"wind_speed\":3.86,\"wind_deg\":287,\"weather\":[{\"id\":616,\"main\":\"Snow\",\"description\":\"rain and snow\",\"icon\":\"13d\"}],\"clouds\":100,\"pop\":1,\"rain\":6.67,\"snow\":8.83,\"uvi\":3}]}"; + final OneCallCurrentForecastModel currentWeatherData = new ObjectMapper().readValue(jsonString, OneCallCurrentForecastModel.class); assertNotNull(currentWeatherData); assertNull(currentWeatherData.getHourlyList().get(0).getUvIndex()); - assertNull(currentWeatherData.getHourlyList().get(0).getVisibilityInMetres()); + assertNull(currentWeatherData.getHourlyList().get(0).getVisibility()); assertNull(currentWeatherData.getHourlyList().get(0).getProbabilityOfPrecipitation()); } @Test - public void mapToCurrent_withoutDailyListNode() { - final String jsonString = "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"snow\":{\"1h\":20},\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"hourly\":[{\"dt\":1618048800,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":7.72,\"wind_deg\":200,\"wind_gust\":10.55,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618052400,\"temp\":11.6,\"feels_like\":9.96,\"pressure\":1018,\"humidity\":44,\"dew_point\":-0.2,\"uvi\":3.22,\"clouds\":32,\"visibility\":10000,\"wind_speed\":7.76,\"wind_deg\":202,\"wind_gust\":10.75,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618056000,\"temp\":12.26,\"feels_like\":10.72,\"pressure\":1018,\"humidity\":45,\"dew_point\":0.68,\"uvi\":2.67,\"clouds\":49,\"visibility\":10000,\"wind_speed\":7.66,\"wind_deg\":205,\"wind_gust\":10.76,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618059600,\"temp\":12.86,\"feels_like\":11.4,\"pressure\":1018,\"humidity\":46,\"dew_point\":1.53,\"uvi\":1.22,\"clouds\":19,\"visibility\":10000,\"wind_speed\":7.15,\"wind_deg\":210,\"wind_gust\":9.99,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618063200,\"temp\":13.04,\"feels_like\":11.68,\"pressure\":1018,\"humidity\":49,\"dew_point\":2.58,\"uvi\":0.7,\"clouds\":50,\"visibility\":10000,\"wind_speed\":5.95,\"wind_deg\":210,\"wind_gust\":9.4,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618066800,\"temp\":12.53,\"feels_like\":11.2,\"pressure\":1018,\"humidity\":52,\"dew_point\":3.07,\"uvi\":0.32,\"clouds\":48,\"visibility\":10000,\"wind_speed\":5.43,\"wind_deg\":209,\"wind_gust\":9.32,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618070400,\"temp\":11.02,\"feels_like\":9.72,\"pressure\":1018,\"humidity\":59,\"dew_point\":3.37,\"uvi\":0.12,\"clouds\":51,\"visibility\":10000,\"wind_speed\":4.22,\"wind_deg\":200,\"wind_gust\":8.94,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618074000,\"temp\":8.81,\"feels_like\":6.7,\"pressure\":1019,\"humidity\":67,\"dew_point\":3.23,\"uvi\":0,\"clouds\":55,\"visibility\":10000,\"wind_speed\":3.67,\"wind_deg\":184,\"wind_gust\":8.41,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618077600,\"temp\":7.94,\"feels_like\":5.47,\"pressure\":1020,\"humidity\":71,\"dew_point\":3.06,\"uvi\":0,\"clouds\":59,\"visibility\":10000,\"wind_speed\":4,\"wind_deg\":177,\"wind_gust\":10.47,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618081200,\"temp\":7.68,\"feels_like\":4.81,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.92,\"uvi\":0,\"clouds\":79,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":179,\"wind_gust\":12.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618084800,\"temp\":7.78,\"feels_like\":4.76,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.89,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":5.12,\"wind_deg\":185,\"wind_gust\":13.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618088400,\"temp\":7.45,\"feels_like\":4.33,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.77,\"uvi\":0,\"clouds\":86,\"visibility\":10000,\"wind_speed\":5.17,\"wind_deg\":190,\"wind_gust\":13.37,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618092000,\"temp\":6.97,\"feels_like\":3.85,\"pressure\":1021,\"humidity\":74,\"dew_point\":2.67,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":4.89,\"wind_deg\":192,\"wind_gust\":12.68,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618095600,\"temp\":6.46,\"feels_like\":3.4,\"pressure\":1021,\"humidity\":76,\"dew_point\":2.7,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":191,\"wind_gust\":11.89,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618099200,\"temp\":5.96,\"feels_like\":2.9,\"pressure\":1021,\"humidity\":79,\"dew_point\":2.65,\"uvi\":0,\"clouds\":91,\"visibility\":10000,\"wind_speed\":4.26,\"wind_deg\":188,\"wind_gust\":11.23,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618102800,\"temp\":5.31,\"feels_like\":2.22,\"pressure\":1022,\"humidity\":81,\"dew_point\":2.47,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.04,\"wind_deg\":186,\"wind_gust\":10.72,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618106400,\"temp\":5.2,\"feels_like\":2.18,\"pressure\":1022,\"humidity\":82,\"dew_point\":2.41,\"uvi\":0,\"clouds\":95,\"visibility\":10000,\"wind_speed\":3.87,\"wind_deg\":190,\"wind_gust\":10.92,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618110000,\"temp\":4.56,\"feels_like\":1.51,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.29,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":3.69,\"wind_deg\":186,\"wind_gust\":10.33,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618113600,\"temp\":4.51,\"feels_like\":1.64,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.33,\"uvi\":0,\"clouds\":84,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":191,\"wind_gust\":10.18,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618117200,\"temp\":6.05,\"feels_like\":3.41,\"pressure\":1024,\"humidity\":80,\"dew_point\":2.89,\"uvi\":0.15,\"clouds\":80,\"visibility\":10000,\"wind_speed\":3.55,\"wind_deg\":193,\"wind_gust\":10.09,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618120800,\"temp\":7.96,\"feels_like\":5.31,\"pressure\":1024,\"humidity\":72,\"dew_point\":3.29,\"uvi\":0.38,\"clouds\":80,\"visibility\":10000,\"wind_speed\":4.39,\"wind_deg\":197,\"wind_gust\":8.53,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618124400,\"temp\":9.61,\"feels_like\":7.3,\"pressure\":1024,\"humidity\":67,\"dew_point\":3.88,\"uvi\":1.01,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":197,\"wind_gust\":7.77,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618128000,\"temp\":11.14,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":62,\"dew_point\":4.27,\"uvi\":1.54,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":198,\"wind_gust\":7.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618131600,\"temp\":12.8,\"feels_like\":11.62,\"pressure\":1025,\"humidity\":57,\"dew_point\":4.57,\"uvi\":1.97,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.87,\"wind_deg\":196,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618135200,\"temp\":14.03,\"feels_like\":12.87,\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"uvi\":3.09,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.11,\"wind_deg\":194,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618138800,\"temp\":14.82,\"feels_like\":13.66,\"pressure\":1025,\"humidity\":50,\"dew_point\":4.62,\"uvi\":2.96,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.32,\"wind_deg\":191,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618142400,\"temp\":15.64,\"feels_like\":14.49,\"pressure\":1025,\"humidity\":47,\"dew_point\":4.48,\"uvi\":2.45,\"clouds\":94,\"visibility\":10000,\"wind_speed\":5.42,\"wind_deg\":192,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618146000,\"temp\":15.81,\"feels_like\":14.62,\"pressure\":1024,\"humidity\":45,\"dew_point\":4.15,\"uvi\":2.02,\"clouds\":24,\"visibility\":10000,\"wind_speed\":5.15,\"wind_deg\":193,\"wind_gust\":6.3,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618149600,\"temp\":15.71,\"feels_like\":14.51,\"pressure\":1025,\"humidity\":45,\"dew_point\":3.87,\"uvi\":1.17,\"clouds\":48,\"visibility\":10000,\"wind_speed\":4.79,\"wind_deg\":188,\"wind_gust\":6.01,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618153200,\"temp\":14.79,\"feels_like\":13.63,\"pressure\":1024,\"humidity\":50,\"dew_point\":4.71,\"uvi\":0.53,\"clouds\":63,\"visibility\":10000,\"wind_speed\":3.73,\"wind_deg\":177,\"wind_gust\":6.35,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618156800,\"temp\":12.85,\"feels_like\":11.73,\"pressure\":1024,\"humidity\":59,\"dew_point\":5.18,\"uvi\":0.17,\"clouds\":72,\"visibility\":10000,\"wind_speed\":3.05,\"wind_deg\":159,\"wind_gust\":6.38,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618160400,\"temp\":10.92,\"feels_like\":9.71,\"pressure\":1025,\"humidity\":63,\"dew_point\":4.26,\"uvi\":0,\"clouds\":78,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":152,\"wind_gust\":6.64,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618164000,\"temp\":9.65,\"feels_like\":7.72,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.66,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":3.68,\"wind_deg\":148,\"wind_gust\":9.04,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618167600,\"temp\":8.82,\"feels_like\":6.59,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.05,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.92,\"wind_deg\":147,\"wind_gust\":11.02,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618171200,\"temp\":8.07,\"feels_like\":5.87,\"pressure\":1026,\"humidity\":67,\"dew_point\":2.43,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.54,\"wind_deg\":154,\"wind_gust\":11.12,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618174800,\"temp\":7.24,\"feels_like\":4.99,\"pressure\":1027,\"humidity\":68,\"dew_point\":1.96,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.32,\"wind_deg\":154,\"wind_gust\":10.55,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618178400,\"temp\":6.58,\"feels_like\":4.31,\"pressure\":1027,\"humidity\":70,\"dew_point\":1.65,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.14,\"wind_deg\":154,\"wind_gust\":9.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618182000,\"temp\":6.03,\"feels_like\":3.57,\"pressure\":1027,\"humidity\":71,\"dew_point\":1.26,\"uvi\":0,\"clouds\":82,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":150,\"wind_gust\":8.44,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618185600,\"temp\":5.51,\"feels_like\":2.94,\"pressure\":1027,\"humidity\":72,\"dew_point\":0.95,\"uvi\":0,\"clouds\":71,\"visibility\":10000,\"wind_speed\":3.26,\"wind_deg\":150,\"wind_gust\":8.58,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618189200,\"temp\":5,\"feels_like\":2.29,\"pressure\":1027,\"humidity\":74,\"dew_point\":0.72,\"uvi\":0,\"clouds\":9,\"visibility\":10000,\"wind_speed\":3.3,\"wind_deg\":147,\"wind_gust\":8.63,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"pop\":0},{\"dt\":1618192800,\"temp\":4.47,\"feels_like\":1.69,\"pressure\":1027,\"humidity\":75,\"dew_point\":0.52,\"uvi\":0,\"clouds\":14,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":145,\"wind_gust\":8.14,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618196400,\"temp\":4.03,\"feels_like\":1.08,\"pressure\":1026,\"humidity\":76,\"dew_point\":0.22,\"uvi\":0,\"clouds\":12,\"visibility\":10000,\"wind_speed\":3.36,\"wind_deg\":138,\"wind_gust\":8.13,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618200000,\"temp\":4,\"feels_like\":0.9,\"pressure\":1026,\"humidity\":75,\"dew_point\":0.13,\"uvi\":0.08,\"clouds\":10,\"visibility\":10000,\"wind_speed\":3.57,\"wind_deg\":131,\"wind_gust\":9.24,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618203600,\"temp\":5.73,\"feels_like\":2.73,\"pressure\":1026,\"humidity\":68,\"dew_point\":0.52,\"uvi\":0.33,\"clouds\":8,\"visibility\":10000,\"wind_speed\":4.05,\"wind_deg\":138,\"wind_gust\":10.36,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618207200,\"temp\":7.87,\"feels_like\":4.9,\"pressure\":1025,\"humidity\":59,\"dew_point\":0.53,\"uvi\":0.84,\"clouds\":7,\"visibility\":10000,\"wind_speed\":5.05,\"wind_deg\":145,\"wind_gust\":10.48,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618210800,\"temp\":9.9,\"feels_like\":7.29,\"pressure\":1025,\"humidity\":53,\"dew_point\":0.8,\"uvi\":1.56,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.48,\"wind_deg\":147,\"wind_gust\":9.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618214400,\"temp\":11.5,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":47,\"dew_point\":0.86,\"uvi\":2.37,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.94,\"wind_deg\":152,\"wind_gust\":8.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618218000,\"temp\":12.64,\"feels_like\":11.08,\"pressure\":1024,\"humidity\":43,\"dew_point\":0.68,\"uvi\":3.04,\"clouds\":0,\"visibility\":10000,\"wind_speed\":6.25,\"wind_deg\":151,\"wind_gust\":8.5,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0}]}"; - final CurrentWeatherData currentWeatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToCurrent(jsonString); + public void mapToCurrent_withoutDailyListNode() throws JsonProcessingException { + final String jsonString = + "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"snow\":{\"1h\":20},\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"minutely\":[{\"dt\":1618050060,\"precipitation\":0},{\"dt\":1618050120,\"precipitation\":0},{\"dt\":1618050180,\"precipitation\":0},{\"dt\":1618050240,\"precipitation\":0},{\"dt\":1618050300,\"precipitation\":0},{\"dt\":1618050360,\"precipitation\":0},{\"dt\":1618050420,\"precipitation\":0},{\"dt\":1618050480,\"precipitation\":0},{\"dt\":1618050540,\"precipitation\":0},{\"dt\":1618050600,\"precipitation\":0},{\"dt\":1618050660,\"precipitation\":0},{\"dt\":1618050720,\"precipitation\":0},{\"dt\":1618050780,\"precipitation\":0},{\"dt\":1618050840,\"precipitation\":0},{\"dt\":1618050900,\"precipitation\":0},{\"dt\":1618050960,\"precipitation\":0},{\"dt\":1618051020,\"precipitation\":0},{\"dt\":1618051080,\"precipitation\":0},{\"dt\":1618051140,\"precipitation\":0},{\"dt\":1618051200,\"precipitation\":0},{\"dt\":1618051260,\"precipitation\":0},{\"dt\":1618051320,\"precipitation\":0},{\"dt\":1618051380,\"precipitation\":0},{\"dt\":1618051440,\"precipitation\":0},{\"dt\":1618051500,\"precipitation\":0},{\"dt\":1618051560,\"precipitation\":0},{\"dt\":1618051620,\"precipitation\":0},{\"dt\":1618051680,\"precipitation\":0},{\"dt\":1618051740,\"precipitation\":0},{\"dt\":1618051800,\"precipitation\":0},{\"dt\":1618051860,\"precipitation\":0},{\"dt\":1618051920,\"precipitation\":0},{\"dt\":1618051980,\"precipitation\":0},{\"dt\":1618052040,\"precipitation\":0},{\"dt\":1618052100,\"precipitation\":0},{\"dt\":1618052160,\"precipitation\":0},{\"dt\":1618052220,\"precipitation\":0},{\"dt\":1618052280,\"precipitation\":0},{\"dt\":1618052340,\"precipitation\":0},{\"dt\":1618052400,\"precipitation\":0},{\"dt\":1618052460,\"precipitation\":0},{\"dt\":1618052520,\"precipitation\":0},{\"dt\":1618052580,\"precipitation\":0},{\"dt\":1618052640,\"precipitation\":0},{\"dt\":1618052700,\"precipitation\":0},{\"dt\":1618052760,\"precipitation\":0},{\"dt\":1618052820,\"precipitation\":0},{\"dt\":1618052880,\"precipitation\":0},{\"dt\":1618052940,\"precipitation\":0},{\"dt\":1618053000,\"precipitation\":0},{\"dt\":1618053060,\"precipitation\":0},{\"dt\":1618053120,\"precipitation\":0},{\"dt\":1618053180,\"precipitation\":0},{\"dt\":1618053240,\"precipitation\":0},{\"dt\":1618053300,\"precipitation\":0},{\"dt\":1618053360,\"precipitation\":0},{\"dt\":1618053420,\"precipitation\":0},{\"dt\":1618053480,\"precipitation\":0},{\"dt\":1618053540,\"precipitation\":0},{\"dt\":1618053600,\"precipitation\":0},{\"dt\":1618053660,\"precipitation\":0}],\"hourly\":[{\"dt\":1618048800,\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":7.72,\"wind_deg\":200,\"wind_gust\":10.55,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618052400,\"temp\":11.6,\"feels_like\":9.96,\"pressure\":1018,\"humidity\":44,\"dew_point\":-0.2,\"uvi\":3.22,\"clouds\":32,\"visibility\":10000,\"wind_speed\":7.76,\"wind_deg\":202,\"wind_gust\":10.75,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618056000,\"temp\":12.26,\"feels_like\":10.72,\"pressure\":1018,\"humidity\":45,\"dew_point\":0.68,\"uvi\":2.67,\"clouds\":49,\"visibility\":10000,\"wind_speed\":7.66,\"wind_deg\":205,\"wind_gust\":10.76,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618059600,\"temp\":12.86,\"feels_like\":11.4,\"pressure\":1018,\"humidity\":46,\"dew_point\":1.53,\"uvi\":1.22,\"clouds\":19,\"visibility\":10000,\"wind_speed\":7.15,\"wind_deg\":210,\"wind_gust\":9.99,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618063200,\"temp\":13.04,\"feels_like\":11.68,\"pressure\":1018,\"humidity\":49,\"dew_point\":2.58,\"uvi\":0.7,\"clouds\":50,\"visibility\":10000,\"wind_speed\":5.95,\"wind_deg\":210,\"wind_gust\":9.4,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618066800,\"temp\":12.53,\"feels_like\":11.2,\"pressure\":1018,\"humidity\":52,\"dew_point\":3.07,\"uvi\":0.32,\"clouds\":48,\"visibility\":10000,\"wind_speed\":5.43,\"wind_deg\":209,\"wind_gust\":9.32,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618070400,\"temp\":11.02,\"feels_like\":9.72,\"pressure\":1018,\"humidity\":59,\"dew_point\":3.37,\"uvi\":0.12,\"clouds\":51,\"visibility\":10000,\"wind_speed\":4.22,\"wind_deg\":200,\"wind_gust\":8.94,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618074000,\"temp\":8.81,\"feels_like\":6.7,\"pressure\":1019,\"humidity\":67,\"dew_point\":3.23,\"uvi\":0,\"clouds\":55,\"visibility\":10000,\"wind_speed\":3.67,\"wind_deg\":184,\"wind_gust\":8.41,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618077600,\"temp\":7.94,\"feels_like\":5.47,\"pressure\":1020,\"humidity\":71,\"dew_point\":3.06,\"uvi\":0,\"clouds\":59,\"visibility\":10000,\"wind_speed\":4,\"wind_deg\":177,\"wind_gust\":10.47,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618081200,\"temp\":7.68,\"feels_like\":4.81,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.92,\"uvi\":0,\"clouds\":79,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":179,\"wind_gust\":12.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618084800,\"temp\":7.78,\"feels_like\":4.76,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.89,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":5.12,\"wind_deg\":185,\"wind_gust\":13.11,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618088400,\"temp\":7.45,\"feels_like\":4.33,\"pressure\":1020,\"humidity\":71,\"dew_point\":2.77,\"uvi\":0,\"clouds\":86,\"visibility\":10000,\"wind_speed\":5.17,\"wind_deg\":190,\"wind_gust\":13.37,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618092000,\"temp\":6.97,\"feels_like\":3.85,\"pressure\":1021,\"humidity\":74,\"dew_point\":2.67,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":4.89,\"wind_deg\":192,\"wind_gust\":12.68,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618095600,\"temp\":6.46,\"feels_like\":3.4,\"pressure\":1021,\"humidity\":76,\"dew_point\":2.7,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":191,\"wind_gust\":11.89,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618099200,\"temp\":5.96,\"feels_like\":2.9,\"pressure\":1021,\"humidity\":79,\"dew_point\":2.65,\"uvi\":0,\"clouds\":91,\"visibility\":10000,\"wind_speed\":4.26,\"wind_deg\":188,\"wind_gust\":11.23,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618102800,\"temp\":5.31,\"feels_like\":2.22,\"pressure\":1022,\"humidity\":81,\"dew_point\":2.47,\"uvi\":0,\"clouds\":89,\"visibility\":10000,\"wind_speed\":4.04,\"wind_deg\":186,\"wind_gust\":10.72,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618106400,\"temp\":5.2,\"feels_like\":2.18,\"pressure\":1022,\"humidity\":82,\"dew_point\":2.41,\"uvi\":0,\"clouds\":95,\"visibility\":10000,\"wind_speed\":3.87,\"wind_deg\":190,\"wind_gust\":10.92,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618110000,\"temp\":4.56,\"feels_like\":1.51,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.29,\"uvi\":0,\"clouds\":88,\"visibility\":10000,\"wind_speed\":3.69,\"wind_deg\":186,\"wind_gust\":10.33,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618113600,\"temp\":4.51,\"feels_like\":1.64,\"pressure\":1023,\"humidity\":85,\"dew_point\":2.33,\"uvi\":0,\"clouds\":84,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":191,\"wind_gust\":10.18,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618117200,\"temp\":6.05,\"feels_like\":3.41,\"pressure\":1024,\"humidity\":80,\"dew_point\":2.89,\"uvi\":0.15,\"clouds\":80,\"visibility\":10000,\"wind_speed\":3.55,\"wind_deg\":193,\"wind_gust\":10.09,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618120800,\"temp\":7.96,\"feels_like\":5.31,\"pressure\":1024,\"humidity\":72,\"dew_point\":3.29,\"uvi\":0.38,\"clouds\":80,\"visibility\":10000,\"wind_speed\":4.39,\"wind_deg\":197,\"wind_gust\":8.53,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618124400,\"temp\":9.61,\"feels_like\":7.3,\"pressure\":1024,\"humidity\":67,\"dew_point\":3.88,\"uvi\":1.01,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.5,\"wind_deg\":197,\"wind_gust\":7.77,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618128000,\"temp\":11.14,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":62,\"dew_point\":4.27,\"uvi\":1.54,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.71,\"wind_deg\":198,\"wind_gust\":7.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618131600,\"temp\":12.8,\"feels_like\":11.62,\"pressure\":1025,\"humidity\":57,\"dew_point\":4.57,\"uvi\":1.97,\"clouds\":100,\"visibility\":10000,\"wind_speed\":4.87,\"wind_deg\":196,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618135200,\"temp\":14.03,\"feels_like\":12.87,\"pressure\":1025,\"humidity\":53,\"dew_point\":4.65,\"uvi\":3.09,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.11,\"wind_deg\":194,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618138800,\"temp\":14.82,\"feels_like\":13.66,\"pressure\":1025,\"humidity\":50,\"dew_point\":4.62,\"uvi\":2.96,\"clouds\":100,\"visibility\":10000,\"wind_speed\":5.32,\"wind_deg\":191,\"wind_gust\":6.82,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618142400,\"temp\":15.64,\"feels_like\":14.49,\"pressure\":1025,\"humidity\":47,\"dew_point\":4.48,\"uvi\":2.45,\"clouds\":94,\"visibility\":10000,\"wind_speed\":5.42,\"wind_deg\":192,\"wind_gust\":6.7,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618146000,\"temp\":15.81,\"feels_like\":14.62,\"pressure\":1024,\"humidity\":45,\"dew_point\":4.15,\"uvi\":2.02,\"clouds\":24,\"visibility\":10000,\"wind_speed\":5.15,\"wind_deg\":193,\"wind_gust\":6.3,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"pop\":0},{\"dt\":1618149600,\"temp\":15.71,\"feels_like\":14.51,\"pressure\":1025,\"humidity\":45,\"dew_point\":3.87,\"uvi\":1.17,\"clouds\":48,\"visibility\":10000,\"wind_speed\":4.79,\"wind_deg\":188,\"wind_gust\":6.01,\"weather\":[{\"id\":802,\"main\":\"Clouds\",\"description\":\"scattered clouds\",\"icon\":\"03d\"}],\"pop\":0},{\"dt\":1618153200,\"temp\":14.79,\"feels_like\":13.63,\"pressure\":1024,\"humidity\":50,\"dew_point\":4.71,\"uvi\":0.53,\"clouds\":63,\"visibility\":10000,\"wind_speed\":3.73,\"wind_deg\":177,\"wind_gust\":6.35,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618156800,\"temp\":12.85,\"feels_like\":11.73,\"pressure\":1024,\"humidity\":59,\"dew_point\":5.18,\"uvi\":0.17,\"clouds\":72,\"visibility\":10000,\"wind_speed\":3.05,\"wind_deg\":159,\"wind_gust\":6.38,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618160400,\"temp\":10.92,\"feels_like\":9.71,\"pressure\":1025,\"humidity\":63,\"dew_point\":4.26,\"uvi\":0,\"clouds\":78,\"visibility\":10000,\"wind_speed\":3.39,\"wind_deg\":152,\"wind_gust\":6.64,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"pop\":0},{\"dt\":1618164000,\"temp\":9.65,\"feels_like\":7.72,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.66,\"uvi\":0,\"clouds\":81,\"visibility\":10000,\"wind_speed\":3.68,\"wind_deg\":148,\"wind_gust\":9.04,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618167600,\"temp\":8.82,\"feels_like\":6.59,\"pressure\":1026,\"humidity\":66,\"dew_point\":3.05,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.92,\"wind_deg\":147,\"wind_gust\":11.02,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618171200,\"temp\":8.07,\"feels_like\":5.87,\"pressure\":1026,\"humidity\":67,\"dew_point\":2.43,\"uvi\":0,\"clouds\":100,\"visibility\":10000,\"wind_speed\":3.54,\"wind_deg\":154,\"wind_gust\":11.12,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618174800,\"temp\":7.24,\"feels_like\":4.99,\"pressure\":1027,\"humidity\":68,\"dew_point\":1.96,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.32,\"wind_deg\":154,\"wind_gust\":10.55,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618178400,\"temp\":6.58,\"feels_like\":4.31,\"pressure\":1027,\"humidity\":70,\"dew_point\":1.65,\"uvi\":0,\"clouds\":98,\"visibility\":10000,\"wind_speed\":3.14,\"wind_deg\":154,\"wind_gust\":9.19,\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618182000,\"temp\":6.03,\"feels_like\":3.57,\"pressure\":1027,\"humidity\":71,\"dew_point\":1.26,\"uvi\":0,\"clouds\":82,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":150,\"wind_gust\":8.44,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618185600,\"temp\":5.51,\"feels_like\":2.94,\"pressure\":1027,\"humidity\":72,\"dew_point\":0.95,\"uvi\":0,\"clouds\":71,\"visibility\":10000,\"wind_speed\":3.26,\"wind_deg\":150,\"wind_gust\":8.58,\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04n\"}],\"pop\":0},{\"dt\":1618189200,\"temp\":5,\"feels_like\":2.29,\"pressure\":1027,\"humidity\":74,\"dew_point\":0.72,\"uvi\":0,\"clouds\":9,\"visibility\":10000,\"wind_speed\":3.3,\"wind_deg\":147,\"wind_gust\":8.63,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"pop\":0},{\"dt\":1618192800,\"temp\":4.47,\"feels_like\":1.69,\"pressure\":1027,\"humidity\":75,\"dew_point\":0.52,\"uvi\":0,\"clouds\":14,\"visibility\":10000,\"wind_speed\":3.25,\"wind_deg\":145,\"wind_gust\":8.14,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618196400,\"temp\":4.03,\"feels_like\":1.08,\"pressure\":1026,\"humidity\":76,\"dew_point\":0.22,\"uvi\":0,\"clouds\":12,\"visibility\":10000,\"wind_speed\":3.36,\"wind_deg\":138,\"wind_gust\":8.13,\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02n\"}],\"pop\":0},{\"dt\":1618200000,\"temp\":4,\"feels_like\":0.9,\"pressure\":1026,\"humidity\":75,\"dew_point\":0.13,\"uvi\":0.08,\"clouds\":10,\"visibility\":10000,\"wind_speed\":3.57,\"wind_deg\":131,\"wind_gust\":9.24,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618203600,\"temp\":5.73,\"feels_like\":2.73,\"pressure\":1026,\"humidity\":68,\"dew_point\":0.52,\"uvi\":0.33,\"clouds\":8,\"visibility\":10000,\"wind_speed\":4.05,\"wind_deg\":138,\"wind_gust\":10.36,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618207200,\"temp\":7.87,\"feels_like\":4.9,\"pressure\":1025,\"humidity\":59,\"dew_point\":0.53,\"uvi\":0.84,\"clouds\":7,\"visibility\":10000,\"wind_speed\":5.05,\"wind_deg\":145,\"wind_gust\":10.48,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618210800,\"temp\":9.9,\"feels_like\":7.29,\"pressure\":1025,\"humidity\":53,\"dew_point\":0.8,\"uvi\":1.56,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.48,\"wind_deg\":147,\"wind_gust\":9.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618214400,\"temp\":11.5,\"feels_like\":9.93,\"pressure\":1025,\"humidity\":47,\"dew_point\":0.86,\"uvi\":2.37,\"clouds\":0,\"visibility\":10000,\"wind_speed\":5.94,\"wind_deg\":152,\"wind_gust\":8.78,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0},{\"dt\":1618218000,\"temp\":12.64,\"feels_like\":11.08,\"pressure\":1024,\"humidity\":43,\"dew_point\":0.68,\"uvi\":3.04,\"clouds\":0,\"visibility\":10000,\"wind_speed\":6.25,\"wind_deg\":151,\"wind_gust\":8.5,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"pop\":0}]}"; + final OneCallCurrentForecastModel currentWeatherData = new ObjectMapper().readValue(jsonString, OneCallCurrentForecastModel.class); assertNotNull(currentWeatherData); assertNull(currentWeatherData.getDailyList()); } @Test - public void mapToCurrent_onlyAlerts() { - final String jsonString = "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"rain\":{\"1h\":20},\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"alerts\":[{\"sender_name\":\"Sender\",\"event\":\"Event\",\"start\":0,\"end\":400,\"description\":\"Description\"}]}"; - final CurrentWeatherData currentWeatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToCurrent(jsonString); + public void mapToCurrent_onlyAlerts() throws JsonProcessingException { + final String jsonString = + "{\"lat\":53.54,\"lon\":27.34,\"timezone\":\"Europe/Minsk\",\"timezone_offset\":10800,\"current\":{\"dt\":1618050045,\"sunrise\":1618024927,\"sunset\":1618074079,\"rain\":{\"1h\":20},\"temp\":11.84,\"feels_like\":10.12,\"pressure\":1018,\"humidity\":40,\"dew_point\":-1.16,\"uvi\":3.36,\"clouds\":0,\"visibility\":10000,\"wind_speed\":9,\"wind_deg\":200,\"wind_gust\":12,\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}]},\"alerts\":[{\"sender_name\":\"Sender\",\"event\":\"Event\",\"start\":0,\"end\":400,\"description\":\"Description\"}]}"; + final OneCallCurrentForecastModel currentWeatherData = new ObjectMapper().readValue(jsonString, OneCallCurrentForecastModel.class); assertNotNull(currentWeatherData); assertNotNull(currentWeatherData.getAlerts()); @@ -88,553 +102,19 @@ public class OneCallWeatherResponseMapperUnitTest { @Test public void mapToHistorical_withInvalidJSON() { - final String jsonString = "{\"lat\":60.99lon\":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,\"clouds\":33,\"wind_speed\":11.04,\"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\":11.14,\"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\"}]}]}"; + final String jsonString = + "{\"lat\":60.99lon\":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,\"clouds\":33,\"wind_speed\":11.04,\"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\":11.14,\"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\"}]}]}"; - assertThrows(RuntimeException.class, () -> new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToHistorical(jsonString)); + assertThrows(JsonParseException.class, () -> new ObjectMapper().readValue(jsonString, HistoricalWeather.class)); } @Test - public void mapToHistorical_withWeatherVariants() { - String jsonString = "{\"lat\":60.99,\"lon\":30.9,\"timezone\":\"Europe/Moscow\",\"timezone_offset\":10800,\"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\":11.14,\"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_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 historicalWeatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToHistorical(jsonString); + public void mapToHistorical_withWeatherVariants() throws IOException { + String jsonString = IOUtils.resourceToString("/responses/valid/onecall-historical.json", StandardCharsets.UTF_8); + HistoricalWeather historicalWeatherData = new ObjectMapper().readValue(jsonString, HistoricalWeather.class); 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_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); - assertNotNull(historicalWeatherData.getHistoricalWeather()); - assertEquals(20000, historicalWeatherData.getHistoricalWeather().getVisibilityInMetres(), 0.00001); + assertNotNull(historicalWeatherData.getData()); + assertEquals(new BigDecimal("20000.00"), historicalWeatherData.getData().get(0).getVisibility().asMeters()); } - - @Test - public void mapToHistorical_withHourlyHistoricalVariants() { - String jsonString = "{\"lat\":60.99,\"lon\":30.9,\"timezone\":\"Europe/Moscow\",\"timezone_offset\":10800,\"current\":{\"dt\":1617739371,\"sunrise\":1617678248,\"sunset\":1617727984,\"temp\":0,\"pressure\":986,\"humidity\":73,\"uvi\":1.69,\"clouds\":33,\"wind_speed\":11.04,\"wind_deg\":196,\"wind_gust\":15.97,\"weather\":[]}}"; - HistoricalWeatherData historicalWeatherData = new OneCallWeatherResponseMapper(UnitSystem.METRIC).mapToHistorical(jsonString); - - assertNotNull(historicalWeatherData); - assertNull(historicalWeatherData.getHourlyList()); - - 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,\"clouds\":33,\"wind_speed\":11.04,\"wind_deg\":196,\"wind_gust\":15.97},\"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,\"visibility\":20000,\"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\":11.14,\"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); - assertNotNull(historicalWeatherData.getHourlyList()); - historicalWeatherData.getHourlyList().forEach(Assertions::assertNotNull); - } -} \ No newline at end of file +} 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 179157d..b58e770 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -24,28 +24,63 @@ package com.github.prominence.openweathermap.api.request.onecall.current; import com.github.prominence.openweathermap.api.ApiTest; import com.github.prominence.openweathermap.api.OpenWeatherMapClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.core.net.HttpClient; 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.model.Coordinates; -import com.github.prominence.openweathermap.api.model.onecall.current.CurrentWeatherData; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.onecall.current.OneCallCurrentForecast; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class CurrentWeatherOneCallIntegrationTest extends ApiTest { + @Test - public void whenRetrieveCurrentOneCallResponseAsJava_thenOk() { - final CurrentWeatherData currentWeatherData = getClient() + public void testBuilder_ShouldGenerateExpectedUrl_whenCalledWithValidData() { + //given + final HttpClient httpClient = mock(HttpClient.class); + final ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + final ApiConfiguration configuration = ApiConfiguration.builder().apiKey("apiKeyValue").httpClient(httpClient).build(); + when(httpClient.executeGetRequest(urlCaptor.capture())).thenReturn("{}"); + + //when + final OneCallCurrentForecast actual = new OpenWeatherMapClient(configuration) .oneCall() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) + .language(Language.ENGLISH) + .exclude(OneCallResultOptions.CURRENT, OneCallResultOptions.MINUTELY) + .retrieve() + .asJava(); + + //then + assertEquals("https://api.openweathermap.org/data/3.0/onecall?mode=json&appid=apiKeyValue&lon=27.34&exclude=current,minutely&units=standard&lang=en&lat=53.54", urlCaptor.getValue()); + } + + @Test + public void whenRetrieveCurrentOneCallResponseAsJava_thenOk() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + Assumptions.assumeTrue(System.getenv(RUN_ONE_CALL) != null, "Skipping one-call API calls."); + final OneCallCurrentForecast currentWeatherData = getClient() + .oneCall() + .current() + .byCoordinates(new Coordinates(53.54, 27.34)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieve() .asJava(); @@ -54,14 +89,15 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { @Test public void whenRetrieveCurrentOneCallResponseAsJSON_thenOk() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + Assumptions.assumeTrue(System.getenv(RUN_ONE_CALL) != null, "Skipping one-call API calls."); final String responseJson = getClient() .oneCall() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieve() - .asJSON(); + .asJSON(UnitSystem.METRIC); assertNotNull(responseJson); assertNotEquals("", responseJson); @@ -70,29 +106,31 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { @Test public void whenRetrieveCurrentOneCallResponseWithExclusionAsJava_thenOk() { - final CurrentWeatherData currentWeatherData = getClient() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + Assumptions.assumeTrue(System.getenv(RUN_ONE_CALL) != null, "Skipping one-call API calls."); + final OneCallCurrentForecast currentWeatherData = getClient() .oneCall() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .exclude(OneCallResultOptions.CURRENT, OneCallResultOptions.MINUTELY) .retrieve() .asJava(); assertNotNull(currentWeatherData); - assertNull(currentWeatherData.getCurrent()); - assertNull(currentWeatherData.getMinutelyList()); + assertNull(currentWeatherData.getCurrentWeather()); + assertNull(currentWeatherData.getMinutelyForecast()); } @Test public void whenRetrieveCurrentOneCallAsyncResponseAsJava_thenOk() throws ExecutionException, InterruptedException { - final CompletableFuture currentWeatherDataFuture = getClient() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + Assumptions.assumeTrue(System.getenv(RUN_ONE_CALL) != null, "Skipping one-call API calls."); + final CompletableFuture currentWeatherDataFuture = getClient() .oneCall() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieveAsync() .asJava(); @@ -102,14 +140,15 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { @Test public void whenRetrieveCurrentOneCallAsyncResponseAsJSON_thenOk() throws ExecutionException, InterruptedException { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + Assumptions.assumeTrue(System.getenv(RUN_ONE_CALL) != null, "Skipping one-call API calls."); final CompletableFuture responseJsonFuture = getClient() .oneCall() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieveAsync() - .asJSON(); + .asJSON(UnitSystem.METRIC); assertNotNull(responseJsonFuture); final String responseJson = responseJsonFuture.get(); @@ -119,16 +158,19 @@ public class CurrentWeatherOneCallIntegrationTest extends ApiTest { @Test public void whenRequestOnecallWithInvalidApiKey_thenThrowAnException() { - OpenWeatherMapClient client = new OpenWeatherMapClient("invalidKey"); + final HttpClient httpClient = mock(HttpClient.class); + when(httpClient.executeGetRequest(anyString())).thenThrow(InvalidAuthTokenException.class); + final OpenWeatherMapClient client = new OpenWeatherMapClient(ApiConfiguration.builder() + .apiKey("invalidKey") + .httpClient(httpClient) + .build()); assertThrows(InvalidAuthTokenException.class, () -> - client - .oneCall() + client.oneCall() .current() - .byCoordinates(Coordinates.of(53.54, 27.34)) + .byCoordinates(new Coordinates(53.54, 27.34)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieve() - .asJSON() + .asJSON(UnitSystem.METRIC) ); } } diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..e17a06c --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherAsyncRequestTerminatorTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021-present 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.onecall.current; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class OneCallCurrentWeatherAsyncRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallCurrentWeatherAsyncRequestTerminator underTest = + new OneCallCurrentWeatherAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asXML(UnitSystem.STANDARD).get()); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallCurrentWeatherAsyncRequestTerminator underTest = + new OneCallCurrentWeatherAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestTerminatorTest.java new file mode 100644 index 0000000..2219fb4 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/current/OneCallCurrentWeatherRequestTerminatorTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021-present 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.onecall.current; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.onecall.current.OneCallCurrentForecastModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class OneCallCurrentWeatherRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallCurrentWeatherRequestTerminator underTest = + new OneCallCurrentWeatherRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asXML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallCurrentWeatherRequestTerminator underTest = + new OneCallCurrentWeatherRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallCurrentWeatherRequestTerminator underTest = + new OneCallCurrentWeatherRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(OneCallCurrentForecastModel.class, actual); + } +} 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 038148f..c065031 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -24,11 +24,14 @@ package com.github.prominence.openweathermap.api.request.onecall.historical; import com.github.prominence.openweathermap.api.ApiTest; import com.github.prominence.openweathermap.api.OpenWeatherMapClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.core.net.HttpClient; 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.model.Coordinates; -import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeatherData; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.onecall.historical.OneCallHistoricalWeather; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; @@ -36,17 +39,23 @@ import java.time.ZoneOffset; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { @Test public void whenRetrieveHistoricalOneCallResponseAsJava_thenOk() { - final HistoricalWeatherData historicalWeatherData = getClient() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + Assumptions.assumeTrue(System.getenv(RUN_ONE_CALL) != null, "Skipping one-call API calls."); + final OneCallHistoricalWeather historicalWeatherData = getClient() .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinates.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(new Coordinates(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieve() .asJava(); @@ -55,14 +64,15 @@ public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { @Test public void whenRetrieveHistoricalOneCallResponseAsJSON_thenOk() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + Assumptions.assumeTrue(System.getenv(RUN_ONE_CALL) != null, "Skipping one-call API calls."); final String responseJson = getClient() .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinates.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(new Coordinates(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieve() - .asJSON(); + .asJSON(UnitSystem.METRIC); assertNotNull(responseJson); assertNotEquals("", responseJson); @@ -71,12 +81,13 @@ public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { @Test public void whenRetrieveHistoricalOneCallAsyncResponseAsJava_thenOk() throws ExecutionException, InterruptedException { - final CompletableFuture historicalWeatherDataFuture = getClient() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + Assumptions.assumeTrue(System.getenv(RUN_ONE_CALL) != null, "Skipping one-call API calls."); + final CompletableFuture historicalWeatherDataFuture = getClient() .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinates.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(new Coordinates(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieveAsync() .asJava(); @@ -86,14 +97,15 @@ public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { @Test public void whenRetrieveHistoricalOneCallAsyncResponseAsJSON_thenOk() throws ExecutionException, InterruptedException { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + Assumptions.assumeTrue(System.getenv(RUN_ONE_CALL) != null, "Skipping one-call API calls."); final CompletableFuture responseJsonFuture = getClient() .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinates.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(new Coordinates(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieveAsync() - .asJSON(); + .asJSON(UnitSystem.METRIC); assertNotNull(responseJsonFuture); final String responseJson = responseJsonFuture.get(); @@ -103,16 +115,21 @@ public class HistoricalWeatherOneCallIntegrationTest extends ApiTest { @Test public void whenRequestOnecallWithInvalidApiKey_thenThrowAnException() { - OpenWeatherMapClient client = new OpenWeatherMapClient("invalidKey"); + final HttpClient httpClient = mock(HttpClient.class); + when(httpClient.executeGetRequest(anyString())).thenThrow(InvalidAuthTokenException.class); + OpenWeatherMapClient client = new OpenWeatherMapClient(ApiConfiguration.builder() + .httpClient(httpClient) + .apiKey("invalidKey") + .build()); assertThrows(InvalidAuthTokenException.class, () -> client .oneCall() .historical() - .byCoordinateAndTimestamp(Coordinates.of(53.54, 27.34), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) + .byCoordinateAndTimestamp(new Coordinates(53.54, 27.34), + LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC)) .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) .retrieve() - .asJSON() + .asJSON(UnitSystem.METRIC) ); } } diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherAsyncRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherAsyncRequestTerminatorTest.java new file mode 100644 index 0000000..b55282f --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherAsyncRequestTerminatorTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021-present 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.onecall.historical; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ExecutionException; + +class OneCallHistoricalWeatherAsyncRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallHistoricalWeatherAsyncRequestTerminator underTest = + new OneCallHistoricalWeatherAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asXML(UnitSystem.STANDARD).get()); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallHistoricalWeatherAsyncRequestTerminator underTest = + new OneCallHistoricalWeatherAsyncRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(ExecutionException.class, () -> underTest.asHTML(UnitSystem.STANDARD).get()); + + //then + exception + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestTerminatorTest.java new file mode 100644 index 0000000..59ba4df --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/onecall/historical/OneCallHistoricalWeatherRequestTerminatorTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021-present 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.onecall.historical; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeather; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class OneCallHistoricalWeatherRequestTerminatorTest { + + @Test + void testAsXML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallHistoricalWeatherRequestTerminator underTest = + new OneCallHistoricalWeatherRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asXML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testAsHTML_ShouldThrowException_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallHistoricalWeatherRequestTerminator underTest = + new OneCallHistoricalWeatherRequestTerminator(requestSettings); + + //when + Assertions.assertThrows(UnsupportedOperationException.class, () -> underTest.asHTML(UnitSystem.STANDARD)); + + //then + exception + } + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final OneCallHistoricalWeatherRequestTerminator underTest = + new OneCallHistoricalWeatherRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(HistoricalWeather.class, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/radiation/RadiationIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/radiation/RadiationIntegrationTest.java new file mode 100644 index 0000000..d247eb6 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/radiation/RadiationIntegrationTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021-present 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.radiation; + +import com.github.prominence.openweathermap.api.OpenWeatherMapClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.core.net.HttpClient; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.radiation.SolarRadiation; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class RadiationIntegrationTest { + + @Test + public void testBuilder_ShouldGenerateExpectedUrl_whenCalledWithValidData() { + //given + final HttpClient httpClient = mock(HttpClient.class); + final ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + final ApiConfiguration configuration = ApiConfiguration.builder().apiKey("apiKeyValue").httpClient(httpClient).build(); + when(httpClient.executeGetRequest(urlCaptor.capture())).thenReturn("{}"); + + //when + final SolarRadiation actual = new OpenWeatherMapClient(configuration) + .solarRadiation() + .current() + .byCoordinates(new Coordinates(53.54, 27.34)) + .retrieve() + .asJava(); + + //then + assertEquals("https://api.openweathermap.org/data/2.5/solar_radiation?mode=json&lon=27.34&units=standard&lat=53.54&appid=apiKeyValue", urlCaptor.getValue()); + } + + @Test + public void testBuilder_ShouldGenerateExpectedHistoricalUrl_whenCalledWithValidData() { + //given + final HttpClient httpClient = mock(HttpClient.class); + final ArgumentCaptor urlCaptor = ArgumentCaptor.forClass(String.class); + final ApiConfiguration configuration = ApiConfiguration.builder().apiKey("apiKeyValue").httpClient(httpClient).build(); + when(httpClient.executeGetRequest(urlCaptor.capture())).thenReturn("{}"); + + //when + final SolarRadiation actual = new OpenWeatherMapClient(configuration) + .solarRadiation() + .historical() + .byCoordinateAndPeriod(new Coordinates(53.54, 27.34), 0, 10) + .retrieve() + .asJava(); + + //then + assertEquals("https://api.openweathermap.org/data/2.5/solar_radiation/history?mode=json&appid=apiKeyValue&start=0&lon=27.34&end=10&units=standard&lat=53.54", urlCaptor.getValue()); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestTerminatorTest.java new file mode 100644 index 0000000..1792980 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/radiation/SolarRadiationRequestTerminatorTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.radiation; + +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.model.radiation.SolarRadiationModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SolarRadiationRequestTerminatorTest { + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final SolarRadiationRequestTerminator underTest = + new SolarRadiationRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(SolarRadiationModel.class, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskIntegrationTest.java index 1f09e0a..988b0d2 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskIntegrationTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskIntegrationTest.java @@ -1,87 +1,96 @@ +/* + * Copyright (c) 2021-present 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.roadrisk; +import com.fasterxml.jackson.databind.ObjectMapper; import com.github.prominence.openweathermap.api.ApiTest; -import com.github.prominence.openweathermap.api.core.net.MockHttpClient; -import com.github.prominence.openweathermap.api.model.Coordinates; -import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskRecord; +import com.github.prominence.openweathermap.api.OpenWeatherMapClient; +import com.github.prominence.openweathermap.api.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.core.net.HttpClient; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRisk; import com.github.prominence.openweathermap.api.model.roadrisk.TrackPoint; -import org.junit.jupiter.api.BeforeAll; +import com.github.prominence.openweathermap.api.request.roadrisk.model.RoadRiskRequestPayload; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; -import java.time.LocalDateTime; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Collections; import java.util.List; -public class RoadRiskIntegrationTest extends ApiTest { - private static final MockHttpClient httpClient = new MockHttpClient(); +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; - @BeforeAll - public static void setup() { - getClient().setHttpClient(httpClient); +public class RoadRiskIntegrationTest extends ApiTest { + @Mock + private HttpClient httpClient; + private AutoCloseable openMocks; + + @BeforeEach + void setUp() { + openMocks = MockitoAnnotations.openMocks(this); + } + + @AfterEach + void tearDown() throws Exception { + if (openMocks != null) { + openMocks.close(); + } } @Test - public void whenGetSingleCurrentWeatherByCoordinateRequestAsJava_thenReturnNotNull() { - final TrackPoint trackPoint = new TrackPoint(); - trackPoint.setCoordinates(Coordinates.of(5, 5)); - trackPoint.setRequestedTime(LocalDateTime.now()); + public void testAsJavaTerminator_ShouldReturnRoadRiskData_WhenCalledWithValidRoadRiskRequest() throws IOException { + //given + final TrackPoint trackPoint = new TrackPoint(5, 5); + trackPoint.setRequestedTime(OffsetDateTime.now(ZoneOffset.UTC)); + final String body = new ObjectMapper().writeValueAsString(new RoadRiskRequestPayload(Collections.singletonList(trackPoint))); - final String responseOutput = """ - [ - { - "dt": 1602702000, - "coord": [ - 7.27, - 44.04 - ], - "weather": { - "temp": 278.44, - "wind_speed": 2.27, - "wind_deg": 7, - "precipitation_intensity": 0.38, - "dew_point": 276.13 - }, - "road": { - "state": 2, - "temp": 293.85 - }, - "alerts": [ - { - "sender_name": "METEO-FRANCE", - "event": "Moderate thunderstorm warning", - "event_level": 2 - } - ] - }, - { - "dt": 1602702400, - "coord": [ - 7.37, - 45.04 - ], - "weather": { - "temp": 282.44, - "wind_speed": 1.84, - "wind_deg": 316, - "dew_point": 275.99 - }, - "road": { - "state": 1, - "temp": 293.85 - }, - "alerts": [ - ] - } - ] - """; - httpClient.setResponseOutput(responseOutput); + final String responseOutput = IOUtils.resourceToString("/responses/valid/road-risk.json", StandardCharsets.UTF_8); + when(httpClient.executePostRequest(anyString(), eq(body))).thenReturn(responseOutput); + final OpenWeatherMapClient client = new OpenWeatherMapClient(ApiConfiguration.builder() + .httpClient(httpClient).apiKey("").build()); - final List roadRiskRecords = getClient() + //when + final List roadRiskRecords = client .roadRisk() - .byTrackPoints(List.of(trackPoint)) + .byTrackPoints(Collections.singletonList(trackPoint)) .retrieve() .asJava(); - System.out.println(roadRiskRecords); + //then + verify(httpClient).executePostRequest(anyString(), eq(body)); + assertNotNull(roadRiskRecords); + assertEquals(2, roadRiskRecords.size()); } } diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherIntegrationTest.java index 96ecf08..26ef4f4 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherIntegrationTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherIntegrationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Alexey Zinchenko + * Copyright (c) 2021-present 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 @@ -23,32 +23,30 @@ 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.conf.TimeoutSettings; import com.github.prominence.openweathermap.api.enums.UnitSystem; -import com.github.prominence.openweathermap.api.model.Coordinates; -import com.github.prominence.openweathermap.api.model.weather.Weather; -import org.junit.jupiter.api.Disabled; +import com.github.prominence.openweathermap.api.model.generic.location.Coordinates; +import com.github.prominence.openweathermap.api.model.weather.CurrentWeather; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - 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() + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); + final CurrentWeather weather = getClient() .currentWeather() - .byCoordinates(Coordinates.of(5, 5)) - .unitSystem(UnitSystem.METRIC) + .withTimeoutSettings(new TimeoutSettings(3000, 3000)) + .byCoordinates(new Coordinates(5, 5)) .retrieve() .asJava(); assertNotNull(weather); assertNotNull(weather.getWeatherStates()); - assertNotNull(weather.getCalculationTime()); + assertNotNull(weather.getForecastTime()); assertNotNull(weather.getTemperature()); assertNotNull(weather.getLocation()); assertNotNull(weather.getAtmosphericPressure()); @@ -59,477 +57,37 @@ public class CurrentWeatherIntegrationTest extends ApiTest { @Test public void whenGetSingleCurrentWeatherByCoordinateRequestAsJSON_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String weatherJson = getClient() .currentWeather() - .byCoordinates(Coordinates.of(5, 5)) - .unitSystem(UnitSystem.METRIC) + .byCoordinates(new Coordinates(5, 5)) .retrieve() - .asJSON(); + .asJSON(UnitSystem.METRIC); assertTrue(weatherJson.startsWith("{")); } @Test public void whenGetSingleCurrentWeatherByCoordinateRequestAsXML_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String weatherXml = getClient() .currentWeather() - .byCoordinates(Coordinates.of(5, 5)) - .unitSystem(UnitSystem.METRIC) + .byCoordinates(new Coordinates(5, 5)) .retrieve() - .asXML(); + .asXML(UnitSystem.METRIC); assertTrue(weatherXml.startsWith("<")); } @Test public void whenGetSingleCurrentWeatherByCoordinateRequestAsHTML_thenReturnNotNull() { + Assumptions.assumeTrue(System.getenv(OPENWEATHER_API_KEY) != null, "Api key is not set, skip."); final String weatherHtml = getClient() .currentWeather() - .byCoordinates(Coordinates.of(5, 5)) - .unitSystem(UnitSystem.METRIC) + .byCoordinates(new Coordinates(5, 5)) .retrieve() - .asHTML(); + .asHTML(UnitSystem.METRIC); assertTrue(weatherHtml.startsWith("<")); } - - @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() - .byZipCodeAndCountry("220015", "by") - .language(Language.ENGLISH) - .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 whenGetSingleCurrentWeatherByZipCodeAndCountryRequestAsJSON_thenReturnNotNull() { - final String weatherJson = getClient() - .currentWeather() - .byZipCodeAndCountry("220015", "by") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asJSON(); - - assertTrue(weatherJson.startsWith("{")); - } - - @Test - @Disabled - public void whenGetSingleCurrentWeatherByZipCodeAndCountryRequestAsXML_thenReturnNotNull() { - final String weatherXml = getClient() - .currentWeather() - .byZipCodeAndCountry("220015", "by") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asXML(); - - assertTrue(weatherXml.startsWith("<")); - } - - @Test - @Disabled - public void whenGetSingleCurrentWeatherByZipCodeAndCountryRequestAsHTML_thenReturnNotNull() { - final String weatherHtml = getClient() - .currentWeather() - .byZipCodeAndCountry("220015", "by") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asHTML(); - - assertTrue(weatherHtml.startsWith("<")); - } - - @Test - @Disabled - public void whenGetSingleCurrentWeatherByZipCodeInUSARequestAsJava_thenReturnNotNull() { - final Weather weather = getClient() - .currentWeather() - .byZipCodeInUSA("10006") - .language(Language.ENGLISH) - .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 whenGetSingleCurrentWeatherByZipCodeInUSARequestAsJSON_thenReturnNotNull() { - final String weatherJson = getClient() - .currentWeather() - .byZipCodeInUSA("10006") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asJSON(); - - assertTrue(weatherJson.startsWith("{")); - } - - @Test - @Disabled - public void whenGetSingleCurrentWeatherByZipCodeInUSARequestAsXML_thenReturnNotNull() { - final String weatherXml = getClient() - .currentWeather() - .byZipCodeInUSA("10006") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asXML(); - - assertTrue(weatherXml.startsWith("<")); - } - - @Test - @Disabled - public void whenGetSingleCurrentWeatherByZipCodeInUSARequestAsHTML_thenReturnNotNull() { - final String weatherHtml = getClient() - .currentWeather() - .byZipCodeInUSA("10006") - .language(Language.ENGLISH) - .unitSystem(UnitSystem.METRIC) - .retrieve() - .asHTML(); - - assertTrue(weatherHtml.startsWith("<")); - } - - @Test - @Disabled - public void whenGetAnySingleCurrentWeatherAsyncRequestAsJava_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture weatherFuture = getClient() - .currentWeather() - .byZipCodeAndCountry("220015", "by") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.METRIC) - .retrieveAsync() - .asJava(); - - assertNotNull(weatherFuture); - System.out.println(weatherFuture.get()); - } - - @Test - @Disabled - public void whenGetAnySingleCurrentWeatherAsyncRequestAsJson_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture weatherFuture = getClient() - .currentWeather() - .byZipCodeAndCountry("220015", "by") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.METRIC) - .retrieveAsync() - .asJSON(); - - assertNotNull(weatherFuture); - System.out.println(weatherFuture.get()); - } - - @Test - @Disabled - public void whenGetAnySingleCurrentWeatherAsyncRequestAsXml_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture weatherXmlFuture = getClient() - .currentWeather() - .byZipCodeAndCountry("220015", "by") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.METRIC) - .retrieveAsync() - .asXML(); - - assertNotNull(weatherXmlFuture); - System.out.println(weatherXmlFuture.get()); - } - - @Test - @Disabled - public void whenGetAnySingleCurrentWeatherAsyncRequestAsHtml_thenReturnNotNull() throws ExecutionException, InterruptedException { - final CompletableFuture weatherFuture = getClient() - .currentWeather() - .byZipCodeAndCountry("220015", "by") - .language(Language.RUSSIAN) - .unitSystem(UnitSystem.METRIC) - .retrieveAsync() - .asHTML(); - - assertNotNull(weatherFuture); - System.out.println(weatherFuture.get()); - } } diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminatorTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminatorTest.java new file mode 100644 index 0000000..c77d5d4 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherRequestTerminatorTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-present 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.context.ApiConfiguration; +import com.github.prominence.openweathermap.api.model.weather.CurrentWeatherModel; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CurrentWeatherRequestTerminatorTest { + + @Test + void testGetValueType_ShouldReturnExpectedClass_WhenCalled() { + //given + final RequestSettings requestSettings = new RequestSettings(ApiConfiguration.builder().apiKey("-").build()); + final CurrentWeatherRequestTerminator underTest = + new CurrentWeatherRequestTerminator(requestSettings); + + //when + final Class actual = underTest.getValueType(); + + //then + assertEquals(CurrentWeatherModel.class, actual); + } +} diff --git a/src/test/java/com/github/prominence/openweathermap/api/utils/TestMappingUtils.java b/src/test/java/com/github/prominence/openweathermap/api/utils/TestMappingUtils.java deleted file mode 100644 index 478dbef..0000000 --- a/src/test/java/com/github/prominence/openweathermap/api/utils/TestMappingUtils.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.github.prominence.openweathermap.api.utils; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.util.TimeZone; - -public class TestMappingUtils { - - public static LocalDateTime parseDateTime(int seconds) { - return LocalDateTime.ofInstant(Instant.ofEpochSecond(seconds), TimeZone.getDefault().toZoneId()); - } -} diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..4ebf4c0 --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,34 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n%ex{3} + + + + + + diff --git a/src/test/resources/responses/invalid/current-weather-minsk-invalid.json b/src/test/resources/responses/invalid/current-weather-minsk-invalid.json new file mode 100644 index 0000000..5b31910 --- /dev/null +++ b/src/test/resources/responses/invalid/current-weather-minsk-invalid.json @@ -0,0 +1,46 @@ +{ + "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 +} diff --git a/src/test/resources/responses/valid/16days-daily.json b/src/test/resources/responses/valid/16days-daily.json new file mode 100644 index 0000000..effc997 --- /dev/null +++ b/src/test/resources/responses/valid/16days-daily.json @@ -0,0 +1,54 @@ +{ + "city": { + "id": 2643743, + "name": "London", + "coord": { + "lon": -0.1258, + "lat": 51.5085 + }, + "country": "GB", + "population": 0, + "timezone": 3600 + }, + "cod": "200", + "message": 0.7809187, + "cnt": 1, + "list": [ + { + "dt": 1568977200, + "sunrise": 1568958164, + "sunset": 1569002733, + "temp": { + "day": 293.79, + "min": 288.85, + "max": 294.47, + "night": 288.85, + "eve": 290.44, + "morn": 293.79 + }, + "feels_like": { + "day": 278.87, + "night": 282.73, + "eve": 281.92, + "morn": 278.87 + }, + "pressure": 1025.04, + "humidity": 42, + "weather": [ + { + "id": 800, + "main": "Clear", + "description": "sky is clear", + "icon": "01d" + } + ], + "speed": 4.66, + "deg": 102, + "gust": 5.3, + "clouds": 0, + "pop": 0.24, + "rain": 22.2, + "snow": 24.2 + } + ] +} diff --git a/src/test/resources/responses/valid/5days3hours.json b/src/test/resources/responses/valid/5days3hours.json new file mode 100644 index 0000000..0be2481 --- /dev/null +++ b/src/test/resources/responses/valid/5days3hours.json @@ -0,0 +1,98 @@ +{ + "cod": "200", + "message": 0, + "cnt": 40, + "list": [ + { + "dt": 1647345600, + "main": { + "temp": 286.88, + "feels_like": 285.93, + "temp_min": 286.74, + "temp_max": 286.88, + "pressure": 1021, + "sea_level": 1021, + "grnd_level": 1018, + "humidity": 62, + "temp_kf": 0.14 + }, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ], + "clouds": { + "all": 85 + }, + "wind": { + "speed": 3.25, + "deg": 134, + "gust": 4.45 + }, + "visibility": 10000, + "pop": 0, + "sys": { + "pod": "d" + }, + "rain": { + "3h": 22.1 + }, + "snow": { + "3h": 13.6 + }, + "dt_txt": "2022-03-15 12:00:00" + }, + { + "dt": 1647356400, + "main": { + "temp": 286.71, + "feels_like": 285.77, + "temp_min": 286.38, + "temp_max": 286.71, + "pressure": 1021, + "sea_level": 1021, + "grnd_level": 1017, + "humidity": 63, + "temp_kf": 0.33 + }, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ], + "clouds": { + "all": 90 + }, + "wind": { + "speed": 3.34, + "deg": 172, + "gust": 4.03 + }, + "visibility": 10000, + "pop": 0, + "sys": { + "pod": "d" + }, + "dt_txt": "2022-03-15 15:00:00" + } + ], + "city": { + "id": 2643743, + "name": "London", + "coord": { + "lat": 51.5073, + "lon": -0.1277 + }, + "country": "GB", + "population": 1000000, + "timezone": 0, + "sunrise": 1647324903, + "sunset": 1647367441 + } +} diff --git a/src/test/resources/responses/valid/climatic.json b/src/test/resources/responses/valid/climatic.json new file mode 100644 index 0000000..3e94fba --- /dev/null +++ b/src/test/resources/responses/valid/climatic.json @@ -0,0 +1,49 @@ +{ + "cod": "200", + "city": { + "id": 2643743, + "name": "London", + "coord": { + "lon": -0.1277, + "lat": 51.5073 + }, + "country": "GB" + }, + "message": 0.353472054, + "list": [ + { + "dt": 1594382400, + "sunrise": 1594353335, + "sunset": 1594412149, + "temp": { + "day": 286.98, + "min": 285.22, + "max": 287.97, + "night": 285.22, + "eve": 287.97, + "morn": 287.29 + }, + "feels_like": { + "day": 282.61, + "night": 283.19, + "eve": 284.98, + "morn": 282.68 + }, + "pressure": 1016, + "humidity": 84, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "speed": 6.78, + "deg": 320, + "clouds": 81, + "rain": 1.96, + "snow": 2.21 + } + ] +} diff --git a/src/test/resources/responses/valid/current-weather-minsk-missing-1h.json b/src/test/resources/responses/valid/current-weather-minsk-missing-1h.json new file mode 100644 index 0000000..834e5cf --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk-missing-1h.json @@ -0,0 +1,49 @@ +{ + "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.6 + }, + "snow": { + "3h": 0.7 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 +} diff --git a/src/test/resources/responses/valid/current-weather-minsk-missing-3h.json b/src/test/resources/responses/valid/current-weather-minsk-missing-3h.json new file mode 100644 index 0000000..7880fb0 --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk-missing-3h.json @@ -0,0 +1,49 @@ +{ + "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 + }, + "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 +} diff --git a/src/test/resources/responses/valid/current-weather-minsk-missing-coord-and-country.json b/src/test/resources/responses/valid/current-weather-minsk-missing-coord-and-country.json new file mode 100644 index 0000000..4b6d817 --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk-missing-coord-and-country.json @@ -0,0 +1,41 @@ +{ + "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, + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 +} diff --git a/src/test/resources/responses/valid/current-weather-minsk-missing-dt.json b/src/test/resources/responses/valid/current-weather-minsk-missing-dt.json new file mode 100644 index 0000000..45d9f78 --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk-missing-dt.json @@ -0,0 +1,45 @@ +{ + "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 +} diff --git a/src/test/resources/responses/valid/current-weather-minsk-missing-feelslike.json b/src/test/resources/responses/valid/current-weather-minsk-missing-feelslike.json new file mode 100644 index 0000000..33e48bc --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk-missing-feelslike.json @@ -0,0 +1,45 @@ +{ + "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 +} diff --git a/src/test/resources/responses/valid/current-weather-minsk-missing-gust.json b/src/test/resources/responses/valid/current-weather-minsk-missing-gust.json new file mode 100644 index 0000000..6baf39a --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk-missing-gust.json @@ -0,0 +1,51 @@ +{ + "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.6 + }, + "snow": { + "1h": 0.2, + "3h": 0.7 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 +} diff --git a/src/test/resources/responses/valid/current-weather-minsk-missing-maxtemp.json b/src/test/resources/responses/valid/current-weather-minsk-missing-maxtemp.json new file mode 100644 index 0000000..ab69611 --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk-missing-maxtemp.json @@ -0,0 +1,45 @@ +{ + "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 +} diff --git a/src/test/resources/responses/valid/current-weather-minsk-missing-mintemp.json b/src/test/resources/responses/valid/current-weather-minsk-missing-mintemp.json new file mode 100644 index 0000000..68620f3 --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk-missing-mintemp.json @@ -0,0 +1,45 @@ +{ + "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 +} diff --git a/src/test/resources/responses/valid/current-weather-minsk-missing-wind-direction.json b/src/test/resources/responses/valid/current-weather-minsk-missing-wind-direction.json new file mode 100644 index 0000000..de12d5d --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk-missing-wind-direction.json @@ -0,0 +1,51 @@ +{ + "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, + "gust": 2.44 + }, + "rain": { + "1h": 0.1, + "3h": 0.6 + }, + "snow": { + "1h": 0.2, + "3h": 0.7 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 +} diff --git a/src/test/resources/responses/valid/current-weather-minsk.json b/src/test/resources/responses/valid/current-weather-minsk.json new file mode 100644 index 0000000..1315fae --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-minsk.json @@ -0,0 +1,52 @@ +{ + "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, + "gust": 2.44, + "deg": 250 + }, + "rain": { + "1h": 0.1, + "3h": 0.6 + }, + "snow": { + "1h": 0.2, + "3h": 0.7 + }, + "clouds": { + "all": 75 + }, + "dt": 1617746826, + "sys": { + "type": 1, + "id": 8939, + "country": "BY", + "sunrise": 1617766068, + "sunset": 1617814530 + }, + "timezone": 10800, + "id": 0, + "name": "Minsk", + "cod": 200 +} diff --git a/src/test/resources/responses/valid/current-weather-official.json b/src/test/resources/responses/valid/current-weather-official.json new file mode 100644 index 0000000..42208bf --- /dev/null +++ b/src/test/resources/responses/valid/current-weather-official.json @@ -0,0 +1,44 @@ +{ + "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 +} diff --git a/src/test/resources/responses/valid/geocoding-reverse.json b/src/test/resources/responses/valid/geocoding-reverse.json new file mode 100644 index 0000000..0bcd40b --- /dev/null +++ b/src/test/resources/responses/valid/geocoding-reverse.json @@ -0,0 +1,133 @@ +[ + { + "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" + } +] diff --git a/src/test/resources/responses/valid/geocoding-zipcode.json b/src/test/resources/responses/valid/geocoding-zipcode.json new file mode 100644 index 0000000..25399ac --- /dev/null +++ b/src/test/resources/responses/valid/geocoding-zipcode.json @@ -0,0 +1,7 @@ +{ + "zip": "90210", + "name": "Beverly Hills", + "lat": 34.0901, + "lon": -118.4065, + "country": "US" +} diff --git a/src/test/resources/responses/valid/hourly-forecast.json b/src/test/resources/responses/valid/hourly-forecast.json new file mode 100644 index 0000000..935a28a --- /dev/null +++ b/src/test/resources/responses/valid/hourly-forecast.json @@ -0,0 +1,61 @@ +{ + "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 + } +} diff --git a/src/test/resources/responses/valid/onecall-current.json b/src/test/resources/responses/valid/onecall-current.json new file mode 100644 index 0000000..b933d62 --- /dev/null +++ b/src/test/resources/responses/valid/onecall-current.json @@ -0,0 +1,116 @@ +{ + "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" + ] + } + ] +} diff --git a/src/test/resources/responses/valid/onecall-historical.json b/src/test/resources/responses/valid/onecall-historical.json new file mode 100644 index 0000000..3655d4b --- /dev/null +++ b/src/test/resources/responses/valid/onecall-historical.json @@ -0,0 +1,469 @@ +{ + "lat": 60.99, + "lon": 30.9, + "timezone": "Europe/Moscow", + "timezone_offset": 10800, + "data": [ + { + "dt": 1617670800, + "temp": 0.22, + "feels_like": -7.76, + "pressure": 988, + "humidity": 80, + "dew_point": -2.49, + "clouds": 100, + "visibility": 20000, + "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" + } + ] + } + ] +} diff --git a/src/test/resources/responses/valid/road-risk.json b/src/test/resources/responses/valid/road-risk.json new file mode 100644 index 0000000..230aba6 --- /dev/null +++ b/src/test/resources/responses/valid/road-risk.json @@ -0,0 +1,46 @@ +[ + { + "dt": 1602702000, + "coord": [ + 7.27, + 44.04 + ], + "weather": { + "temp": 278.44, + "wind_speed": 2.27, + "wind_deg": 7, + "precipitation_intensity": 0.38, + "dew_point": 276.13 + }, + "road": { + "state": 2, + "temp": 293.85 + }, + "alerts": [ + { + "sender_name": "METEO-FRANCE", + "event": "Moderate thunderstorm warning", + "event_level": 2 + } + ] + }, + { + "dt": 1602702400, + "coord": [ + 7.37, + 45.04 + ], + "weather": { + "temp": 282.44, + "wind_speed": 1.84, + "wind_deg": 316, + "dew_point": 275.99 + }, + "road": { + "state": 1, + "temp": 293.85 + }, + "alerts": [ + ] + } +] diff --git a/src/test/resources/responses/valid/solar-radiation.json b/src/test/resources/responses/valid/solar-radiation.json new file mode 100644 index 0000000..1e9b9e9 --- /dev/null +++ b/src/test/resources/responses/valid/solar-radiation.json @@ -0,0 +1,19 @@ +{ + "coord": { + "lon": -114.6244, + "lat": 32.7243 + }, + "list": [ + { + "radiation": { + "ghi": 206.68, + "dni": 2.27, + "dhi": 204.83, + "ghi_cs": 826.71, + "dni_cs": 885.47, + "dhi_cs": 114.93 + }, + "dt": 1618232400 + } + ] +}