Implemented free-plan weather forecast retrieving.

This commit is contained in:
Alexey Zinchenko 2021-03-22 01:46:44 +03:00
parent ea39441e83
commit f7741e1df6
15 changed files with 1008 additions and 25 deletions

View File

@ -0,0 +1,38 @@
/*
* 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;
public enum DayTime {
DAY("d"),
NIGHT("n");
private final String value;
DayTime(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}

View File

@ -224,6 +224,5 @@ public class Weather {
stringBuilder.append(snow.getUnit());
}
return stringBuilder.toString();
}
}

View File

@ -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.
*/
/*
* Copyright (c) 2021 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
import java.util.List;
import java.util.Objects;
public class Forecast {
private Location location;
private List<WeatherForecast> weatherForecasts;
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public List<WeatherForecast> getWeatherForecasts() {
return weatherForecasts;
}
public void setWeatherForecasts(List<WeatherForecast> weatherForecasts) {
this.weatherForecasts = weatherForecasts;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Forecast forecast = (Forecast) o;
return Objects.equals(location, forecast.location) && Objects.equals(weatherForecasts, forecast.weatherForecasts);
}
@Override
public int hashCode() {
return Objects.hash(location, weatherForecasts);
}
@Override
public String toString() {
return "A forecast for " + location.getName() + " with " + weatherForecasts.size() + " timestamps.";
}
}

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
import com.github.prominence.openweathermap.api.model.Coordinate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Objects;
public class Location {
private int id;
private String name;
private String countryCode;
private LocalDateTime sunrise;
private LocalDateTime sunset;
private ZoneOffset zoneOffset;
private Coordinate coordinate;
private Long population;
public Location(int id, String name) {
if (name == null) {
throw new IllegalArgumentException("Name must be set.");
}
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public LocalDateTime getSunrise() {
return sunrise;
}
public void setSunrise(LocalDateTime sunrise) {
this.sunrise = sunrise;
}
public LocalDateTime getSunset() {
return sunset;
}
public void setSunset(LocalDateTime sunset) {
this.sunset = sunset;
}
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
public void setZoneOffset(ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset;
}
public Coordinate getCoordinate() {
return coordinate;
}
public void setCoordinate(Coordinate coordinate) {
this.coordinate = coordinate;
}
public Long getPopulation() {
return population;
}
public void setPopulation(Long population) {
this.population = population;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Location)) return false;
Location location = (Location) o;
return id == location.id &&
Objects.equals(name, location.name) &&
Objects.equals(countryCode, location.countryCode) &&
Objects.equals(sunrise, location.sunrise) &&
Objects.equals(sunset, location.sunset) &&
Objects.equals(zoneOffset, location.zoneOffset) &&
Objects.equals(coordinate, location.coordinate) &&
Objects.equals(population, location.population);
}
@Override
public int hashCode() {
return Objects.hash(id, name, countryCode, sunrise, sunset, zoneOffset, coordinate, population);
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();
if (coordinate != null) {
stringBuilder.append(coordinate.toString());
stringBuilder.append(". ");
}
stringBuilder.append("ID: ");
stringBuilder.append(id);
stringBuilder.append(", Name: ");
stringBuilder.append(name);
if (countryCode != null) {
stringBuilder.append('(');
stringBuilder.append(countryCode);
stringBuilder.append(')');
}
if (population != null) {
stringBuilder.append(", Population: ");
stringBuilder.append(population);
}
return stringBuilder.toString();
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
import java.util.Objects;
public class Rain {
private static final String DEFAULT_UNIT = "mm";
private Double threeHourRainLevel;
public Rain() {
}
public Rain(Double threeHourRainLevel) {
this.threeHourRainLevel = threeHourRainLevel;
}
public Double getThreeHourRainLevel() {
return threeHourRainLevel;
}
public void setThreeHourRainLevel(Double threeHourRainLevel) {
this.threeHourRainLevel = threeHourRainLevel;
}
public String getUnit() {
return DEFAULT_UNIT;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Rain)) return false;
Rain rain = (Rain) o;
return Objects.equals(threeHourRainLevel, rain.threeHourRainLevel);
}
@Override
public int hashCode() {
return Objects.hash(threeHourRainLevel);
}
@Override
public String toString() {
StringBuilder snowString = new StringBuilder();
if (threeHourRainLevel == null) {
snowString.append("unknown");
} else {
snowString.append("3 last hours rain level: ");
snowString.append(threeHourRainLevel);
snowString.append(getUnit());
}
return snowString.toString();
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
import java.util.Objects;
public class Snow {
private static final String DEFAULT_UNIT = "mm";
private Double threeHourSnowLevel;
public Snow() {
}
public Snow(Double oneHourSnowLevel, Double threeHourSnowLevel) {
this.threeHourSnowLevel = threeHourSnowLevel;
}
public Double getThreeHourSnowLevel() {
return threeHourSnowLevel;
}
public void setThreeHourSnowLevel(Double threeHourSnowLevel) {
this.threeHourSnowLevel = threeHourSnowLevel;
}
public String getUnit() {
return DEFAULT_UNIT;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Snow)) return false;
Snow snow = (Snow) o;
return Objects.equals(threeHourSnowLevel, snow.threeHourSnowLevel);
}
@Override
public int hashCode() {
return Objects.hash(threeHourSnowLevel);
}
@Override
public String toString() {
StringBuilder snowString = new StringBuilder();
if (threeHourSnowLevel == null) {
snowString.append("unknown");
} else {
snowString.append("3 last hours snow level: ");
snowString.append(threeHourSnowLevel);
snowString.append(getUnit());
}
return snowString.toString();
}
}

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
import java.util.Objects;
public class Temperature {
private double value;
private Double maxTemperature;
private Double minTemperature;
private Double feelsLike;
private String unit;
public Temperature(double value, String unit) {
if (unit == null) {
throw new IllegalArgumentException("Unit must be set.");
}
this.value = value;
this.unit = unit;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public Double getMaxTemperature() {
return maxTemperature;
}
public void setMaxTemperature(Double maxTemperature) {
this.maxTemperature = maxTemperature;
}
public Double getMinTemperature() {
return minTemperature;
}
public void setMinTemperature(Double minTemperature) {
this.minTemperature = minTemperature;
}
public Double getFeelsLike() {
return feelsLike;
}
public void setFeelsLike(Double feelsLike) {
this.feelsLike = feelsLike;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
if (unit == null) {
throw new IllegalArgumentException("Unit must be set.");
}
this.unit = unit;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Temperature)) return false;
Temperature that = (Temperature) o;
return Double.compare(that.value, value) == 0 &&
Objects.equals(maxTemperature, that.maxTemperature) &&
Objects.equals(minTemperature, that.minTemperature) &&
Objects.equals(feelsLike, that.feelsLike) &&
Objects.equals(unit, that.unit);
}
@Override
public int hashCode() {
return Objects.hash(value, maxTemperature, minTemperature, feelsLike, unit);
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Temperature: ");
stringBuilder.append(value);
stringBuilder.append(' ');
stringBuilder.append(unit);
if (maxTemperature != null) {
stringBuilder.append(", Maximum value: ");
stringBuilder.append(maxTemperature);
stringBuilder.append(' ');
stringBuilder.append(unit);
}
if (minTemperature != null) {
stringBuilder.append(", Minimum value: ");
stringBuilder.append(minTemperature);
stringBuilder.append(' ');
stringBuilder.append(unit);
}
if (feelsLike != null) {
stringBuilder.append(", Feels like: ");
stringBuilder.append(feelsLike);
stringBuilder.append(' ');
stringBuilder.append(unit);
}
return stringBuilder.toString();
}
}

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
import com.github.prominence.openweathermap.api.model.Clouds;
import com.github.prominence.openweathermap.api.model.Humidity;
import com.github.prominence.openweathermap.api.model.Pressure;
import com.github.prominence.openweathermap.api.model.Wind;
import com.github.prominence.openweathermap.api.model.DayTime;
import java.time.LocalDateTime;
import java.util.Objects;
public class WeatherForecast {
private LocalDateTime forecastTime;
private Temperature temperature;
private Pressure pressure;
private Humidity humidity;
private String state;
private String description;
private String weatherIconUrl;
private Clouds clouds;
private Wind wind;
private Snow snow;
private Rain rain;
private String forecastTimeISO;
private DayTime dayTime;
public LocalDateTime getForecastTime() {
return forecastTime;
}
public void setForecastTime(LocalDateTime forecastTime) {
this.forecastTime = forecastTime;
}
public Temperature getTemperature() {
return temperature;
}
public void setTemperature(Temperature temperature) {
this.temperature = temperature;
}
public Pressure getPressure() {
return pressure;
}
public void setPressure(Pressure pressure) {
this.pressure = pressure;
}
public Humidity getHumidity() {
return humidity;
}
public void setHumidity(Humidity humidity) {
this.humidity = humidity;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getWeatherIconUrl() {
return weatherIconUrl;
}
public void setWeatherIconUrl(String weatherIconUrl) {
this.weatherIconUrl = weatherIconUrl;
}
public Clouds getClouds() {
return clouds;
}
public void setClouds(Clouds clouds) {
this.clouds = clouds;
}
public Wind getWind() {
return wind;
}
public void setWind(Wind wind) {
this.wind = wind;
}
public Snow getSnow() {
return snow;
}
public void setSnow(Snow snow) {
this.snow = snow;
}
public Rain getRain() {
return rain;
}
public void setRain(Rain rain) {
this.rain = rain;
}
public String getForecastTimeISO() {
return forecastTimeISO;
}
public void setForecastTimeISO(String forecastTimeISO) {
this.forecastTimeISO = forecastTimeISO;
}
public DayTime getDayTime() {
return dayTime;
}
public void setDayTime(DayTime dayTime) {
this.dayTime = dayTime;
}
@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(temperature, that.temperature) &&
Objects.equals(pressure, that.pressure) &&
Objects.equals(humidity, that.humidity) &&
Objects.equals(state, that.state) &&
Objects.equals(description, that.description) &&
Objects.equals(weatherIconUrl, that.weatherIconUrl) &&
Objects.equals(clouds, that.clouds) &&
Objects.equals(wind, that.wind) &&
Objects.equals(snow, that.snow) &&
Objects.equals(rain, that.rain) &&
Objects.equals(forecastTimeISO, that.forecastTimeISO) &&
dayTime == that.dayTime;
}
@Override
public int hashCode() {
return Objects.hash(forecastTime, temperature, pressure, humidity, state, description, weatherIconUrl, clouds, wind, snow, rain, forecastTimeISO, dayTime);
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Timestamp: ");
stringBuilder.append(forecastTimeISO);
stringBuilder.append(", Weather: ");
stringBuilder.append(description);
if (temperature != null) {
stringBuilder.append(", ");
stringBuilder.append(temperature.getValue());
stringBuilder.append(' ');
stringBuilder.append(temperature.getUnit());
}
if (pressure != null) {
stringBuilder.append(", ");
stringBuilder.append(pressure.getValue());
stringBuilder.append(' ');
stringBuilder.append(pressure.getUnit());
}
if (clouds != null) {
stringBuilder.append(", ");
stringBuilder.append(clouds.toString());
}
if (rain != null && rain.getThreeHourRainLevel() != null) {
stringBuilder.append(", Rain: ");
stringBuilder.append(rain.getThreeHourRainLevel());
stringBuilder.append(' ');
stringBuilder.append(rain.getUnit());
}
if (snow != null && snow.getThreeHourSnowLevel() != null) {
stringBuilder.append(", Snow: ");
stringBuilder.append(snow.getThreeHourSnowLevel());
stringBuilder.append(' ');
stringBuilder.append(snow.getUnit());
}
return stringBuilder.toString();
}
}

View File

@ -22,14 +22,13 @@
package com.github.prominence.openweathermap.api.request.forecast.free;
import com.github.prominence.openweathermap.api.model.Weather;
import com.github.prominence.openweathermap.api.model.forecast.Forecast;
import com.github.prominence.openweathermap.api.request.AsyncRequestTerminator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public interface FiveDayThreeHourStepForecastAsyncRequestTerminator extends AsyncRequestTerminator<List<Weather>, String> {
public interface FiveDayThreeHourStepForecastAsyncRequestTerminator extends AsyncRequestTerminator<Forecast, String> {
CompletableFuture<String> asXML();
}

View File

@ -23,11 +23,10 @@
package com.github.prominence.openweathermap.api.request.forecast.free;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.Weather;
import com.github.prominence.openweathermap.api.model.forecast.Forecast;
import com.github.prominence.openweathermap.api.request.RequestUrlBuilder;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class FiveDayThreeHourStepForecastAsyncRequestTerminatorImpl implements FiveDayThreeHourStepForecastAsyncRequestTerminator {
@ -41,8 +40,8 @@ public class FiveDayThreeHourStepForecastAsyncRequestTerminatorImpl implements F
}
@Override
public CompletableFuture<List<Weather>> asJava() {
return CompletableFuture.supplyAsync(() -> new FiveDayThreeHourStepForecastResponseMapper(unitSystem).getTest());
public CompletableFuture<Forecast> asJava() {
return CompletableFuture.supplyAsync(() -> new FiveDayThreeHourStepForecastResponseMapper(unitSystem).mapToForecast(getRawResponse()));
}
@Override

View File

@ -22,13 +22,11 @@
package com.github.prominence.openweathermap.api.request.forecast.free;
import com.github.prominence.openweathermap.api.model.Weather;
import com.github.prominence.openweathermap.api.model.forecast.Forecast;
import com.github.prominence.openweathermap.api.request.RequestTerminator;
import java.util.List;
public interface FiveDayThreeHourStepForecastRequestTerminator extends RequestTerminator<List<Weather>, String> {
public interface FiveDayThreeHourStepForecastRequestTerminator extends RequestTerminator<Forecast, String> {
String asXML();
}

View File

@ -23,12 +23,10 @@
package com.github.prominence.openweathermap.api.request.forecast.free;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.Weather;
import com.github.prominence.openweathermap.api.model.forecast.Forecast;
import com.github.prominence.openweathermap.api.request.RequestUrlBuilder;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
import java.util.List;
public class FiveDayThreeHourStepForecastRequestTerminatorImpl implements FiveDayThreeHourStepForecastRequestTerminator {
private final RequestUrlBuilder urlBuilder;
@ -40,8 +38,8 @@ public class FiveDayThreeHourStepForecastRequestTerminatorImpl implements FiveDa
}
@Override
public List<Weather> asJava() {
return new FiveDayThreeHourStepForecastResponseMapper(unitSystem).getTest();
public Forecast asJava() {
return new FiveDayThreeHourStepForecastResponseMapper(unitSystem).mapToForecast(getRawResponse());
}
@Override

View File

@ -22,10 +22,23 @@
package com.github.prominence.openweathermap.api.request.forecast.free;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.Weather;
import com.github.prominence.openweathermap.api.model.*;
import com.github.prominence.openweathermap.api.model.forecast.*;
import com.github.prominence.openweathermap.api.model.forecast.Location;
import com.github.prominence.openweathermap.api.model.forecast.Rain;
import com.github.prominence.openweathermap.api.model.forecast.Snow;
import com.github.prominence.openweathermap.api.model.forecast.Temperature;
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:
@ -81,7 +94,197 @@ public class FiveDayThreeHourStepForecastResponseMapper {
this.unitSystem = unitSystem;
}
public List<Weather> getTest() {
public Forecast mapToForecast(String json) {
ObjectMapper objectMapper = new ObjectMapper();
Forecast forecast;
try {
JsonNode root = objectMapper.readTree(json);
forecast = mapToForecast(root);
} catch (IOException e) {
throw new RuntimeException("Cannot parse Forecast response");
}
return forecast;
}
private Forecast mapToForecast(JsonNode root) {
Forecast forecast = new Forecast();
forecast.setLocation(parseLocation(root.get("city")));
List<WeatherForecast> forecasts = new ArrayList<>(root.get("cnt").asInt());
JsonNode forecastListNode = root.get("list");
forecastListNode.forEach(forecastNode -> forecasts.add(parseWeatherForecast(forecastNode)));
forecast.setWeatherForecasts(forecasts);
return forecast;
}
private WeatherForecast parseWeatherForecast(JsonNode rootNode) {
WeatherForecast weatherForecast = new WeatherForecast();
weatherForecast.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(rootNode.get("dt").asLong()), TimeZone.getDefault().toZoneId()));
weatherForecast.setForecastTimeISO(rootNode.get("dt_txt").asText());
JsonNode weatherNode = rootNode.get("weather").get(0);
weatherForecast.setState(weatherNode.get("main").asText());
weatherForecast.setDescription(weatherNode.get("description").asText());
weatherForecast.setWeatherIconUrl("https://openweathermap.org/img/w/" + weatherNode.get("icon").asText() + ".png");
JsonNode mainNode = rootNode.get("main");
weatherForecast.setTemperature(parseTemperature(mainNode));
weatherForecast.setPressure(parsePressure(mainNode));
weatherForecast.setHumidity(parseHumidity(mainNode));
weatherForecast.setClouds(parseClouds(rootNode));
weatherForecast.setWind(parseWind(rootNode));
weatherForecast.setRain(parseRain(rootNode));
weatherForecast.setSnow(parseSnow(rootNode));
JsonNode sysNode = rootNode.get("sys");
if (sysNode != null) {
weatherForecast.setDayTime("d".equals(sysNode.get("pod").asText()) ? DayTime.DAY : DayTime.NIGHT);
}
return weatherForecast;
}
private Temperature parseTemperature(JsonNode rootNode) {
final double tempValue = rootNode.get("temp").asDouble();
Temperature temperature = new Temperature(tempValue, UnitSystem.getTemperatureUnit(unitSystem));
final JsonNode tempMaxNode = rootNode.get("temp_max");
if (tempMaxNode != null) {
temperature.setMaxTemperature(tempMaxNode.asDouble());
}
final JsonNode tempMinNode = rootNode.get("temp_min");
if (tempMinNode != null) {
temperature.setMinTemperature(tempMinNode.asDouble());
}
final JsonNode tempFeelsLike = rootNode.get("fells_like");
if (tempFeelsLike != null) {
temperature.setFeelsLike(tempFeelsLike.asDouble());
}
return temperature;
}
private Pressure parsePressure(JsonNode rootNode) {
Pressure pressure = new Pressure(rootNode.get("pressure").asDouble());
final JsonNode seaLevelNode = rootNode.get("sea_level");
final JsonNode groundLevelNode = rootNode.get("grnd_level");
if (seaLevelNode != null) {
pressure.setSeaLevelValue(seaLevelNode.asDouble());
}
if (groundLevelNode != null) {
pressure.setGroundLevelValue(groundLevelNode.asDouble());
}
return pressure;
}
private Humidity parseHumidity(JsonNode rootNode) {
return new Humidity((byte) (rootNode.get("humidity").asInt()));
}
private Wind parseWind(JsonNode root) {
final JsonNode windNode = root.get("wind");
double speed = windNode.get("speed").asDouble();
Wind wind = new Wind(speed, UnitSystem.getWindUnit(unitSystem));
final JsonNode degNode = windNode.get("deg");
if (degNode != null) {
wind.setDegrees(degNode.asDouble());
}
return wind;
}
private Rain parseRain(JsonNode root) {
Rain rain = null;
final JsonNode rainNode = root.get("rain");
if (rainNode != null) {
rain = new Rain();
final JsonNode threeHourNode = rainNode.get("3h");
if (threeHourNode != null) {
rain.setThreeHourRainLevel(threeHourNode.asDouble());
}
}
return rain;
}
private Snow parseSnow(JsonNode root) {
Snow snow = null;
final JsonNode snowNode = root.get("snow");
if (snowNode != null) {
snow = new Snow();
final JsonNode threeHourNode = snowNode.get("3h");
if (threeHourNode != null) {
snow.setThreeHourSnowLevel(threeHourNode.asDouble());
}
}
return snow;
}
private Clouds parseClouds(JsonNode rootNode) {
Clouds clouds = null;
final JsonNode cloudsNode = rootNode.get("clouds");
final JsonNode allValueNode = cloudsNode.get("all");
if (allValueNode != null) {
clouds = new Clouds((byte) allValueNode.asInt());
}
return clouds;
}
private Location parseLocation(JsonNode rootNode) {
Location location = new Location(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.setSunrise(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunriseNode.asLong()), TimeZone.getDefault().toZoneId()));
}
if (sunsetNode != null) {
location.setSunset(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunsetNode.asLong()), TimeZone.getDefault().toZoneId()));
}
final JsonNode coordNode = rootNode.get("coord");
if (coordNode != null) {
location.setCoordinate(parseCoordinate(coordNode));
}
final JsonNode populationNode = rootNode.get("population");
if (populationNode != null) {
location.setPopulation(populationNode.asLong());
}
return location;
}
private Coordinate parseCoordinate(JsonNode rootNode) {
JsonNode latitudeNode = rootNode.get("lat");
JsonNode longitudeNode = rootNode.get("lon");
if (latitudeNode != null && longitudeNode != null) {
return new Coordinate(latitudeNode.asDouble(), longitudeNode.asDouble());
}
return null;
}
}

View File

@ -102,7 +102,7 @@ public class CurrentWeatherResponseMapper implements ResponseMapper<Weather> {
}
private Weather getSingle(JsonNode root) {
final Weather weather;
Weather weather;
JsonNode weatherState = root.get("weather").get(0);
weather = new Weather(weatherState.get("main").asText(), weatherState.get("description").asText());

View File

@ -25,22 +25,23 @@ package com.github.prominence.openweathermap.api.request.forecast.free;
import com.github.prominence.openweathermap.api.ApiTest;
import com.github.prominence.openweathermap.api.enums.Language;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.forecast.Forecast;
import org.junit.Test;
public class FiveDayThreeHourStepForecastIntegrationTest extends ApiTest {
@Test
public void whenGetTest_thenReturnNotNull() {
final String weatherJSON = getClient()
final Forecast forecast = getClient()
.forecast5Day3HourStep()
.byCityName("Minsk")
.language(Language.RUSSIAN)
.language(Language.ENGLISH)
.unitSystem(UnitSystem.METRIC)
.count(15)
.retrieve()
.asJSON();
.asJava();
assert weatherJSON != null;
System.out.println(weatherJSON);
assert forecast != null;
System.out.println(forecast);
}
}