diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/DayTime.java b/src/main/java/com/github/prominence/openweathermap/api/model/DayTime.java new file mode 100644 index 0000000..4fe093f --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/DayTime.java @@ -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; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/Weather.java b/src/main/java/com/github/prominence/openweathermap/api/model/Weather.java index d94ee11..7baa830 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/model/Weather.java +++ b/src/main/java/com/github/prominence/openweathermap/api/model/Weather.java @@ -224,6 +224,5 @@ public class Weather { stringBuilder.append(snow.getUnit()); } return stringBuilder.toString(); - } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Forecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Forecast.java new file mode 100644 index 0000000..c8ee354 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Forecast.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. + */ + +/* + * 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 weatherForecasts; + + public Location getLocation() { + return location; + } + + public void setLocation(Location location) { + this.location = location; + } + + public List getWeatherForecasts() { + return weatherForecasts; + } + + public void setWeatherForecasts(List weatherForecasts) { + this.weatherForecasts = weatherForecasts; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Forecast forecast = (Forecast) o; + return Objects.equals(location, forecast.location) && Objects.equals(weatherForecasts, forecast.weatherForecasts); + } + + @Override + public int hashCode() { + return Objects.hash(location, weatherForecasts); + } + + @Override + public String toString() { + return "A forecast for " + location.getName() + " with " + weatherForecasts.size() + " timestamps."; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Location.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Location.java new file mode 100644 index 0000000..8025c84 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Location.java @@ -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(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Rain.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Rain.java new file mode 100644 index 0000000..0f1e828 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Rain.java @@ -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(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Snow.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Snow.java new file mode 100644 index 0000000..06ceec9 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Snow.java @@ -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(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Temperature.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Temperature.java new file mode 100644 index 0000000..b01d530 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/Temperature.java @@ -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(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/forecast/WeatherForecast.java b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/WeatherForecast.java new file mode 100644 index 0000000..fd1c8c1 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/forecast/WeatherForecast.java @@ -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(); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminator.java index ee70295..03c3fcb 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminator.java @@ -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, String> { +public interface FiveDayThreeHourStepForecastAsyncRequestTerminator extends AsyncRequestTerminator { CompletableFuture asXML(); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminatorImpl.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminatorImpl.java index aa926fe..286b8df 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminatorImpl.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastAsyncRequestTerminatorImpl.java @@ -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> asJava() { - return CompletableFuture.supplyAsync(() -> new FiveDayThreeHourStepForecastResponseMapper(unitSystem).getTest()); + public CompletableFuture asJava() { + return CompletableFuture.supplyAsync(() -> new FiveDayThreeHourStepForecastResponseMapper(unitSystem).mapToForecast(getRawResponse())); } @Override diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminator.java index e80664b..c1e075c 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminator.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminator.java @@ -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, String> { +public interface FiveDayThreeHourStepForecastRequestTerminator extends RequestTerminator { String asXML(); } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminatorImpl.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminatorImpl.java index 9d61199..3d4ee4b 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminatorImpl.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastRequestTerminatorImpl.java @@ -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 asJava() { - return new FiveDayThreeHourStepForecastResponseMapper(unitSystem).getTest(); + public Forecast asJava() { + return new FiveDayThreeHourStepForecastResponseMapper(unitSystem).mapToForecast(getRawResponse()); } @Override diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastResponseMapper.java index f787c46..9559ed9 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastResponseMapper.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastResponseMapper.java @@ -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 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 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; } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherResponseMapper.java index d19a777..69e81b3 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherResponseMapper.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/weather/CurrentWeatherResponseMapper.java @@ -102,7 +102,7 @@ public class CurrentWeatherResponseMapper implements ResponseMapper { } 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()); diff --git a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastIntegrationTest.java b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastIntegrationTest.java index 4db19af..af0d2ce 100644 --- a/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastIntegrationTest.java +++ b/src/test/java/com/github/prominence/openweathermap/api/request/forecast/free/FiveDayThreeHourStepForecastIntegrationTest.java @@ -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); } }