diff --git a/README.md b/README.md
index cff7f90..9584326 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,11 @@ Free:
* Current weather data
* 5 day / 3-hour forecast
* One Call API
+* Air pollution
### Will be implemented later:
Free:
-* Air pollution
* Geocoding API
* Weather Stations
* Weather Triggers
@@ -26,14 +26,14 @@ Paid:
com.github.prominence
openweathermap-api
- 2.1.1
+ 2.2.0
```
### Gradle coordinates:
```groovy
-compile('com.github.prominence:openweathermap-api:2.1.1')
+compile('com.github.prominence:openweathermap-api:2.2.0')
```
### Documentation
@@ -44,6 +44,7 @@ compile('com.github.prominence:openweathermap-api:2.1.1')
* [OpenWeatherMap Java API - 2.0.1](docs/Release_2.0.1.md)
* [OpenWeatherMap Java API - 2.1.0](docs/Release_2.1.0.md)
* [OpenWeatherMap Java API - 2.1.1](docs/Release_2.1.1.md)
+* [OpenWeatherMap Java API - 2.2.0](docs/Release_2.2.0.md)
* [OpenWeatherMap Java API - SNAPSHOT](docs/SNAPSHOT.md)
### License
diff --git a/docs/Release_2.2.0.md b/docs/Release_2.2.0.md
new file mode 100644
index 0000000..5d4495f
--- /dev/null
+++ b/docs/Release_2.2.0.md
@@ -0,0 +1,538 @@
+### Implemented features:
+* Current weather data
+* 5 day / 3-hour forecast
+* One Call API
+* Air Pollution
+
+### Maven coordinates:
+
+```xml
+
+ com.github.prominence
+ openweathermap-api
+ 2.2.0
+
+```
+
+### Gradle coordinates:
+
+```groovy
+compile('com.github.prominence:openweathermap-api:2.2.0')
+```
+
+### How to use:
+
+Firstly, you need to create the instance of `OpenWeatherMapClient` class:
+```java
+OpenWeatherMapClient openWeatherClient = new OpenWeatherMapClient(API_TOKEN);
+```
+where `API_TOKEN` is your token([you can get it here](https://home.openweathermap.org/api_keys)) as `String`.
+
+Currently, available APIs are:
+* `currentWeather()`
+* `forecast5Day3HourStep()`
+* `oneCall()`
+* `airPollution()`
+
+Default(more or less) customization points:
+```java
+...
+// response language
+.language(Language.RUSSIAN)
+...
+// response units of measure
+.unitSystem(UnitSystem.IMPERIAL)
+...
+```
+
+Available output forms:
+* `asJava()`
+* `asJSON()`
+
+Additional output forms, available for several APIs:
+* `asXML()`
+* `asHTML()`
+
+_All response forms can be in **sync** and **async** variants._
+
+#### Current weather data
+Examples:
+```java
+final String weatherJson = openWeatherClient
+ .currentWeather()
+ .single()
+ .byCityName("Minsk")
+ .language(Language.RUSSIAN)
+ .unitSystem(UnitSystem.IMPERIAL)
+ .retrieve()
+ .asJSON();
+```
+
+```java
+final Weather weather = openWeatherClient
+ .currentWeather()
+ .single()
+ .byCityName("Minsk")
+ .language(Language.RUSSIAN)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieve()
+ .asJava();
+```
+
+```java
+final List weatherList = openWeatherClient
+ .currentWeather()
+ .multiple()
+ .byCitiesInCycle(Coordinate.of(55.5, 37.5))
+ .language(Language.GERMAN)
+ .unitSystem(UnitSystem.IMPERIAL)
+ .retrieve()
+ .asJava();
+```
+
+```java
+final CompletableFuture weatherXmlFuture = openWeatherClient
+ .currentWeather()
+ .single()
+ .byZipCodeAndCountry("220015", "by")
+ .language(Language.RUSSIAN)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieveAsync()
+ .asXML();
+```
+
+You are able to set preferable options(via chain methods) and execute appropriate request.
+
+`com.github.prominence.openweathermap.api.model.weather.Weather`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `getCalculationTime()` | Returns `LocalDateTime` object with data calculation time. |
+| `getWeatherState()` | Returns `WeatherState` object with basic weather state information. |
+| `getTemperature()` | Returns `Temperature` instance that contains information about temperature. Available fields: `value`, `maxTemperature`, `minTemperature`, `feelsLike` and `unit`. |
+| `getAtmosphericPressure()`| Returns `AtmosphericPressure` instance that contains information about atmospheric pressure. Available fields: `value`, `seaLevelValue`, `groundLevelValue` and `unit`. |
+| `getHumidity()` | Returns `Humidity` instance that contains humidity percentage information. |
+| `getWind()` | Returns `Wind` instance that contains wind information: `speed`, `degrees`, `gust` and `unit`. |
+| `getRain()` | Returns `Rain` instance that contains information about rain volume for the last one hour and/or the last 3 hours. Can be absent in case of no data. |
+| `getSnow()` | Returns `Snow` instance that contains information about snow volume for the last one hour and/or the last 3 hours. Can be absent in case of no data. |
+| `getClouds()` | Returns `Clouds` instance that contains information about cloudiness percentage. |
+| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset` and `coordinate`. |
+| `toString()` | Returns informative string for the whole available weather information. |
+
+`toString()` output example:
+```
+Location: Minsk(BY), Weather: clear sky, -4.22 ℃, 1020.0 hPa, Clouds: 0%
+```
+
+#### 5 day / 3-hour forecast
+Examples:
+```java
+final Forecast forecast = openWeatherClient
+ .forecast5Day3HourStep()
+ .byCityName("Minsk")
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .count(15)
+ .retrieve()
+ .asJava();
+```
+
+```java
+final String forecastJson = getClient()
+ .forecast5Day3HourStep()
+ .byCityName("New York", "NY", "US")
+ .language(Language.SPANISH)
+ .unitSystem(UnitSystem.IMPERIAL)
+ .count(15)
+ .retrieve()
+ .asJSON();
+```
+
+```java
+CompletableFuture forecastFuture = getClient()
+ .forecast5Day3HourStep()
+ .byCityId(350001514)
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .count(15)
+ .retrieveAsync()
+ .asXML();
+```
+
+```java
+final String forecastXml = getClient()
+ .forecast5Day3HourStep()
+ .byZipCodeInUSA("10005")
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieve()
+ .asXML();
+```
+
+You are able to set preferable options(via chain methods) and execute appropriate request.
+
+`com.github.prominence.openweathermap.api.model.forecast.free.Forecast`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset`, `coordinate` and `population`. |
+| `getWeatherForecasts()` | Returns list of `WeatherForecast` objects with forecast information. |
+| `toString()` | Returns informative string for the whole available forecast information. |
+
+`toString()` output example:
+```
+A forecast for Minsk with 15 timestamps.
+```
+
+`com.github.prominence.openweathermap.api.model.forecast.WeatherForecast`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `getForecastTime()` | Returns `LocalDateTime` object with weather forecast time. |
+| `getWeatherState()` | Returns `WeatherState` object with basic weather state information. |
+| `getTemperature()` | Returns `Temperature` instance that contains information about temperature. Available fields: `value`, `maxTemperature`, `minTemperature`, `feelsLike` and `unit`. |
+| `getAtmosphericPressure()` | Returns `AtmosphericPressure` instance that contains information about atmospheric pressure. Available fields: `value`, `seaLevelValue`, `groundLevelValue` and `unit`. |
+| `getHumidity()` | Returns `Humidity` instance that contains humidity percentage information. |
+| `getWind()` | Returns `Wind` instance that contains wind information: `speed`, `degrees` and `unit`. |
+| `getRain()` | Returns `Rain` instance that contains information about rain volume for the last 3 hours. Can be absent in case of no data. |
+| `getSnow()` | Returns `Snow` instance that contains information about snow volume for the last 3 hours. Can be absent in case of no data. |
+| `getClouds()` | Returns `Clouds` instance that contains information about cloudiness percentage. |
+| `getForecastTimeISO()` | Returns String with time of data forecasted, ISO, UTC. |
+| `getDayTime()` | Returns enumerations representing the part of day(day, night). |
+| `toString()` | Returns informative string for the forecast of particular timestamp. |
+
+#### One Call API
+Examples:
+```java
+final CurrentWeatherData currentWeatherData = openWeatherClient
+ .oneCall()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieve()
+ .asJava();
+```
+
+```java
+final CurrentWeatherData currentWeatherData = openWeatherClient
+ .oneCall()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .exclude(OneCallResultOptions.CURRENT, OneCallResultOptions.MINUTELY)
+ .retrieve()
+ .asJava();
+```
+
+```java
+final CompletableFuture currentWeatherDataFuture = openWeatherClient
+ .oneCall()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieveAsync()
+ .asJava();
+```
+
+```java
+final String responseJson = openWeatherClient
+ .oneCall()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieve()
+ .asJSON();
+```
+
+```java
+final HistoricalWeatherData historicalWeatherData = openWeatherClient
+ .oneCall()
+ .historical()
+ .byCoordinateAndTimestamp(Coordinate.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC))
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieve()
+ .asJava();
+```
+
+```java
+final String responseJson = openWeatherClient
+ .oneCall()
+ .historical()
+ .byCoordinateAndTimestamp(Coordinate.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC))
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieve()
+ .asJSON();
+```
+
+```java
+final CompletableFuture historicalWeatherDataFuture = openWeatherClient
+ .oneCall()
+ .historical()
+ .byCoordinateAndTimestamp(Coordinate.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC))
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieveAsync()
+ .asJava();
+```
+
+```java
+final CompletableFuture responseJsonFuture = openWeatherClient
+ .oneCall()
+ .historical()
+ .byCoordinateAndTimestamp(Coordinate.of(60.99, 30.9), LocalDateTime.now().minusDays(5).toEpochSecond(ZoneOffset.UTC))
+ .language(Language.ENGLISH)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieveAsync()
+ .asJSON();
+```
+
+You are able to set preferable options(via chain methods) and execute appropriate request.
+
+`com.github.prominence.openweathermap.api.model.onecall.current.CurrentWeatherData`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|--------------------------------------------------------------------------------|
+| `getCoordinate()` | Returns `Coordinate` object. Available fields: `latitude`, `longitude`. |
+| `getTimezone()` | Returns location timezone object. |
+| `getTimezoneOffset()` | Returns zone offset. |
+| `getCurrent()` | Returns `Current` object with current weather state if available. |
+| `getMinutelyList()` | Returns list of `Minutely` objects if available. |
+| `getHourlyList()` | Returns list of `Houlry` objects if available. |
+| `getDailyList()` | Returns list of `Daily` objects if available. |
+| `getAlerts()` | Returns list of `Alert` objects if available. |
+
+`com.github.prominence.openweathermap.api.model.onecall.Current`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|-------------------------------------------------------------------------------------------------|
+| `getForecastTime()` | Returns `LocalDateTime` object with weather forecast time. |
+| `getSunriseTime()` | Returns `LocalDateTime` object with sunrise time. |
+| `getSunsetTime()` | Returns `LocalDateTime` object with sunset time. |
+| `getWeatherState()` | Returns `WeatherState` object with basic weather state information. |
+| `getTemperature()` | Returns `Temperature` object. Available fields: `value`, `feelsLike`, `dewPoint` and `unit`. |
+| `getAtmosphericPressure()` | Returns `AtmosphericPressure` object. Available fields: `seaLevelValue`. |
+| `getHumidity()` | Returns `Humidity` object. Available fields: `value` and `unit`. |
+| `getClouds()` | Returns `Clouds` object. Available fields: `value` and `unit`. |
+| `getUvIndex()` | Returns UV index value. |
+| `getVisibilityInMetres()` | Returns visibility in metres. |
+| `getWind()` | Returns `Wind` object. Available fields: `speed`, `degrees`, `gust` and `unit`. |
+| `getRain()` | Returns `Rain` object. Available fields: `oneHourLevel` and `unit`. |
+| `getSnow()` | Returns `Snow` object. Available fields: `oneHourLevel` and `unit`. |
+
+`com.github.prominence.openweathermap.api.model.onecall.current.Minutely`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|---------------------------------------------------------------|
+| `getForecastTime()` | Returns `LocalDateTime` object with weather forecast time. |
+| `getPrecipitationVolume()` | Returns precipitation volume. |
+
+`com.github.prominence.openweathermap.api.model.onecall.current.Hourly`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-----------------------------------------------|---------------------------------------------------------------------------------------------------|
+| `getForecastTime()` | Returns `LocalDateTime` object with weather forecast time. |
+| `getWeatherState()` | Returns `WeatherState` object with basic weather state information. |
+| `getTemperature()` | Returns `Temperature` object. Available fields: `value`, `feelsLike`, `dewPoint` and `unit`. |
+| `getAtmosphericPressure()` | Returns `AtmosphericPressure` object. Available fields: `seaLevelValue`. |
+| `getHumidity()` | Returns `Humidity` object. Available fields: `value` and `unit`. |
+| `getClouds()` | Returns `Clouds` object. Available fields: `value` and `unit`. |
+| `getUvIndex()` | Returns UV index value. |
+| `getVisibilityInMetres()` | Returns visibility in metres. |
+| `getWind()` | Returns `Wind` object. Available fields: `speed`, `degrees`, `gust` and `unit`. |
+| `getProbabilityOfPrecipitation()` | Returns probability of precipitation(not percentage). |
+| `getProbabilityOfPrecipitationPercentage()` | Returns probability of precipitation percentage. |
+| `getRain()` | Returns `Rain` object. Available fields: `oneHourLevel` and `unit`. |
+| `getSnow()` | Returns `Snow` object. Available fields: `oneHourLevel` and `unit`. |
+
+`com.github.prominence.openweathermap.api.model.onecall.current.Daily`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-----------------------------------------------|---------------------------------------------------------------------------------------------------|
+| `getForecastTime()` | Returns `LocalDateTime` object with weather forecast time. |
+| `getSunriseTime()` | Returns `LocalDateTime` object with sunrise time. |
+| `getSunsetTime()` | Returns `LocalDateTime` object with sunset time. |
+| `getWeatherState()` | Returns `WeatherState` object with basic weather state information. |
+| `getTemperature()` | Returns `DailyTemperature` object. Available fields: `value`, `feelsLike`, `dewPoint` and `unit`. |
+| `getAtmosphericPressure()` | Returns `AtmosphericPressure` object. Available fields: `seaLevelValue`. |
+| `getHumidity()` | Returns `Humidity` object. Available fields: `value` and `unit`. |
+| `getWind()` | Returns `Wind` object. Available fields: `speed`, `degrees`, `gust` and `unit`. |
+| `getClouds()` | Returns `Clouds` object. Available fields: `value` and `unit`. |
+| `getUvIndex()` | Returns UV index value. |
+| `getProbabilityOfPrecipitation()` | Returns probability of precipitation(not percentage). |
+| `getProbabilityOfPrecipitationPercentage()` | Returns probability of precipitation percentage. |
+| `getRain()` | Returns `DailyRain` object. Available fields: `value`. |
+| `getSnow()` | Returns `DailySnow` object. Available fields: `value`. |
+
+`com.github.prominence.openweathermap.api.model.onecall.current.Alert`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|------------------------------|--------------------------------------------------------|
+| `getSenderName()` | Returns alert sender name. |
+| `getEventName()` | Returns alert event name. |
+| `getStartTime()` | Returns `LocalDateTime` when event should start. |
+| `getEndTime()` | Returns `LocalDateTime` when event should end. |
+| `getDescription()` | Returns alert description. |
+
+`com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeatherData`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|-------------------------------------------------------------------------------|
+| `getCoordinate()` | Returns `Coordinate` object. Available fields: `latitude`, `longitude`. |
+| `getTimezone()` | Returns location timezone object. |
+| `getTimezoneOffset()` | Returns zone offset. |
+| `getHistoricalWeather()` | Returns `HistoricalWeather` object with historical weather state. |
+| `getHourlyList()` | Returns list of `HourlyHistorical` objects. |
+
+`com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeather`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|-------------------------------------------------------------------------------------------------|
+| `getForecastTime()` | Returns `LocalDateTime` object with weather forecast time. |
+| `getSunriseTime()` | Returns `LocalDateTime` object with sunrise time. |
+| `getSunsetTime()` | Returns `LocalDateTime` object with sunset time. |
+| `getWeatherState()` | Returns `WeatherState` object with basic weather state information. |
+| `getTemperature()` | Returns `Temperature` object. Available fields: `value`, `feelsLike`, `dewPoint` and `unit`. |
+| `getAtmosphericPressure()` | Returns `AtmosphericPressure` object. Available fields: `seaLevelValue`. |
+| `getHumidity()` | Returns `Humidity` object. Available fields: `value` and `unit`. |
+| `getClouds()` | Returns `Clouds` object. Available fields: `value` and `unit`. |
+| `getUvIndex()` | Returns UV index value. |
+| `getVisibilityInMetres()` | Returns visibility in metres. |
+| `getWind()` | Returns `Wind` object. Available fields: `speed`, `degrees`, `gust` and `unit`. |
+| `getRain()` | Returns `Rain` object. Available fields: `oneHourLevel` and `unit`. |
+| `getSnow()` | Returns `Snow` object. Available fields: `oneHourLevel` and `unit`. |
+
+`com.github.prominence.openweathermap.api.model.onecall.historical.HourlyHistorical`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-----------------------------------|---------------------------------------------------------------------------------------------------|
+| `getForecastTime()` | Returns `LocalDateTime` object with weather forecast time. |
+| `getWeatherState()` | Returns `WeatherState` object with basic weather state information. |
+| `getTemperature()` | Returns `Temperature` object. Available fields: `value`, `feelsLike`, `dewPoint` and `unit`. |
+| `getAtmosphericPressure()` | Returns `AtmosphericPressure` object. Available fields: `seaLevelValue`. |
+| `getHumidity()` | Returns `Humidity` object. Available fields: `value` and `unit`. |
+| `getClouds()` | Returns `Clouds` object. Available fields: `value` and `unit`. |
+| `getVisibilityInMetres()` | Returns visibility in metres. |
+| `getWind()` | Returns `Wind` object. Available fields: `speed`, `degrees`, `gust` and `unit`. |
+| `getRain()` | Returns `Rain` object. Available fields: `oneHourLevel` and `unit`. |
+| `getSnow()` | Returns `Snow` object. Available fields: `oneHourLevel` and `unit`. |
+
+#### Air Pollution API
+Examples:
+```java
+final AirPollutionDetails airPollutionDetails = openWeatherClient
+ .airPollution()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieve()
+ .asJava();
+```
+
+```java
+final AirPollutionDetails airPollutionDetails = openWeatherClient
+ .airPollution()
+ .historical()
+ .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999)
+ .retrieve()
+ .asJava();
+```
+
+`com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|---------------------------------------------------------------------------|
+| `getCoordinate()` | Returns `Coordinate` object. Available fields: `latitude`, `longitude`. |
+| `getAirPollutionRecords()` | Returns list of `AirPollutionRecord` objects. |
+
+`com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionRecord`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|---------------------------------------------------------------------------|
+| `getForecastTime()` | Returns `LocalDateTime` object with air pollution forecast time. |
+| `getAirQualityIndex()` | Returns `AirQualityIndex` object. |
+| `getCO()` | Returns carbon monoxide concentration value in μg/m^3.s. |
+| `getCarbonMonoxide()` | An alias for `getCO()` method. |
+| `getNO()` | Returns nitrogen monoxide concentration value in μg/m^3. |
+| `getNitrogenMonoxide()` | An alias for `getNO()` method. |
+| `getNO2()` | Returns nitrogen dioxide concentration value in μg/m^3. |
+| `getNitrogenDioxide()` | An alias for `getNO2()` method. |
+| `getO3()` | Returns ozone concentration value in μg/m^3. |
+| `getOzone()` | An alias for `getO3()` method. |
+| `getSO2()` | Returns sulphur dioxide concentration value in μg/m^3. |
+| `getSulphurDioxide()` | An alias for `getSO2()` method. |
+| `getPM2_5()` | Returns fine particles matter concentration value in μg/m^3. |
+| `getFineParticlesMatter()` | An alias for `getPM2_5()` method. |
+| `getPM10()` | Returns coarse particulate matter concentration value in μg/m^3. |
+| `getCoarseParticulateMatter()`| An alias for `getPM10()` method. |
+| `getNH3()` | Returns ammonia concentration value in μg/m^3. |
+| `getAmmonia()` | An alias for `getNH3()` method. |
+
+### Constants and options
+
+#### Language
+| Constant | Description |
+|-----------------------------------|-------------------------------|
+| Language.AFRIKAANS | Afrikaans language. |
+| Language.ALBANIAN | ALBANIAN language. |
+| Language.ARABIC | Arabic language. |
+| Language.AZERBAIJANI | Azerbaijani language. |
+| Language.BULGARIAN | Bulgarian language. |
+| Language.CATALAN | Catalan language. |
+| Language.CZECH | Czech language. |
+| Language.DANISH | Danish language. |
+| Language.GERMAN | German language. |
+| Language.GREEK | Greek language. |
+| Language.ENGLISH | English language. |
+| Language.BASQUE | Basque language. |
+| Language.PERSIAN | Persian (Farsi) language. |
+| Language.FINNISH | Finnish language. |
+| Language.FRENCH | French language. |
+| Language.GALICIAN | Galician language. |
+| Language.HEBREW | Hebrew language. |
+| Language.HINDI | Hindi language. |
+| Language.CROATIAN | Croatian language. |
+| Language.HUNGARIAN | Hungarian language. |
+| Language.INDONESIAN | Indonesian language. |
+| Language.ITALIAN | Italian language. |
+| Language.JAPANESE | Japanese language. |
+| Language.KOREAN | Korean language. |
+| Language.LATVIAN | Latvian language. |
+| Language.LITHUANIAN | Lithuanian language. |
+| Language.MACEDONIAN | Macedonian language. |
+| Language.NORWEGIAN | Norwegian language. |
+| Language.DUTCH | Dutch language. |
+| Language.POLISH | Polish language. |
+| Language.PORTUGUESE | Portuguese language. |
+| Language.PORTUGUES_BRAZIL | Português Brasil language. |
+| Language.ROMANIAN | Romanian language. |
+| Language.RUSSIAN | Russian language. |
+| Language.SWEDISH | Swedish language. |
+| Language.SLOVAK | Slovak language. |
+| Language.SLOVENIAN | Slovenian language. |
+| Language.SPANISH | Spanish language. |
+| Language.SERBIAN | Serbian language. |
+| Language.THAI | Thai language. |
+| Language.TURKISH | Turkish language. |
+| Language.UKRANIAN | Ukrainian language. |
+| Language.VIETNAMESE | Vietnamese language. |
+| Language.CHINESE_SIMPLIFIED | Chinese Simplified language. |
+| Language.CHINESE_TRADITIONAL | Chinese Traditional language. |
+| Language.ZULU | Zulu language. |
+
+#### Unit
+| Constant | Description |
+|----------------------|------------------------------------------------|
+| Unit.METRIC_SYSTEM | Celsius, meter/sec, hPa, mm(rain, snow). |
+| Unit.IMPERIAL_SYSTEM | Fahrenheit, miles/hour, hPa, mm(rain, snow). |
+| Unit.STANDARD_SYSTEM | Kelvin, meter/sec, hPa, mm(rain, snow). |
+
+### Dependencies
+* com.fasterxml.jackson.core:jackson-databind:2.12.2
+* org.slf4j:slf4j-api:1.7.30 (*compile*)
+* org.junit.jupiter:junit-jupiter-engine:5.7.1 (*test*)
+* org.junit.platform:junit-platform-runner:1.7.1 (*test*)
\ No newline at end of file
diff --git a/docs/SNAPSHOT.md b/docs/SNAPSHOT.md
index b67018c..328fb27 100644
--- a/docs/SNAPSHOT.md
+++ b/docs/SNAPSHOT.md
@@ -2,6 +2,7 @@
* Current weather data
* 5 day / 3-hour forecast
* One Call API
+* Air Pollution
### Maven coordinates:
@@ -31,6 +32,7 @@ Currently, available APIs are:
* `currentWeather()`
* `forecast5Day3HourStep()`
* `oneCall()`
+* `airPollution()`
Default(more or less) customization points:
```java
@@ -420,6 +422,56 @@ You are able to set preferable options(via chain methods) and execute appropriat
| `getRain()` | Returns `Rain` object. Available fields: `oneHourLevel` and `unit`. |
| `getSnow()` | Returns `Snow` object. Available fields: `oneHourLevel` and `unit`. |
+#### Air Pollution API
+Examples:
+```java
+final AirPollutionDetails airPollutionDetails = openWeatherClient
+ .airPollution()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieve()
+ .asJava();
+```
+
+```java
+final AirPollutionDetails airPollutionDetails = openWeatherClient
+ .airPollution()
+ .historical()
+ .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999)
+ .retrieve()
+ .asJava();
+```
+
+`com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|---------------------------------------------------------------------------|
+| `getCoordinate()` | Returns `Coordinate` object. Available fields: `latitude`, `longitude`. |
+| `getAirPollutionRecords()` | Returns list of `AirPollutionRecord` objects. |
+
+`com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionRecord`'s useful public methods(setters are not listed):
+
+| Method | Description |
+|-------------------------------|---------------------------------------------------------------------------|
+| `getForecastTime()` | Returns `LocalDateTime` object with air pollution forecast time. |
+| `getAirQualityIndex()` | Returns `AirQualityIndex` object. |
+| `getCO()` | Returns carbon monoxide concentration value in μg/m^3.s. |
+| `getCarbonMonoxide()` | An alias for `getCO()` method. |
+| `getNO()` | Returns nitrogen monoxide concentration value in μg/m^3. |
+| `getNitrogenMonoxide()` | An alias for `getNO()` method. |
+| `getNO2()` | Returns nitrogen dioxide concentration value in μg/m^3. |
+| `getNitrogenDioxide()` | An alias for `getNO2()` method. |
+| `getO3()` | Returns ozone concentration value in μg/m^3. |
+| `getOzone()` | An alias for `getO3()` method. |
+| `getSO2()` | Returns sulphur dioxide concentration value in μg/m^3. |
+| `getSulphurDioxide()` | An alias for `getSO2()` method. |
+| `getPM2_5()` | Returns fine particles matter concentration value in μg/m^3. |
+| `getFineParticlesMatter()` | An alias for `getPM2_5()` method. |
+| `getPM10()` | Returns coarse particulate matter concentration value in μg/m^3. |
+| `getCoarseParticulateMatter()`| An alias for `getPM10()` method. |
+| `getNH3()` | Returns ammonia concentration value in μg/m^3. |
+| `getAmmonia()` | An alias for `getNH3()` method. |
+
### Constants and options
#### Language
diff --git a/pom.xml b/pom.xml
index dd4a389..168b4f4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.github.prominence
openweathermap-api
- 2.1.1
+ 2.2.0
jar
Java OpenWeatherMap API
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 5579c4a..145be6d 100644
--- a/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java
+++ b/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java
@@ -23,6 +23,8 @@
package com.github.prominence.openweathermap.api;
import com.github.prominence.openweathermap.api.annotation.SubscriptionAvailability;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequester;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequesterImpl;
import com.github.prominence.openweathermap.api.request.forecast.free.FiveDayThreeHourStepForecastRequester;
import com.github.prominence.openweathermap.api.request.forecast.free.FiveDayThreeHourStepForecastRequesterImpl;
import com.github.prominence.openweathermap.api.request.onecall.OneCallWeatherRequester;
@@ -74,4 +76,14 @@ public class OpenWeatherMapClient {
public OneCallWeatherRequester oneCall() {
return new OneCallWeatherRequesterImpl(apiKey);
}
+
+ /**
+ * 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)
+ public AirPollutionRequester airPollution() {
+ return new AirPollutionRequesterImpl(apiKey);
+ }
}
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
new file mode 100644
index 0000000..e90d97c
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/enums/AirQualityIndex.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * * 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.enums;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * The enum Air quality index.
+ */
+public enum AirQualityIndex {
+ /**
+ * Good air quality index.
+ */
+ GOOD(1),
+ /**
+ * Fair air quality index.
+ */
+ FAIR(2),
+ /**
+ * Moderate air quality index.
+ */
+ MODERATE(3),
+ /**
+ * Poor air quality index.
+ */
+ POOR(4),
+ /**
+ * Very poor air quality index.
+ */
+ VERY_POOR(5);
+
+ private final int value;
+
+ AirQualityIndex(int index) {
+ this.value = index;
+ }
+
+ /**
+ * Gets value.
+ *
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Gets by index.
+ *
+ * @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);
+ }
+}
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
new file mode 100644
index 0000000..c4e7112
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetails.java
@@ -0,0 +1,87 @@
+/*
+ *
+ * * 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.Coordinate;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * The type Air pollution.
+ */
+public class AirPollutionDetails {
+ private Coordinate coordinate;
+ private List airPollutionRecords;
+
+ /**
+ * Gets coordinate.
+ *
+ * @return the coordinate
+ */
+ public Coordinate getCoordinate() {
+ return coordinate;
+ }
+
+ /**
+ * Sets coordinate.
+ *
+ * @param coordinate the coordinate
+ */
+ public void setCoordinate(Coordinate coordinate) {
+ this.coordinate = coordinate;
+ }
+
+ /**
+ * 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(coordinate, that.coordinate) && Objects.equals(airPollutionRecords, that.airPollutionRecords);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(coordinate, airPollutionRecords);
+ }
+}
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
new file mode 100644
index 0000000..7ced2be
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecord.java
@@ -0,0 +1,376 @@
+/*
+ *
+ * * 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.enums.AirQualityIndex;
+
+import java.time.LocalDateTime;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * The type Air pollution record.
+ */
+public class AirPollutionRecord {
+ private LocalDateTime forecastTime;
+ private AirQualityIndex airQualityIndex;
+
+ 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;
+ }
+
+ /**
+ * 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
+ */
+ 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;
+ }
+
+ @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);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(forecastTime, airQualityIndex, CO, NO, NO2, O3, SO2, PM2_5, PM10, NH3);
+ }
+
+ @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();
+ }
+}
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
new file mode 100644
index 0000000..608e60f
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminator.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails;
+import com.github.prominence.openweathermap.api.request.AsyncRequestTerminator;
+
+/**
+ * The interface Current air pollution async request terminator.
+ */
+public interface AirPollutionAsyncRequestTerminator extends AsyncRequestTerminator {
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminatorImpl.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminatorImpl.java
new file mode 100644
index 0000000..45ffcd2
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionAsyncRequestTerminatorImpl.java
@@ -0,0 +1,61 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails;
+import com.github.prominence.openweathermap.api.request.RequestUrlBuilder;
+import com.github.prominence.openweathermap.api.utils.RequestUtils;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * The type Air pollution async request terminator.
+ */
+public class AirPollutionAsyncRequestTerminatorImpl implements AirPollutionAsyncRequestTerminator {
+ private final RequestUrlBuilder urlBuilder;
+
+ /**
+ * Instantiates a new Air pollution async request terminator.
+ *
+ * @param urlBuilder the url builder
+ */
+ public AirPollutionAsyncRequestTerminatorImpl(RequestUrlBuilder urlBuilder) {
+ this.urlBuilder = urlBuilder;
+ }
+
+ @Override
+ public CompletableFuture asJava() {
+ return CompletableFuture.supplyAsync(() -> new AirPollutionResponseMapper().mapToAirPollution(getRawResponse()));
+ }
+
+ @Override
+ public CompletableFuture asJSON() {
+ return CompletableFuture.supplyAsync(this::getRawResponse);
+ }
+
+ private String getRawResponse() {
+ return RequestUtils.getResponse(urlBuilder.buildUrl());
+ }
+}
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
new file mode 100644
index 0000000..d4b35ef
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestCustomizer.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+/**
+ * The interface Current air pollution request customizer.
+ */
+public interface AirPollutionRequestCustomizer {
+ /**
+ * Retrieve current air pollution request terminator.
+ *
+ * @return the current air pollution request terminator
+ */
+ AirPollutionRequestTerminator retrieve();
+
+ /**
+ * Retrieve async current air pollution async request terminator.
+ *
+ * @return the current air pollution async request terminator
+ */
+ AirPollutionAsyncRequestTerminator retrieveAsync();
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestCustomizerImpl.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestCustomizerImpl.java
new file mode 100644
index 0000000..2c75b81
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestCustomizerImpl.java
@@ -0,0 +1,45 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.github.prominence.openweathermap.api.request.RequestUrlBuilder;
+
+public class AirPollutionRequestCustomizerImpl implements AirPollutionRequestCustomizer {
+ private final RequestUrlBuilder urlBuilder;
+
+ public AirPollutionRequestCustomizerImpl(RequestUrlBuilder urlBuilder) {
+ this.urlBuilder = urlBuilder;
+ }
+
+ @Override
+ public AirPollutionRequestTerminator retrieve() {
+ return new AirPollutionRequestTerminatorImpl(urlBuilder);
+ }
+
+ @Override
+ public AirPollutionAsyncRequestTerminator retrieveAsync() {
+ return new AirPollutionAsyncRequestTerminatorImpl(urlBuilder);
+ }
+}
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
new file mode 100644
index 0000000..64f4870
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminator.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails;
+import com.github.prominence.openweathermap.api.request.RequestTerminator;
+
+/**
+ * The interface Current air pollution request terminator.
+ */
+public interface AirPollutionRequestTerminator extends RequestTerminator {
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminatorImpl.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminatorImpl.java
new file mode 100644
index 0000000..aae8ac1
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequestTerminatorImpl.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails;
+import com.github.prominence.openweathermap.api.request.RequestUrlBuilder;
+import com.github.prominence.openweathermap.api.utils.RequestUtils;
+
+/**
+ * The type Air pollution request terminator.
+ */
+public class AirPollutionRequestTerminatorImpl implements AirPollutionRequestTerminator {
+ private final RequestUrlBuilder urlBuilder;
+
+ /**
+ * Instantiates a new Air pollution request terminator.
+ *
+ * @param urlBuilder the url builder
+ */
+ public AirPollutionRequestTerminatorImpl(RequestUrlBuilder urlBuilder) {
+ this.urlBuilder = urlBuilder;
+ }
+
+ @Override
+ public AirPollutionDetails asJava() {
+ return new AirPollutionResponseMapper().mapToAirPollution(getRawResponse());
+ }
+
+ @Override
+ public String asJSON() {
+ return getRawResponse();
+ }
+
+ private String getRawResponse() {
+ return RequestUtils.getResponse(urlBuilder.buildUrl());
+ }
+}
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
new file mode 100644
index 0000000..e0f4ba3
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequester.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Alexey Zinchenko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.github.prominence.openweathermap.api.request.air.pollution.current.CurrentAirPollutionRequester;
+import com.github.prominence.openweathermap.api.request.air.pollution.forecast.ForecastAirPollutionRequester;
+import com.github.prominence.openweathermap.api.request.air.pollution.historical.HistoricalAirPollutionRequester;
+
+/**
+ * The interface Air pollution requester.
+ */
+public interface AirPollutionRequester {
+ /**
+ * Current current air pollution requester.
+ *
+ * @return the current air pollution requester
+ */
+ CurrentAirPollutionRequester current();
+
+ /**
+ * Forecast forecast air pollution requester.
+ *
+ * @return the forecast air pollution requester
+ */
+ ForecastAirPollutionRequester forecast();
+
+ /**
+ * Historical historical air pollution requester.
+ *
+ * @return the historical air pollution requester
+ */
+ HistoricalAirPollutionRequester historical();
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequesterImpl.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequesterImpl.java
new file mode 100644
index 0000000..0faa6b3
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionRequesterImpl.java
@@ -0,0 +1,67 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.github.prominence.openweathermap.api.request.RequestUrlBuilder;
+import com.github.prominence.openweathermap.api.request.air.pollution.current.CurrentAirPollutionRequester;
+import com.github.prominence.openweathermap.api.request.air.pollution.current.CurrentAirPollutionRequesterImpl;
+import com.github.prominence.openweathermap.api.request.air.pollution.forecast.ForecastAirPollutionRequester;
+import com.github.prominence.openweathermap.api.request.air.pollution.forecast.ForecastAirPollutionRequesterImpl;
+import com.github.prominence.openweathermap.api.request.air.pollution.historical.HistoricalAirPollutionRequester;
+import com.github.prominence.openweathermap.api.request.air.pollution.historical.HistoricalAirPollutionRequesterImpl;
+
+/**
+ * The type Air pollution requester.
+ */
+public class AirPollutionRequesterImpl implements AirPollutionRequester {
+ private final RequestUrlBuilder urlBuilder;
+
+ /**
+ * Instantiates a new Air pollution requester.
+ *
+ * @param apiKey the api key
+ */
+ public AirPollutionRequesterImpl(String apiKey) {
+ urlBuilder = new RequestUrlBuilder(apiKey);
+ }
+
+ @Override
+ public CurrentAirPollutionRequester current() {
+ urlBuilder.append("air_pollution");
+ return new CurrentAirPollutionRequesterImpl(urlBuilder);
+ }
+
+ @Override
+ public ForecastAirPollutionRequester forecast() {
+ urlBuilder.append("air_pollution/forecast");
+ return new ForecastAirPollutionRequesterImpl(urlBuilder);
+ }
+
+ @Override
+ public HistoricalAirPollutionRequester historical() {
+ urlBuilder.append("air_pollution/history");
+ return new HistoricalAirPollutionRequesterImpl(urlBuilder);
+ }
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionResponseMapper.java
new file mode 100644
index 0000000..fd9b26e
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionResponseMapper.java
@@ -0,0 +1,104 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.prominence.openweathermap.api.enums.AirQualityIndex;
+import com.github.prominence.openweathermap.api.model.Coordinate;
+import com.github.prominence.openweathermap.api.model.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;
+
+/**
+ * The type Air pollution response mapper.
+ */
+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.setCoordinate(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 Coordinate parseCoordinate(JsonNode rootNode) {
+ final JsonNode latitudeNode = rootNode.get("lat");
+ final JsonNode longitudeNode = rootNode.get("lon");
+ if (latitudeNode != null && longitudeNode != null) {
+ return Coordinate.of(latitudeNode.asDouble(), longitudeNode.asDouble());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/current/CurrentAirPollutionRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/current/CurrentAirPollutionRequester.java
new file mode 100644
index 0000000..f9ef4a4
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/current/CurrentAirPollutionRequester.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Alexey Zinchenko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution.current;
+
+import com.github.prominence.openweathermap.api.model.Coordinate;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequestCustomizer;
+
+/**
+ * The interface Current air pollution requester.
+ */
+public interface CurrentAirPollutionRequester {
+ /**
+ * By coordinate current air pollution request customizer.
+ *
+ * @param coordinate the coordinate
+ * @return the current air pollution request customizer
+ */
+ AirPollutionRequestCustomizer byCoordinate(Coordinate coordinate);
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/current/CurrentAirPollutionRequesterImpl.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/current/CurrentAirPollutionRequesterImpl.java
new file mode 100644
index 0000000..4b770a0
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/current/CurrentAirPollutionRequesterImpl.java
@@ -0,0 +1,53 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution.current;
+
+import com.github.prominence.openweathermap.api.model.Coordinate;
+import com.github.prominence.openweathermap.api.request.RequestUrlBuilder;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequestCustomizer;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequestCustomizerImpl;
+
+/**
+ * The type Current air pollution requester.
+ */
+public class CurrentAirPollutionRequesterImpl implements CurrentAirPollutionRequester {
+ private final RequestUrlBuilder urlBuilder;
+
+ /**
+ * Instantiates a new Current air pollution requester.
+ *
+ * @param urlBuilder the url builder
+ */
+ public CurrentAirPollutionRequesterImpl(RequestUrlBuilder urlBuilder) {
+ this.urlBuilder = urlBuilder;
+ }
+
+ @Override
+ public AirPollutionRequestCustomizer byCoordinate(Coordinate coordinate) {
+ urlBuilder.addRequestParameter("lat", String.valueOf(coordinate.getLatitude()));
+ urlBuilder.addRequestParameter("lon", String.valueOf(coordinate.getLongitude()));
+ return new AirPollutionRequestCustomizerImpl(urlBuilder);
+ }
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/forecast/ForecastAirPollutionRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/forecast/ForecastAirPollutionRequester.java
new file mode 100644
index 0000000..7dec255
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/forecast/ForecastAirPollutionRequester.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution.forecast;
+
+import com.github.prominence.openweathermap.api.model.Coordinate;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequestCustomizer;
+
+/**
+ * The interface Forecast air pollution requester.
+ */
+public interface ForecastAirPollutionRequester {
+ /**
+ * By coordinate forecast air pollution request customizer.
+ *
+ * @param coordinate the coordinate
+ * @return the forecast air pollution request customizer
+ */
+ AirPollutionRequestCustomizer byCoordinate(Coordinate coordinate);
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/forecast/ForecastAirPollutionRequesterImpl.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/forecast/ForecastAirPollutionRequesterImpl.java
new file mode 100644
index 0000000..87d5e37
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/forecast/ForecastAirPollutionRequesterImpl.java
@@ -0,0 +1,53 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution.forecast;
+
+import com.github.prominence.openweathermap.api.model.Coordinate;
+import com.github.prominence.openweathermap.api.request.RequestUrlBuilder;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequestCustomizer;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequestCustomizerImpl;
+
+/**
+ * The type Forecast air pollution requester.
+ */
+public class ForecastAirPollutionRequesterImpl implements ForecastAirPollutionRequester {
+ private final RequestUrlBuilder urlBuilder;
+
+ /**
+ * Instantiates a new Forecast air pollution requester.
+ *
+ * @param urlBuilder the url builder
+ */
+ public ForecastAirPollutionRequesterImpl(RequestUrlBuilder urlBuilder) {
+ this.urlBuilder = urlBuilder;
+ }
+
+ @Override
+ public AirPollutionRequestCustomizer byCoordinate(Coordinate coordinate) {
+ urlBuilder.addRequestParameter("lat", String.valueOf(coordinate.getLatitude()));
+ urlBuilder.addRequestParameter("lon", String.valueOf(coordinate.getLongitude()));
+ return new AirPollutionRequestCustomizerImpl(urlBuilder);
+ }
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/historical/HistoricalAirPollutionRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/historical/HistoricalAirPollutionRequester.java
new file mode 100644
index 0000000..f06dc1d
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/historical/HistoricalAirPollutionRequester.java
@@ -0,0 +1,43 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution.historical;
+
+import com.github.prominence.openweathermap.api.model.Coordinate;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequestCustomizer;
+
+/**
+ * The interface Historical air pollution requester.
+ */
+public interface HistoricalAirPollutionRequester {
+ /**
+ * By coordinate historical air pollution request customizer.
+ *
+ * @param coordinate the coordinate
+ * @param startUnixTime the start unix time
+ * @param endUnixTime the end unix time
+ * @return the historical air pollution request customizer
+ */
+ AirPollutionRequestCustomizer byCoordinateAndPeriod(Coordinate coordinate, long startUnixTime, long endUnixTime);
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/historical/HistoricalAirPollutionRequesterImpl.java b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/historical/HistoricalAirPollutionRequesterImpl.java
new file mode 100644
index 0000000..8ea1618
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/air/pollution/historical/HistoricalAirPollutionRequesterImpl.java
@@ -0,0 +1,55 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution.historical;
+
+import com.github.prominence.openweathermap.api.model.Coordinate;
+import com.github.prominence.openweathermap.api.request.RequestUrlBuilder;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequestCustomizer;
+import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequestCustomizerImpl;
+
+/**
+ * The type Historical air pollution requester.
+ */
+public class HistoricalAirPollutionRequesterImpl implements HistoricalAirPollutionRequester {
+ private final RequestUrlBuilder urlBuilder;
+
+ /**
+ * Instantiates a new Historical air pollution requester.
+ *
+ * @param urlBuilder the url builder
+ */
+ public HistoricalAirPollutionRequesterImpl(RequestUrlBuilder urlBuilder) {
+ this.urlBuilder = urlBuilder;
+ }
+
+ @Override
+ public AirPollutionRequestCustomizer byCoordinateAndPeriod(Coordinate coordinate, long startUnixTime, long endUnixTime) {
+ urlBuilder.addRequestParameter("lat", String.valueOf(coordinate.getLatitude()));
+ urlBuilder.addRequestParameter("lon", String.valueOf(coordinate.getLongitude()));
+ urlBuilder.addRequestParameter("start", String.valueOf(startUnixTime));
+ urlBuilder.addRequestParameter("end", String.valueOf(endUnixTime));
+ return new AirPollutionRequestCustomizerImpl(urlBuilder);
+ }
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherResponseMapper.java
index 5b4caf3..7837b94 100644
--- a/src/main/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherResponseMapper.java
+++ b/src/main/java/com/github/prominence/openweathermap/api/request/onecall/OneCallWeatherResponseMapper.java
@@ -72,7 +72,7 @@ public class OneCallWeatherResponseMapper {
final JsonNode root = objectMapper.readTree(json);
currentData = mapToCurrent(root);
} catch (JsonProcessingException e) {
- throw new RuntimeException("Cannot parse Forecast response");
+ throw new RuntimeException("Cannot parse OneCall response");
}
return currentData;
@@ -91,7 +91,7 @@ public class OneCallWeatherResponseMapper {
final JsonNode root = objectMapper.readTree(json);
historicalData = mapToHistorical(root);
} catch (JsonProcessingException e) {
- throw new RuntimeException("Cannot parse Forecast response");
+ throw new RuntimeException("Cannot parse OneCall response");
}
return historicalData;
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
new file mode 100644
index 0000000..a274a8e
--- /dev/null
+++ b/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionDetailsUnitTest.java
@@ -0,0 +1,97 @@
+/*
+ *
+ * * 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.Coordinate;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class AirPollutionDetailsUnitTest {
+ @Test
+ public void getCoordinate() {
+ final AirPollutionDetails airPollutionDetails = new AirPollutionDetails();
+ final Coordinate coordinate = Coordinate.of(22.3, 44.2);
+ airPollutionDetails.setCoordinate(coordinate);
+
+ assertEquals(coordinate, airPollutionDetails.getCoordinate());
+ }
+
+ @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 Coordinate coordinate = Coordinate.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.setCoordinate(coordinate);
+
+ assertNotEquals(first, second);
+
+ second.setCoordinate(coordinate);
+
+ 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 Coordinate coordinate = Coordinate.of(22.3, 44.2);
+
+ assertEquals(first.hashCode(), second.hashCode());
+
+ first.setCoordinate(coordinate);
+
+ 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
new file mode 100644
index 0000000..2937a17
--- /dev/null
+++ b/src/test/java/com/github/prominence/openweathermap/api/model/air/pollution/AirPollutionRecordUnitTest.java
@@ -0,0 +1,280 @@
+/*
+ *
+ * * 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.enums.AirQualityIndex;
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDateTime;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class AirPollutionRecordUnitTest {
+ @Test
+ public void getForecastTime() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ final LocalDateTime now = LocalDateTime.now();
+ airPollutionRecord.setForecastTime(now);
+
+ assertEquals(now, airPollutionRecord.getForecastTime());
+ }
+
+ @Test
+ public void getAirQualityIndex() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ airPollutionRecord.setAirQualityIndex(AirQualityIndex.FAIR);
+
+ assertEquals(AirQualityIndex.FAIR, airPollutionRecord.getAirQualityIndex());
+ }
+
+ @Test
+ public void getCarbonMonoxide() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ final double value = 0.55;
+ airPollutionRecord.setCO(value);
+
+ assertEquals(value, airPollutionRecord.getCarbonMonoxide(), 0.00001);
+ }
+
+ @Test
+ public void getNitrogenMonoxide() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ final double value = 0.55;
+ airPollutionRecord.setNO(value);
+
+ assertEquals(value, airPollutionRecord.getNitrogenMonoxide(), 0.00001);
+ }
+
+ @Test
+ public void getNitrogenDioxide() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ final double value = 0.55;
+ airPollutionRecord.setNO2(value);
+
+ assertEquals(value, airPollutionRecord.getNitrogenDioxide(), 0.00001);
+ }
+
+ @Test
+ public void getOzone() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ final double value = 0.55;
+ airPollutionRecord.setO3(value);
+
+ assertEquals(value, airPollutionRecord.getOzone(), 0.00001);
+ }
+
+ @Test
+ public void getSulphurDioxide() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ final double value = 0.55;
+ airPollutionRecord.setSO2(value);
+
+ assertEquals(value, airPollutionRecord.getSulphurDioxide(), 0.00001);
+ }
+
+ @Test
+ public void getFineParticlesMatter() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ final double value = 0.55;
+ airPollutionRecord.setPM2_5(value);
+
+ assertEquals(value, airPollutionRecord.getFineParticlesMatter(), 0.00001);
+ }
+
+ @Test
+ public void getCoarseParticulateMatter() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ final double value = 0.55;
+ airPollutionRecord.setPM10(value);
+
+ assertEquals(value, airPollutionRecord.getCoarseParticulateMatter(), 0.00001);
+ }
+
+ @Test
+ public void getAmmonia() {
+ final AirPollutionRecord airPollutionRecord = new AirPollutionRecord();
+ final double value = 0.55;
+ airPollutionRecord.setNH3(value);
+
+ assertEquals(value, airPollutionRecord.getAmmonia());
+ }
+
+ @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);
+ }
+
+ @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/request/air/pollution/AirPollutionIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionIntegrationTest.java
new file mode 100644
index 0000000..657cd15
--- /dev/null
+++ b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionIntegrationTest.java
@@ -0,0 +1,208 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.github.prominence.openweathermap.api.ApiTest;
+import com.github.prominence.openweathermap.api.model.Coordinate;
+import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class AirPollutionIntegrationTest extends ApiTest {
+ @Test
+ public void whenRetrieveCurrentAirPollutionResponseAsJava_thenOk() {
+ final AirPollutionDetails airPollutionDetails = getClient()
+ .airPollution()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieve()
+ .asJava();
+
+ assertNotNull(airPollutionDetails);
+ airPollutionDetails.getAirPollutionRecords().forEach(airPollutionRecord -> {
+ assertNotNull(airPollutionRecord);
+ System.out.println(airPollutionRecord);
+ });
+ }
+
+ @Test
+ public void whenRetrieveCurrentAirPollutionResponseAsJSON_thenOk() {
+ final String jsonString = getClient()
+ .airPollution()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieve()
+ .asJSON();
+
+ assertNotNull(jsonString);
+ System.out.println(jsonString);
+ }
+
+ @Test
+ public void whenRetrieveCurrentAirPollutionAsyncResponseAsJava_thenOk() throws ExecutionException, InterruptedException {
+ final CompletableFuture pollutionDetailsFuture = getClient()
+ .airPollution()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieveAsync()
+ .asJava();
+
+ assertNotNull(pollutionDetailsFuture);
+ assertNotNull(pollutionDetailsFuture.get());
+ }
+
+ @Test
+ public void whenRetrieveCurrentAirPollutionAsyncResponseAsJSON_thenOk() throws ExecutionException, InterruptedException {
+ final CompletableFuture jsonStringFuture = getClient()
+ .airPollution()
+ .current()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieveAsync()
+ .asJSON();
+
+ assertNotNull(jsonStringFuture);
+ final String jsonString = jsonStringFuture.get();
+ assertNotNull(jsonString);
+ System.out.println(jsonString);
+ }
+
+ @Test
+ public void whenRetrieveForecastAirPollutionResponseAsJava_thenOk() {
+ final AirPollutionDetails airPollutionDetails = getClient()
+ .airPollution()
+ .forecast()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieve()
+ .asJava();
+
+ assertNotNull(airPollutionDetails);
+ airPollutionDetails.getAirPollutionRecords().forEach(airPollutionRecord -> {
+ assertNotNull(airPollutionRecord);
+ System.out.println(airPollutionRecord);
+ });
+ }
+
+ @Test
+ public void whenRetrieveForecastAirPollutionResponseAsJSON_thenOk() {
+ final String jsonString = getClient()
+ .airPollution()
+ .forecast()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieve()
+ .asJSON();
+
+ assertNotNull(jsonString);
+ System.out.println(jsonString);
+ }
+
+ @Test
+ public void whenRetrieveForecastAirPollutionAsyncResponseAsJava_thenOk() throws ExecutionException, InterruptedException {
+ final CompletableFuture pollutionDetailsFuture = getClient()
+ .airPollution()
+ .forecast()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieveAsync()
+ .asJava();
+
+ assertNotNull(pollutionDetailsFuture);
+ assertNotNull(pollutionDetailsFuture.get());
+ }
+
+ @Test
+ public void whenRetrieveForecastAirPollutionAsyncResponseAsJSON_thenOk() throws ExecutionException, InterruptedException {
+ final CompletableFuture jsonStringFuture = getClient()
+ .airPollution()
+ .forecast()
+ .byCoordinate(Coordinate.of(53.54, 27.34))
+ .retrieveAsync()
+ .asJSON();
+
+ assertNotNull(jsonStringFuture);
+ final String jsonString = jsonStringFuture.get();
+ assertNotNull(jsonString);
+ System.out.println(jsonString);
+ }
+
+ @Test
+ public void whenRetrieveHistoricalAirPollutionResponseAsJava_thenOk() {
+ final AirPollutionDetails airPollutionDetails = getClient()
+ .airPollution()
+ .historical()
+ .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999)
+ .retrieve()
+ .asJava();
+
+ assertNotNull(airPollutionDetails);
+ airPollutionDetails.getAirPollutionRecords().forEach(airPollutionRecord -> {
+ assertNotNull(airPollutionRecord);
+ System.out.println(airPollutionRecord);
+ });
+ }
+
+ @Test
+ public void whenRetrieveHistoricalAirPollutionResponseAsJSON_thenOk() {
+ final String jsonString = getClient()
+ .airPollution()
+ .historical()
+ .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999)
+ .retrieve()
+ .asJSON();
+
+ assertNotNull(jsonString);
+ System.out.println(jsonString);
+ }
+
+ @Test
+ public void whenRetrieveHistoricalAirPollutionAsyncResponseAsJava_thenOk() throws ExecutionException, InterruptedException {
+ final CompletableFuture pollutionDetailsFuture = getClient()
+ .airPollution()
+ .historical()
+ .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999)
+ .retrieveAsync()
+ .asJava();
+
+ assertNotNull(pollutionDetailsFuture);
+ assertNotNull(pollutionDetailsFuture.get());
+ }
+
+ @Test
+ public void whenRetrieveHistoricalAirPollutionAsyncResponseAsJSON_thenOk() throws ExecutionException, InterruptedException {
+ final CompletableFuture jsonStringFuture = getClient()
+ .airPollution()
+ .historical()
+ .byCoordinateAndPeriod(Coordinate.of(53.54, 27.34), 1606223802, 1606482999)
+ .retrieveAsync()
+ .asJSON();
+
+ assertNotNull(jsonStringFuture);
+ final String jsonString = jsonStringFuture.get();
+ assertNotNull(jsonString);
+ System.out.println(jsonString);
+ }
+}
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
new file mode 100644
index 0000000..b8c86b2
--- /dev/null
+++ b/src/test/java/com/github/prominence/openweathermap/api/request/air/pollution/AirPollutionResponseMapperUnitTest.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * * Copyright (c) 2021 Alexey Zinchenko
+ * *
+ * * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * * of this software and associated documentation files (the "Software"), to deal
+ * * in the Software without restriction, including without limitation the rights
+ * * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * * copies of the Software, and to permit persons to whom the Software is
+ * * furnished to do so, subject to the following conditions:
+ * *
+ * * The above copyright notice and this permission notice shall be included in all
+ * * copies or substantial portions of the Software.
+ * *
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * * SOFTWARE.
+ *
+ */
+
+package com.github.prominence.openweathermap.api.request.air.pollution;
+
+import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+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));
+ }
+
+ @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);
+
+ 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);
+
+ 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);
+
+ assertNotNull(airPollutionDetails);
+ }
+}
\ No newline at end of file
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 293a4fe..5dab17b 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
@@ -31,11 +31,6 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class OneCallWeatherResponseMapperUnitTest {
- @Test
- public void mapToCurrent() { // TODO: remove
- 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}]}";
- }
-
@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}]}";
@@ -90,12 +85,6 @@ public class OneCallWeatherResponseMapperUnitTest {
assertNotNull(currentWeatherData.getAlerts());
}
- @Test
- public void mapToHistorical() {
- final String jsonString = "{\"lat\":60.99,\"lon\":30.9,\"timezone\":\"Europe/Moscow\",\"timezone_offset\":10800,\"current\":{\"dt\":1617739371,\"sunrise\":1617678248,\"sunset\":1617727984,\"snow\":{\"1h\":20},\"temp\":0,\"feels_like\":-10.26,\"pressure\":986,\"humidity\":73,\"dew_point\":-3.77,\"uvi\":1.69,\"clouds\":33,\"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\":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\"}]}]}";
-
- }
-
@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\"}]}]}";
diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherIntegrationTest.java
index cb4ea85..2996967 100644
--- a/src/test/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherIntegrationTest.java
+++ b/src/test/java/com/github/prominence/openweathermap/api/request/weather/multiple/MultipleResultCurrentWeatherIntegrationTest.java
@@ -86,6 +86,34 @@ public class MultipleResultCurrentWeatherIntegrationTest extends ApiTest {
assertTrue(weatherJson.startsWith("{"));
}
+ @Test
+ public void whenGetMultipleCurrentWeatherByCoordinateRectangleAsyncRequestAsJava_thenReturnNotNull() throws ExecutionException, InterruptedException {
+ final CompletableFuture> weatherListFuture = getClient()
+ .currentWeather()
+ .multiple()
+ .byRectangle(CoordinateRectangle.withValues(12, 32, 15, 37), 10)
+ .language(Language.ROMANIAN)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieveAsync()
+ .asJava();
+
+ assertNotNull(weatherListFuture.get());
+ }
+
+ @Test
+ public void whenGetMultipleCurrentWeatherByCoordinateRectangleAsyncRequestAsJSON_thenReturnNotNull() throws ExecutionException, InterruptedException {
+ final CompletableFuture weatherJsonFuture = getClient()
+ .currentWeather()
+ .multiple()
+ .byRectangle(CoordinateRectangle.withValues(12, 32, 15, 37), 10)
+ .language(Language.ROMANIAN)
+ .unitSystem(UnitSystem.METRIC)
+ .retrieveAsync()
+ .asJSON();
+
+ assertTrue(weatherJsonFuture.get().startsWith("{"));
+ }
+
@Test
public void whenGetMultipleCurrentWeatherByCitiesInCycleRequestAsJava_thenReturnNotNull() {
final List weatherList = getClient()
@@ -225,6 +253,21 @@ public class MultipleResultCurrentWeatherIntegrationTest extends ApiTest {
System.out.println(weatherFuture.get());
}
+ @Test
+ public void whenGetMultipleCurrentWeatherByCoordinateAsyncRequestAsXML_thenReturnNotNull() throws ExecutionException, InterruptedException {
+ final CompletableFuture weatherXMLFuture = getClient()
+ .currentWeather()
+ .multiple()
+ .byCitiesInCycle(Coordinate.of(55.5, 37.5), 10)
+ .language(Language.GERMAN)
+ .unitSystem(UnitSystem.IMPERIAL)
+ .retrieveAsync()
+ .asXML();
+
+ assertNotNull(weatherXMLFuture);
+ System.out.println(weatherXMLFuture.get());
+ }
+
@Test
public void whenRequestCurrentWeatherWithInvalidApiKey_thenThrowAnException() {
OpenWeatherMapClient client = new OpenWeatherMapClient("invalidKey");