Updated 5 Day / 3 Hour Forecast functionality.

This commit is contained in:
Alexey Zinchenko 2022-05-01 21:21:24 +03:00
parent 7e88fe597c
commit 8a1daa0fe2
10 changed files with 443 additions and 149 deletions

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2022 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.deserializer.forecast.free;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.prominence.openweathermap.api.deserializer.CoordinatesDeserializer;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.model.forecast.free.Location;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.TimeZone;
public class FreeForecastLocationDeserializer extends JsonDeserializer<Location> {
private final ObjectMapper objectMapper = new ObjectMapper();
public FreeForecastLocationDeserializer() {
final SimpleModule module = new SimpleModule();
module.addDeserializer(Coordinates.class, new CoordinatesDeserializer());
objectMapper.registerModule(module);
}
@Override
public Location deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rootNode = p.getCodec().readTree(p);
final Location location = Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText());
final JsonNode timezoneNode = rootNode.get("timezone");
if (timezoneNode != null) {
location.setZoneOffset(ZoneOffset.ofTotalSeconds(timezoneNode.asInt()));
}
final JsonNode countryNode = rootNode.get("country");
if (countryNode != null) {
location.setCountryCode(countryNode.asText());
}
final JsonNode sunriseNode = rootNode.get("sunrise");
final JsonNode sunsetNode = rootNode.get("sunset");
if (sunriseNode != null) {
location.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunriseNode.asLong()), TimeZone.getDefault().toZoneId()));
}
if (sunsetNode != null) {
location.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunsetNode.asLong()), TimeZone.getDefault().toZoneId()));
}
final JsonNode coordNode = rootNode.get("coord");
if (coordNode != null) {
location.setCoordinates(objectMapper.readValue(objectMapper.treeAsTokens(coordNode), Coordinates.class));
}
final JsonNode populationNode = rootNode.get("population");
if (populationNode != null) {
location.setPopulation(populationNode.asLong());
}
return location;
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2022 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.deserializer.forecast.free;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.prominence.openweathermap.api.model.forecast.free.Rain;
import java.io.IOException;
public class FreeForecastRainDeserializer extends JsonDeserializer<Rain> {
@Override
public Rain deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rainNode = p.getCodec().readTree(p);
final JsonNode oneHourNode = rainNode.get("3h");
if (oneHourNode != null) {
return Rain.withThreeHourLevelValue(oneHourNode.asDouble());
}
return null;
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2022 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.deserializer.forecast.free;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.prominence.openweathermap.api.model.forecast.free.Snow;
import java.io.IOException;
public class FreeForecastSnowDeserializer extends JsonDeserializer<Snow> {
@Override
public Snow deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode snowNode = p.getCodec().readTree(p);
final JsonNode oneHourNode = snowNode.get("3h");
if (oneHourNode != null) {
return Snow.withThreeHourLevelValue(oneHourNode.asDouble());
}
return null;
}
}

View File

@ -24,30 +24,23 @@ package com.github.prominence.openweathermap.api.mapper;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.prominence.openweathermap.api.deserializer.AtmosphericPressureDeserializer;
import com.github.prominence.openweathermap.api.deserializer.TemperatureDeserializer;
import com.github.prominence.openweathermap.api.deserializer.WeatherStateDeserializer;
import com.github.prominence.openweathermap.api.deserializer.WindDeserializer;
import com.github.prominence.openweathermap.api.deserializer.*;
import com.github.prominence.openweathermap.api.deserializer.forecast.free.FreeForecastLocationDeserializer;
import com.github.prominence.openweathermap.api.deserializer.forecast.free.FreeForecastRainDeserializer;
import com.github.prominence.openweathermap.api.deserializer.forecast.free.FreeForecastSnowDeserializer;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.*;
import com.github.prominence.openweathermap.api.model.forecast.free.*;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
/**
* Official API response documentation: <a href="https://openweathermap.org/forecast5#JSON">https://openweathermap.org/forecast5#JSON</a>.
*/
public class FiveDayThreeHourStepForecastResponseMapper {
private final ObjectMapper objectMapper = new ObjectMapper();
public class FiveDayThreeHourStepForecastResponseMapper extends AbstractMapper {
/**
* Instantiates a new forecast response mapper.
*
@ -59,7 +52,12 @@ public class FiveDayThreeHourStepForecastResponseMapper {
module.addDeserializer(WeatherState.class, new WeatherStateDeserializer());
module.addDeserializer(Temperature.class, new TemperatureDeserializer());
module.addDeserializer(AtmosphericPressure.class, new AtmosphericPressureDeserializer());
module.addDeserializer(Humidity.class, new HumidityDeserializer());
module.addDeserializer(Clouds.class, new CloudsDeserializer());
module.addDeserializer(Wind.class, new WindDeserializer());
module.addDeserializer(Rain.class, new FreeForecastRainDeserializer());
module.addDeserializer(Snow.class, new FreeForecastSnowDeserializer());
module.addDeserializer(Location.class, new FreeForecastLocationDeserializer());
objectMapper.registerModule(module);
}
@ -83,13 +81,13 @@ public class FiveDayThreeHourStepForecastResponseMapper {
return forecast;
}
private Forecast mapToForecast(JsonNode root) throws IOException {
private Forecast mapToForecast(JsonNode rootNode) throws IOException {
final Forecast forecast = new Forecast();
forecast.setLocation(parseLocation(root.get("city")));
forecast.setLocation(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("city")), Location.class));
final List<WeatherForecast> forecasts = new ArrayList<>(root.get("cnt").asInt());
final List<WeatherForecast> forecasts = new ArrayList<>(rootNode.get("cnt").asInt());
final JsonNode forecastListNode = root.get("list");
final JsonNode forecastListNode = rootNode.get("list");
for (JsonNode forecastNode : forecastListNode) {
forecasts.add(parseWeatherForecast(forecastNode));
}
@ -102,128 +100,38 @@ public class FiveDayThreeHourStepForecastResponseMapper {
private WeatherForecast parseWeatherForecast(JsonNode rootNode) throws IOException {
final WeatherForecast weatherForecast = new WeatherForecast();
final JsonNode weatherArrayNode = rootNode.get("weather");
if (weatherArrayNode != null) {
final JsonNode weatherNode = weatherArrayNode.get(0);
weatherForecast.setWeatherState(parseWeatherState(weatherNode));
}
weatherForecast.setWeatherStates(parseWeatherStates(weatherArrayNode));
final JsonNode mainNode = rootNode.get("main");
weatherForecast.setTemperature(parseTemperature(mainNode));
weatherForecast.setAtmosphericPressure(parsePressure(mainNode));
weatherForecast.setHumidity(parseHumidity(mainNode));
weatherForecast.setClouds(parseClouds(rootNode));
weatherForecast.setWind(parseWind(rootNode));
weatherForecast.setRain(parseRain(rootNode));
weatherForecast.setSnow(parseSnow(rootNode));
weatherForecast.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(mainNode), Temperature.class));
weatherForecast.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(mainNode), AtmosphericPressure.class));
weatherForecast.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(mainNode), Humidity.class));
weatherForecast.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("clouds")), Clouds.class));
weatherForecast.setWind(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("wind")), Wind.class));
if (rootNode.has("rain")) {
weatherForecast.setRain(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("rain")), Rain.class));
}
if (rootNode.has("snow")) {
weatherForecast.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("snow")), Snow.class));
}
final JsonNode sysNode = rootNode.get("sys");
if (sysNode != null) {
weatherForecast.setDayTime("d".equals(sysNode.get("pod").asText()) ? DayTime.DAY : DayTime.NIGHT);
}
weatherForecast.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(rootNode.get("dt").asLong()), TimeZone.getDefault().toZoneId()));
final JsonNode visibilityNode = rootNode.get("visibility");
if (visibilityNode != null) {
weatherForecast.setVisibilityInMetres(visibilityNode.asDouble());
}
final JsonNode popNode = rootNode.get("pop");
if (popNode != null) {
weatherForecast.setProbabilityOfPrecipitation(popNode.asDouble());
}
weatherForecast.setForecastTime(parseDateTime(rootNode.get("dt")));
weatherForecast.setForecastTimeISO(rootNode.get("dt_txt").asText());
return weatherForecast;
}
private WeatherState parseWeatherState(JsonNode weatherNode) throws IOException {
if (weatherNode == null) {
return null;
}
return objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class);
}
private Temperature parseTemperature(JsonNode rootNode) throws IOException {
return objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Temperature.class);
}
private AtmosphericPressure parsePressure(JsonNode rootNode) throws IOException {
return objectMapper.readValue(objectMapper.treeAsTokens(rootNode), AtmosphericPressure.class);
}
private Humidity parseHumidity(JsonNode rootNode) {
return Humidity.withValue((byte) (rootNode.get("humidity").asInt()));
}
private Wind parseWind(JsonNode root) throws IOException {
final JsonNode windNode = root.get("wind");
return objectMapper.readValue(objectMapper.treeAsTokens(windNode), Wind.class);
}
private Rain parseRain(JsonNode root) {
final JsonNode rainNode = root.get("rain");
if (rainNode != null) {
final JsonNode threeHourNode = rainNode.get("3h");
if (threeHourNode != null) {
return Rain.withThreeHourLevelValue(threeHourNode.asDouble());
}
}
return null;
}
private Snow parseSnow(JsonNode root) {
final JsonNode snowNode = root.get("snow");
if (snowNode != null) {
final JsonNode threeHourNode = snowNode.get("3h");
if (threeHourNode != null) {
return Snow.withThreeHourLevelValue(threeHourNode.asDouble());
}
}
return null;
}
private Clouds parseClouds(JsonNode rootNode) {
final JsonNode cloudsNode = rootNode.get("clouds");
final JsonNode allValueNode = cloudsNode.get("all");
if (allValueNode != null) {
return Clouds.withValue((byte) allValueNode.asInt());
}
return null;
}
private Location parseLocation(JsonNode rootNode) {
final Location location = Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText());
final JsonNode timezoneNode = rootNode.get("timezone");
if (timezoneNode != null) {
location.setZoneOffset(ZoneOffset.ofTotalSeconds(timezoneNode.asInt()));
}
final JsonNode countryNode = rootNode.get("country");
if (countryNode != null) {
location.setCountryCode(countryNode.asText());
}
final JsonNode sunriseNode = rootNode.get("sunrise");
final JsonNode sunsetNode = rootNode.get("sunset");
if (sunriseNode != null) {
location.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunriseNode.asLong()), TimeZone.getDefault().toZoneId()));
}
if (sunsetNode != null) {
location.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunsetNode.asLong()), TimeZone.getDefault().toZoneId()));
}
final JsonNode coordNode = rootNode.get("coord");
if (coordNode != null) {
location.setCoordinates(parseCoordinate(coordNode));
}
final JsonNode populationNode = rootNode.get("population");
if (populationNode != null) {
location.setPopulation(populationNode.asLong());
}
return location;
}
private Coordinates parseCoordinate(JsonNode rootNode) {
final JsonNode latitudeNode = rootNode.get("lat");
final JsonNode longitudeNode = rootNode.get("lon");
if (latitudeNode != null && longitudeNode != null) {
return Coordinates.of(latitudeNode.asDouble(), longitudeNode.asDouble());
}
return null;
}
}

View File

@ -25,6 +25,7 @@ package com.github.prominence.openweathermap.api.model.forecast.free;
import com.github.prominence.openweathermap.api.model.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
@ -33,7 +34,7 @@ import java.util.Objects;
public class WeatherForecast {
private LocalDateTime forecastTime;
private WeatherState weatherState;
private List<WeatherState> weatherStates;
private Temperature temperature;
private AtmosphericPressure atmosphericPressure;
private Humidity humidity;
@ -46,6 +47,9 @@ public class WeatherForecast {
private String forecastTimeISO;
private DayTime dayTime;
private Double visibilityInMetres;
private Double probabilityOfPrecipitation;
/**
* Gets forecast time.
*
@ -69,17 +73,17 @@ public class WeatherForecast {
*
* @return the weather state
*/
public WeatherState getWeatherState() {
return weatherState;
public List<WeatherState> getWeatherStates() {
return weatherStates;
}
/**
* Sets weather state.
*
* @param weatherState the weather state
* @param weatherStates the weather state
*/
public void setWeatherState(WeatherState weatherState) {
this.weatherState = weatherState;
public void setWeatherStates(List<WeatherState> weatherStates) {
this.weatherStates = weatherStates;
}
/**
@ -244,13 +248,29 @@ public class WeatherForecast {
this.dayTime = dayTime;
}
public Double getVisibilityInMetres() {
return visibilityInMetres;
}
public void setVisibilityInMetres(Double visibilityInMetres) {
this.visibilityInMetres = visibilityInMetres;
}
public Double getProbabilityOfPrecipitation() {
return probabilityOfPrecipitation;
}
public void setProbabilityOfPrecipitation(Double probabilityOfPrecipitation) {
this.probabilityOfPrecipitation = probabilityOfPrecipitation;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WeatherForecast that = (WeatherForecast) o;
return Objects.equals(forecastTime, that.forecastTime) &&
Objects.equals(weatherState, that.weatherState) &&
Objects.equals(weatherStates, that.weatherStates) &&
Objects.equals(temperature, that.temperature) &&
Objects.equals(atmosphericPressure, that.atmosphericPressure) &&
Objects.equals(humidity, that.humidity) &&
@ -259,12 +279,14 @@ public class WeatherForecast {
Objects.equals(snow, that.snow) &&
Objects.equals(clouds, that.clouds) &&
Objects.equals(forecastTimeISO, that.forecastTimeISO) &&
Objects.equals(visibilityInMetres, that.visibilityInMetres) &&
Objects.equals(probabilityOfPrecipitation, that.probabilityOfPrecipitation) &&
dayTime == that.dayTime;
}
@Override
public int hashCode() {
return Objects.hash(forecastTime, weatherState, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, forecastTimeISO, dayTime);
return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, forecastTimeISO, visibilityInMetres, probabilityOfPrecipitation, dayTime);
}
@Override
@ -272,9 +294,9 @@ public class WeatherForecast {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Timestamp: ");
stringBuilder.append(forecastTimeISO);
if (weatherState != null) {
if (weatherStates != null && weatherStates.size() > 0) {
stringBuilder.append(", Weather: ");
stringBuilder.append(weatherState.getDescription());
stringBuilder.append(weatherStates.get(0).getDescription());
}
if (temperature != null) {
stringBuilder.append(", ");

View File

@ -46,16 +46,19 @@ public class FiveDayThreeHourStepForecastRequester {
return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings);
}
@Deprecated
public FiveDayThreeHourStepForecastRequestCustomizer byCityName(String cityName, String stateCode) {
requestSettings.putRequestParameter("q", cityName + "," + stateCode);
return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings);
}
@Deprecated
public FiveDayThreeHourStepForecastRequestCustomizer byCityName(String cityName, String stateCode, String countryCode) {
requestSettings.putRequestParameter("q", cityName + "," + stateCode + "," + countryCode);
return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings);
}
@Deprecated
public FiveDayThreeHourStepForecastRequestCustomizer byCityId(long cityId) {
requestSettings.putRequestParameter("id", Long.toString(cityId));
return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings);
@ -67,11 +70,13 @@ public class FiveDayThreeHourStepForecastRequester {
return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings);
}
@Deprecated
public FiveDayThreeHourStepForecastRequestCustomizer byZipCodeAndCountry(String zipCode, String countryCode) {
requestSettings.putRequestParameter("zip", zipCode + "," + countryCode);
return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings);
}
@Deprecated
public FiveDayThreeHourStepForecastRequestCustomizer byZipCodeInUSA(String zipCode) {
requestSettings.putRequestParameter("zip", zipCode);
return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings);

View File

@ -0,0 +1,183 @@
package com.github.prominence.openweathermap.api.mapper;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.*;
import com.github.prominence.openweathermap.api.model.forecast.free.*;
import com.github.prominence.openweathermap.api.utils.TestMappingUtils;
import org.junit.jupiter.api.Test;
import java.time.ZoneOffset;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class FiveDayThreeHourStepForecastResponseMapperTest {
@Test
void mapToForecast() {
final String jsonResponse = """
{
"cod": "200",
"message": 0,
"cnt": 40,
"list": [
{
"dt": 1647345600,
"main": {
"temp": 286.88,
"feels_like": 285.93,
"temp_min": 286.74,
"temp_max": 286.88,
"pressure": 1021,
"sea_level": 1021,
"grnd_level": 1018,
"humidity": 62,
"temp_kf": 0.14
},
"weather": [
{
"id": 804,
"main": "Clouds",
"description": "overcast clouds",
"icon": "04d"
}
],
"clouds": {
"all": 85
},
"wind": {
"speed": 3.25,
"deg": 134,
"gust": 4.45
},
"visibility": 10000,
"pop": 0,
"sys": {
"pod": "d"
},
"rain": {
"3h": 22.1
},
"snow": {
"3h": 13.6
},
"dt_txt": "2022-03-15 12:00:00"
},
{
"dt": 1647356400,
"main": {
"temp": 286.71,
"feels_like": 285.77,
"temp_min": 286.38,
"temp_max": 286.71,
"pressure": 1021,
"sea_level": 1021,
"grnd_level": 1017,
"humidity": 63,
"temp_kf": 0.33
},
"weather": [
{
"id": 804,
"main": "Clouds",
"description": "overcast clouds",
"icon": "04d"
}
],
"clouds": {
"all": 90
},
"wind": {
"speed": 3.34,
"deg": 172,
"gust": 4.03
},
"visibility": 10000,
"pop": 0,
"sys": {
"pod": "d"
},
"dt_txt": "2022-03-15 15:00:00"
}
],
"city": {
"id": 2643743,
"name": "London",
"coord": {
"lat": 51.5073,
"lon": -0.1277
},
"country": "GB",
"population": 1000000,
"timezone": 0,
"sunrise": 1647324903,
"sunset": 1647367441
}
}
""";
final Forecast forecast = new FiveDayThreeHourStepForecastResponseMapper(UnitSystem.METRIC).mapToForecast(jsonResponse);
assertNotNull(forecast);
final Location location = forecast.getLocation();
assertNotNull(location);
assertEquals(Coordinates.of(51.5073, -0.1277), location.getCoordinates());
assertEquals(2643743, location.getId());
assertEquals("London", location.getName());
assertEquals("GB", location.getCountryCode());
assertEquals(1000000, location.getPopulation());
assertEquals(TestMappingUtils.parseDateTime(1647324903), location.getSunriseTime());
assertEquals(TestMappingUtils.parseDateTime(1647367441), location.getSunsetTime());
assertEquals(ZoneOffset.ofTotalSeconds(0), location.getZoneOffset());
final List<WeatherForecast> weatherForecastList = forecast.getWeatherForecasts();
assertEquals(2, weatherForecastList.size());
final WeatherForecast weatherForecast = weatherForecastList.get(0);
assertNotNull(weatherForecast);
assertEquals(TestMappingUtils.parseDateTime(1647345600), weatherForecast.getForecastTime());
assertEquals(10000, weatherForecast.getVisibilityInMetres());
assertEquals(0, weatherForecast.getProbabilityOfPrecipitation());
assertEquals("2022-03-15 12:00:00", weatherForecast.getForecastTimeISO());
assertEquals(DayTime.DAY, weatherForecast.getDayTime());
final Temperature temperature = weatherForecast.getTemperature();
assertNotNull(temperature);
assertEquals(286.88, temperature.getValue());
assertEquals(285.93, temperature.getFeelsLike());
assertEquals(286.74, temperature.getMinTemperature());
assertEquals(286.88, temperature.getMaxTemperature());
final AtmosphericPressure pressure = weatherForecast.getAtmosphericPressure();
assertEquals(1021, pressure.getValue());
assertEquals(1021, pressure.getSeaLevelValue());
assertEquals(1018, pressure.getGroundLevelValue());
final Humidity humidity = weatherForecast.getHumidity();
assertEquals(62, humidity.getValue());
final Clouds clouds = weatherForecast.getClouds();
assertEquals(85, clouds.getValue());
final Wind wind = weatherForecast.getWind();
assertEquals(3.25, wind.getSpeed());
assertEquals(134, wind.getDegrees());
assertEquals(4.45, wind.getGust());
assertEquals(1, weatherForecast.getWeatherStates().size());
final WeatherState weatherState = weatherForecast.getWeatherStates().get(0);
assertEquals(804, weatherState.getId());
assertEquals("Clouds", weatherState.getName());
assertEquals("overcast clouds", weatherState.getDescription());
assertEquals("04d", weatherState.getIconId());
final Rain rain = weatherForecast.getRain();
assertEquals(22.1, rain.getThreeHourLevel());
final Snow snow = weatherForecast.getSnow();
assertEquals(13.6, snow.getThreeHourLevel());
}
}

View File

@ -26,6 +26,7 @@ import com.github.prominence.openweathermap.api.model.*;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@ -138,7 +139,7 @@ public class WeatherForecastUnitTest {
assertNotEquals("", weatherForecast.toString());
assertNotNull(weatherForecast.toString());
weatherForecast.setWeatherState(weatherState);
weatherForecast.setWeatherStates(List.of(weatherState));
assertNotEquals("", weatherForecast.toString());
assertNotNull(weatherForecast.toString());
@ -224,11 +225,11 @@ public class WeatherForecastUnitTest {
assertEquals(first, second);
final WeatherState weatherState = new WeatherState(800, "Clear", "clear sky");
first.setWeatherState(weatherState);
first.setWeatherStates(List.of(weatherState));
assertNotEquals(first, second);
second.setWeatherState(weatherState);
second.setWeatherStates(List.of(weatherState));
assertEquals(first, second);

View File

@ -54,7 +54,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest {
assertNotNull(forecast.getLocation());
assertNotNull(forecast.getWeatherForecasts());
for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) {
assertNotNull(weatherForecast.getWeatherState());
assertNotNull(weatherForecast.getWeatherStates());
assertNotNull(weatherForecast.getForecastTime());
assertNotNull(weatherForecast.getTemperature());
assertNotNull(weatherForecast.getAtmosphericPressure());
@ -106,7 +106,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest {
assertNotNull(forecast.getLocation());
assertNotNull(forecast.getWeatherForecasts());
for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) {
assertNotNull(weatherForecast.getWeatherState());
assertNotNull(weatherForecast.getWeatherStates());
assertNotNull(weatherForecast.getForecastTime());
assertNotNull(weatherForecast.getTemperature());
assertNotNull(weatherForecast.getAtmosphericPressure());
@ -158,7 +158,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest {
assertNotNull(forecast.getLocation());
assertNotNull(forecast.getWeatherForecasts());
for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) {
assertNotNull(weatherForecast.getWeatherState());
assertNotNull(weatherForecast.getWeatherStates());
assertNotNull(weatherForecast.getForecastTime());
assertNotNull(weatherForecast.getTemperature());
assertNotNull(weatherForecast.getAtmosphericPressure());
@ -209,7 +209,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest {
assertNotNull(forecast.getLocation());
assertNotNull(forecast.getWeatherForecasts());
for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) {
assertNotNull(weatherForecast.getWeatherState());
assertNotNull(weatherForecast.getWeatherStates());
assertNotNull(weatherForecast.getForecastTime());
assertNotNull(weatherForecast.getTemperature());
assertNotNull(weatherForecast.getAtmosphericPressure());
@ -260,7 +260,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest {
assertNotNull(forecast.getLocation());
assertNotNull(forecast.getWeatherForecasts());
for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) {
assertNotNull(weatherForecast.getWeatherState());
assertNotNull(weatherForecast.getWeatherStates());
assertNotNull(weatherForecast.getForecastTime());
assertNotNull(weatherForecast.getTemperature());
assertNotNull(weatherForecast.getAtmosphericPressure());
@ -311,7 +311,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest {
assertNotNull(forecast.getLocation());
assertNotNull(forecast.getWeatherForecasts());
for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) {
assertNotNull(weatherForecast.getWeatherState());
assertNotNull(weatherForecast.getWeatherStates());
assertNotNull(weatherForecast.getForecastTime());
assertNotNull(weatherForecast.getTemperature());
assertNotNull(weatherForecast.getAtmosphericPressure());
@ -362,7 +362,7 @@ public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest {
assertNotNull(forecast.getLocation());
assertNotNull(forecast.getWeatherForecasts());
for (WeatherForecast weatherForecast : forecast.getWeatherForecasts()) {
assertNotNull(weatherForecast.getWeatherState());
assertNotNull(weatherForecast.getWeatherStates());
assertNotNull(weatherForecast.getForecastTime());
assertNotNull(weatherForecast.getTemperature());
assertNotNull(weatherForecast.getAtmosphericPressure());

View File

@ -56,7 +56,7 @@ public class FiveDayThreeHourStepForecastResponseMapperUnitTest {
assertNotNull(forecast);
assertNotNull(forecast.getLocation());
assertNotNull(forecast.getWeatherForecasts());
forecast.getWeatherForecasts().forEach(weatherForecast -> assertNull(weatherForecast.getWeatherState()));
forecast.getWeatherForecasts().forEach(weatherForecast -> assertNull(weatherForecast.getWeatherStates()));
}
@Test