From 6c1a1642f1b4935e692d011b768e7a62afb0ab2f Mon Sep 17 00:00:00 2001 From: Alexey Zinchenko Date: Mon, 2 May 2022 01:19:19 +0300 Subject: [PATCH] Implemented first part of Road Risk API. --- README.md | 1 + docs/SNAPSHOT.md | 1 + .../api/OpenWeatherMapClient.java | 10 +++ .../roadrisk/RoadRiskAlertDeserializer.java | 23 +++++ .../RoadRiskRoadDetailsDeserializer.java | 23 +++++ .../roadrisk/RoadRiskWeatherDeserializer.java | 31 +++++++ .../openweathermap/api/enums/EventLevel.java | 25 ++++++ .../openweathermap/api/enums/RoadState.java | 39 +++++++++ .../api/mapper/RoadRiskResponseMapper.java | 72 ++++++++++++++++ .../api/model/roadrisk/Alert.java | 57 ++++++++++++ .../api/model/roadrisk/RoadDetails.java | 47 ++++++++++ .../api/model/roadrisk/RoadRiskRecord.java | 81 +++++++++++++++++ .../api/model/roadrisk/TrackPoint.java | 48 +++++++++++ .../api/model/roadrisk/Weather.java | 86 +++++++++++++++++++ .../api/request/RequestSettings.java | 8 ++ .../RoadRiskAsyncRequestTerminator.java | 70 +++++++++++++++ .../roadrisk/RoadRiskRequestCustomizer.java | 19 ++++ .../roadrisk/RoadRiskRequestTerminator.java | 61 +++++++++++++ .../request/roadrisk/RoadRiskRequester.java | 20 +++++ .../api/utils/RequestUtils.java | 1 + .../mapper/RoadRiskResponseMapperTest.java | 67 +++++++++++++++ 21 files changed, 790 insertions(+) create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskAlertDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskRoadDetailsDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskWeatherDeserializer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/enums/EventLevel.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/enums/RoadState.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapper.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Alert.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadDetails.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskRecord.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/TrackPoint.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Weather.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskAsyncRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestCustomizer.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestTerminator.java create mode 100644 src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequester.java create mode 100644 src/test/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapperTest.java diff --git a/README.md b/README.md index a90c113..b23ea83 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Paid: * Daily Forecast 16 days * Climatic 30 days * Solar Radiation API +* Road Risk API Other: * Request timeout settings diff --git a/docs/SNAPSHOT.md b/docs/SNAPSHOT.md index 10314a8..bb55362 100644 --- a/docs/SNAPSHOT.md +++ b/docs/SNAPSHOT.md @@ -5,6 +5,7 @@ * Daily forecast * Solar Radiation API * 5 day / 3-hour forecast +* Road Risk API * Air Pollution * Geocoding API diff --git a/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java b/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java index 15c2649..78e050b 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java +++ b/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java @@ -33,6 +33,7 @@ import com.github.prominence.openweathermap.api.request.forecast.hourly.FourDays import com.github.prominence.openweathermap.api.request.geocoding.GeocodingRequester; import com.github.prominence.openweathermap.api.request.onecall.OneCallWeatherRequester; import com.github.prominence.openweathermap.api.request.radiation.SolarRadiationRequester; +import com.github.prominence.openweathermap.api.request.roadrisk.RoadRiskRequester; import com.github.prominence.openweathermap.api.request.weather.CurrentWeatherRequester; import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.*; @@ -125,6 +126,15 @@ public class OpenWeatherMapClient { return new FiveDayThreeHourStepForecastRequester(new RequestSettings(apiKey, timeoutSettings)); } + /** + * Road Risk API. + * @return requester for retrieving road risk information. + */ + @SubscriptionAvailability(plans = SPECIAL) + public RoadRiskRequester roadRisk() { + return new RoadRiskRequester(new RequestSettings(apiKey, timeoutSettings)); + } + /** * Air Pollution API. * Air Pollution API provides current, forecast and historical air pollution data for any coordinates on the globe. diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskAlertDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskAlertDeserializer.java new file mode 100644 index 0000000..eb37528 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskAlertDeserializer.java @@ -0,0 +1,23 @@ +package com.github.prominence.openweathermap.api.deserializer.roadrisk; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.enums.EventLevel; +import com.github.prominence.openweathermap.api.model.roadrisk.Alert; + +import java.io.IOException; + +public class RoadRiskAlertDeserializer extends JsonDeserializer { + @Override + public Alert deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { + final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); + final Alert alert = new Alert(); + alert.setEvent(rootNode.get("event").asText()); + alert.setSenderName(rootNode.get("sender_name").asText()); + alert.setEventLevel(EventLevel.findByValue(rootNode.get("event_level").asInt())); + return alert; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskRoadDetailsDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskRoadDetailsDeserializer.java new file mode 100644 index 0000000..943fcf6 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskRoadDetailsDeserializer.java @@ -0,0 +1,23 @@ +package com.github.prominence.openweathermap.api.deserializer.roadrisk; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.enums.RoadState; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadDetails; + +import java.io.IOException; + +public class RoadRiskRoadDetailsDeserializer extends JsonDeserializer { + @Override + public RoadDetails deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { + final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); + final RoadDetails roadDetails = new RoadDetails(); + roadDetails.setSurfaceTemperature(rootNode.get("temp").asDouble()); + roadDetails.setRoadState(RoadState.findByValue(rootNode.get("state").asInt())); + + return roadDetails; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskWeatherDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskWeatherDeserializer.java new file mode 100644 index 0000000..8627a96 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/roadrisk/RoadRiskWeatherDeserializer.java @@ -0,0 +1,31 @@ +package com.github.prominence.openweathermap.api.deserializer.roadrisk; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.prominence.openweathermap.api.model.roadrisk.Weather; + +import java.io.IOException; + +public class RoadRiskWeatherDeserializer extends JsonDeserializer { + @Override + public Weather deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { + final JsonNode rootNode = jsonParser.getCodec().readTree(jsonParser); + + final Weather weather = new Weather(); + weather.setTemperature(rootNode.get("temp").asDouble()); + weather.setDewPoint(rootNode.get("dew_point").asDouble()); + weather.setWindSpeed(rootNode.get("wind_speed").asDouble()); + weather.setWindDegrees(rootNode.get("wind_deg").asDouble()); + if (rootNode.has("precipitation_intensity")) { + weather.setPrecipitationIntensity(rootNode.get("precipitation_intensity").asDouble()); + } + if (rootNode.has("visibility")) { + weather.setVisibilityInMetres(rootNode.get("visibility").asDouble()); + } + + return weather; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/EventLevel.java b/src/main/java/com/github/prominence/openweathermap/api/enums/EventLevel.java new file mode 100644 index 0000000..7133a2c --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/EventLevel.java @@ -0,0 +1,25 @@ +package com.github.prominence.openweathermap.api.enums; + +import java.util.Arrays; + +public enum EventLevel { + UNKNOWN(0), + GREEN(1), + YELLOW(2), + ORANGE(3), + RED(4); + + private final int value; + + EventLevel(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static EventLevel findByValue(int value) { + return Arrays.stream(values()).filter(eventLevel -> eventLevel.getValue() == value).findFirst().orElse(null); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/enums/RoadState.java b/src/main/java/com/github/prominence/openweathermap/api/enums/RoadState.java new file mode 100644 index 0000000..fe2f2f2 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/enums/RoadState.java @@ -0,0 +1,39 @@ +package com.github.prominence.openweathermap.api.enums; + +import java.util.Arrays; + +public enum RoadState { + NO_REPORT(0), + DRY(1), + MOIST(2), + MOIST_AND_CHEMICALLY_TREATED(3), + WET(4), + WET_AND_CHEMICALLY_TREATED(5), + ICE(6), + FROST(7), + SNOW(8), + SNOW_OR_ICE_WATCH(9), + SNOW_OR_ICE_WARNING(10), + WET_ABOVE_FREEZING(11), + WET_BELOW_FREEZING(12), + ABSORPTION(13), + ABSORPTION_AT_DEWPOINT(14), + DEW(15), + BLACK_ICE_WARNING(16), + OTHER(17), + SLUSH(18); + + private final int value; + + RoadState(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static RoadState findByValue(int value) { + return Arrays.stream(values()).filter(roadState -> roadState.getValue() == value).findFirst().orElse(null); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapper.java b/src/main/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapper.java new file mode 100644 index 0000000..cd62814 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapper.java @@ -0,0 +1,72 @@ +package com.github.prominence.openweathermap.api.mapper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.github.prominence.openweathermap.api.deserializer.roadrisk.RoadRiskAlertDeserializer; +import com.github.prominence.openweathermap.api.deserializer.roadrisk.RoadRiskRoadDetailsDeserializer; +import com.github.prominence.openweathermap.api.deserializer.roadrisk.RoadRiskWeatherDeserializer; +import com.github.prominence.openweathermap.api.model.Coordinates; +import com.github.prominence.openweathermap.api.model.roadrisk.Alert; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadDetails; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskRecord; +import com.github.prominence.openweathermap.api.model.roadrisk.Weather; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class RoadRiskResponseMapper extends AbstractMapper { + + public RoadRiskResponseMapper() { + final SimpleModule module = new SimpleModule(); + module.addDeserializer(Weather.class, new RoadRiskWeatherDeserializer()); + module.addDeserializer(RoadDetails.class, new RoadRiskRoadDetailsDeserializer()); + module.addDeserializer(Alert.class, new RoadRiskAlertDeserializer()); + objectMapper.registerModule(module); + } + + public List mapToObjects(String jsonResponse) { + List roadRiskRecords; + try { + final JsonNode root = objectMapper.readTree(jsonResponse); + roadRiskRecords = mapToObjects(root); + } catch (IOException e) { + throw new RuntimeException("Cannot parse SolarRadiation response", e); + } + + return roadRiskRecords; + } + + private List mapToObjects(JsonNode rootNode) throws IOException { + List roadRiskRecords = new ArrayList<>(); + + if (rootNode.isArray()) { + for (JsonNode recordNode : rootNode) { + RoadRiskRecord roadRiskRecord = new RoadRiskRecord(); + roadRiskRecord.setForecastTime(parseDateTime(recordNode.get("dt"))); + + final JsonNode coordNode = recordNode.get("coord"); + roadRiskRecord.setCoordinates(Coordinates.of(coordNode.get(0).asDouble(), coordNode.get(1).asDouble())); + + roadRiskRecord.setWeather(objectMapper.readValue(objectMapper.treeAsTokens(recordNode.get("weather")), Weather.class)); + if (recordNode.has("road")) { + roadRiskRecord.setRoadDetails(objectMapper.readValue(objectMapper.treeAsTokens(recordNode.get("road")), RoadDetails.class)); + } + + final JsonNode alertsNode = recordNode.get("alerts"); + if (alertsNode != null && alertsNode.isArray()) { + List alerts = new ArrayList<>(); + for (JsonNode alertNode : alertsNode) { + alerts.add(objectMapper.readValue(objectMapper.treeAsTokens(alertNode), Alert.class)); + } + + roadRiskRecord.setAlerts(alerts); + } + + roadRiskRecords.add(roadRiskRecord); + } + } + + return roadRiskRecords; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Alert.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Alert.java new file mode 100644 index 0000000..056fd37 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Alert.java @@ -0,0 +1,57 @@ +package com.github.prominence.openweathermap.api.model.roadrisk; + +import com.github.prominence.openweathermap.api.enums.EventLevel; + +import java.util.Objects; + +public class Alert { + private String senderName; + private String event; + private EventLevel eventLevel; + + public String getSenderName() { + return senderName; + } + + public void setSenderName(String senderName) { + this.senderName = senderName; + } + + public String getEvent() { + return event; + } + + public void setEvent(String event) { + this.event = event; + } + + public EventLevel getEventLevel() { + return eventLevel; + } + + public void setEventLevel(EventLevel eventLevel) { + this.eventLevel = eventLevel; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Alert alert = (Alert) o; + return Objects.equals(senderName, alert.senderName) && Objects.equals(event, alert.event) && eventLevel == alert.eventLevel; + } + + @Override + public int hashCode() { + return Objects.hash(senderName, event, eventLevel); + } + + @Override + public String toString() { + return "Alert{" + + "senderName='" + senderName + '\'' + + ", event='" + event + '\'' + + ", eventLevel=" + eventLevel + + '}'; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadDetails.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadDetails.java new file mode 100644 index 0000000..8b6618b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadDetails.java @@ -0,0 +1,47 @@ +package com.github.prominence.openweathermap.api.model.roadrisk; + +import com.github.prominence.openweathermap.api.enums.RoadState; + +import java.util.Objects; + +public class RoadDetails { + private RoadState roadState; + private Double surfaceTemperature; + + public RoadState getRoadState() { + return roadState; + } + + public void setRoadState(RoadState roadState) { + this.roadState = roadState; + } + + public Double getSurfaceTemperature() { + return surfaceTemperature; + } + + public void setSurfaceTemperature(Double surfaceTemperature) { + this.surfaceTemperature = surfaceTemperature; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RoadDetails that = (RoadDetails) o; + return roadState == that.roadState && Objects.equals(surfaceTemperature, that.surfaceTemperature); + } + + @Override + public int hashCode() { + return Objects.hash(roadState, surfaceTemperature); + } + + @Override + public String toString() { + return "RoadDetails{" + + "roadState=" + roadState + + ", surfaceTemperature=" + surfaceTemperature + + '}'; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskRecord.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskRecord.java new file mode 100644 index 0000000..c94a11b --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/RoadRiskRecord.java @@ -0,0 +1,81 @@ +package com.github.prominence.openweathermap.api.model.roadrisk; + +import com.github.prominence.openweathermap.api.model.Coordinates; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + +public class RoadRiskRecord { + private LocalDateTime forecastTime; + private Coordinates coordinates; + + private Weather weather; + private RoadDetails roadDetails; + + private List alerts; + + public LocalDateTime getForecastTime() { + return forecastTime; + } + + public void setForecastTime(LocalDateTime forecastTime) { + this.forecastTime = forecastTime; + } + + public Coordinates getCoordinates() { + return coordinates; + } + + public void setCoordinates(Coordinates coordinates) { + this.coordinates = coordinates; + } + + public Weather getWeather() { + return weather; + } + + public void setWeather(Weather weather) { + this.weather = weather; + } + + public RoadDetails getRoadDetails() { + return roadDetails; + } + + public void setRoadDetails(RoadDetails roadDetails) { + this.roadDetails = roadDetails; + } + + public List getAlerts() { + return alerts; + } + + public void setAlerts(List alerts) { + this.alerts = alerts; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RoadRiskRecord record = (RoadRiskRecord) o; + return Objects.equals(forecastTime, record.forecastTime) && Objects.equals(coordinates, record.coordinates) && Objects.equals(weather, record.weather) && Objects.equals(roadDetails, record.roadDetails) && Objects.equals(alerts, record.alerts); + } + + @Override + public int hashCode() { + return Objects.hash(forecastTime, coordinates, weather, roadDetails, alerts); + } + + @Override + public String toString() { + return "RoadRiskRecord{" + + "forecastTime=" + forecastTime + + ", coordinates=" + coordinates + + ", weather=" + weather + + ", roadDetails=" + roadDetails + + ", alerts=" + alerts + + '}'; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/TrackPoint.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/TrackPoint.java new file mode 100644 index 0000000..22de4dd --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/TrackPoint.java @@ -0,0 +1,48 @@ +package com.github.prominence.openweathermap.api.model.roadrisk; + +import com.github.prominence.openweathermap.api.model.Coordinates; + +import java.time.LocalDateTime; +import java.util.Objects; + +public class TrackPoint { + private Coordinates coordinates; + private LocalDateTime requestedTime; + + public Coordinates getCoordinates() { + return coordinates; + } + + public void setCoordinates(Coordinates coordinates) { + this.coordinates = coordinates; + } + + public LocalDateTime getRequestedTime() { + return requestedTime; + } + + public void setRequestedTime(LocalDateTime requestedTime) { + this.requestedTime = requestedTime; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TrackPoint that = (TrackPoint) o; + return Objects.equals(coordinates, that.coordinates) && Objects.equals(requestedTime, that.requestedTime); + } + + @Override + public int hashCode() { + return Objects.hash(coordinates, requestedTime); + } + + @Override + public String toString() { + return "TrackPoint{" + + "coordinates=" + coordinates + + ", requestedTime=" + requestedTime + + '}'; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Weather.java b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Weather.java new file mode 100644 index 0000000..5d3d4db --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/model/roadrisk/Weather.java @@ -0,0 +1,86 @@ +package com.github.prominence.openweathermap.api.model.roadrisk; + +import java.util.Objects; + +public class Weather { + + private Double temperature; + private Double windSpeed; + private Double windDegrees; + private Double precipitationIntensity; + private Double visibilityInMetres; + private Double dewPoint; + + public Double getTemperature() { + return temperature; + } + + public void setTemperature(Double temperature) { + this.temperature = temperature; + } + + public Double getWindSpeed() { + return windSpeed; + } + + public void setWindSpeed(Double windSpeed) { + this.windSpeed = windSpeed; + } + + public Double getWindDegrees() { + return windDegrees; + } + + public void setWindDegrees(Double windDegrees) { + this.windDegrees = windDegrees; + } + + public Double getPrecipitationIntensity() { + return precipitationIntensity; + } + + public void setPrecipitationIntensity(Double precipitationIntensity) { + this.precipitationIntensity = precipitationIntensity; + } + + public Double getVisibilityInMetres() { + return visibilityInMetres; + } + + public void setVisibilityInMetres(Double visibilityInMetres) { + this.visibilityInMetres = visibilityInMetres; + } + + public Double getDewPoint() { + return dewPoint; + } + + public void setDewPoint(Double dewPoint) { + this.dewPoint = dewPoint; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Weather weather = (Weather) o; + return Objects.equals(temperature, weather.temperature) && Objects.equals(windSpeed, weather.windSpeed) && Objects.equals(windDegrees, weather.windDegrees) && Objects.equals(precipitationIntensity, weather.precipitationIntensity) && Objects.equals(visibilityInMetres, weather.visibilityInMetres) && Objects.equals(dewPoint, weather.dewPoint); + } + + @Override + public int hashCode() { + return Objects.hash(temperature, windSpeed, windDegrees, precipitationIntensity, visibilityInMetres, dewPoint); + } + + @Override + public String toString() { + return "Weather{" + + "temperature=" + temperature + + ", windSpeed=" + windSpeed + + ", windDegrees=" + windDegrees + + ", precipitationIntensity=" + precipitationIntensity + + ", visibilityInMetres=" + visibilityInMetres + + ", dewPoint=" + dewPoint + + '}'; + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/RequestSettings.java b/src/main/java/com/github/prominence/openweathermap/api/request/RequestSettings.java index 56218d6..f4599e8 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/request/RequestSettings.java +++ b/src/main/java/com/github/prominence/openweathermap/api/request/RequestSettings.java @@ -26,8 +26,10 @@ import com.github.prominence.openweathermap.api.conf.TimeoutSettings; import com.github.prominence.openweathermap.api.enums.Language; import com.github.prominence.openweathermap.api.enums.ResponseType; import com.github.prominence.openweathermap.api.enums.UnitSystem; +import com.github.prominence.openweathermap.api.model.roadrisk.TrackPoint; import java.util.HashMap; +import java.util.List; import java.util.Map; public class RequestSettings { @@ -41,6 +43,8 @@ public class RequestSettings { private final Map requestParameters = new HashMap<>(8); + private final Map requestBody = new HashMap<>(); + private final StringBuilder urlAppenderBuilder = new StringBuilder(); private String subdomain = "api"; @@ -107,4 +111,8 @@ public class RequestSettings { public StringBuilder getUrlAppender() { return urlAppenderBuilder; } + + public void addToRequestBody(String key, Object object) { + requestBody.put(key, object); + } } diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskAsyncRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskAsyncRequestTerminator.java new file mode 100644 index 0000000..7ff68b7 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskAsyncRequestTerminator.java @@ -0,0 +1,70 @@ +/* + * 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.request.roadrisk; + +import com.github.prominence.openweathermap.api.enums.ResponseType; +import com.github.prominence.openweathermap.api.mapper.RoadRiskResponseMapper; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskRecord; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.utils.RequestUtils; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +/** + * The type Single result current weather async request terminator. + */ +public class RoadRiskAsyncRequestTerminator { + private final RequestSettings requestSettings; + + /** + * Instantiates a new Single result current weather async request terminator. + * + * @param requestSettings request settings object. + */ + RoadRiskAsyncRequestTerminator(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + public CompletableFuture> asJava() { + return CompletableFuture.supplyAsync(() -> new RoadRiskResponseMapper().mapToObjects(getRawResponse())); + } + + public CompletableFuture asJSON() { + return CompletableFuture.supplyAsync(this::getRawResponse); + } + + public CompletableFuture asXML() { + requestSettings.setResponseType(ResponseType.XML); + return CompletableFuture.supplyAsync(this::getRawResponse); + } + + public CompletableFuture asHTML() { + requestSettings.setResponseType(ResponseType.HTML); + return CompletableFuture.supplyAsync(this::getRawResponse); + } + + private String getRawResponse() { + return RequestUtils.getResponse(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestCustomizer.java b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestCustomizer.java new file mode 100644 index 0000000..8bfca40 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestCustomizer.java @@ -0,0 +1,19 @@ +package com.github.prominence.openweathermap.api.request.roadrisk; + +import com.github.prominence.openweathermap.api.request.RequestSettings; + +public class RoadRiskRequestCustomizer { + private final RequestSettings requestSettings; + + public RoadRiskRequestCustomizer(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + public RoadRiskRequestTerminator retrieve() { + return new RoadRiskRequestTerminator(requestSettings); + } + + public RoadRiskAsyncRequestTerminator retrieveAsync() { + return new RoadRiskAsyncRequestTerminator(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestTerminator.java b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestTerminator.java new file mode 100644 index 0000000..1cc869a --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequestTerminator.java @@ -0,0 +1,61 @@ +/* + * 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.request.roadrisk; + +import com.github.prominence.openweathermap.api.enums.ResponseType; +import com.github.prominence.openweathermap.api.mapper.RoadRiskResponseMapper; +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskRecord; +import com.github.prominence.openweathermap.api.request.RequestSettings; +import com.github.prominence.openweathermap.api.utils.RequestUtils; + +import java.util.List; + +public class RoadRiskRequestTerminator { + private final RequestSettings requestSettings; + + RoadRiskRequestTerminator(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + } + + public List asJava() { + return new RoadRiskResponseMapper().mapToObjects(asJSON()); + } + + public String asJSON() { + return getRawResponse(); + } + + public String asXML() { + requestSettings.setResponseType(ResponseType.XML); + return getRawResponse(); + } + + public String asHTML() { + requestSettings.setResponseType(ResponseType.HTML); + return getRawResponse(); + } + + private String getRawResponse() { + return RequestUtils.getResponse(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequester.java b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequester.java new file mode 100644 index 0000000..0789c17 --- /dev/null +++ b/src/main/java/com/github/prominence/openweathermap/api/request/roadrisk/RoadRiskRequester.java @@ -0,0 +1,20 @@ +package com.github.prominence.openweathermap.api.request.roadrisk; + +import com.github.prominence.openweathermap.api.model.roadrisk.TrackPoint; +import com.github.prominence.openweathermap.api.request.RequestSettings; + +import java.util.List; + +public class RoadRiskRequester { + private final RequestSettings requestSettings; + + public RoadRiskRequester(RequestSettings requestSettings) { + this.requestSettings = requestSettings; + this.requestSettings.appendToURL("data/2.5/roadrisk"); + } + + public RoadRiskRequestCustomizer byTrackPoints(List trackPoints) { + requestSettings.addToRequestBody("track", trackPoints); + return new RoadRiskRequestCustomizer(requestSettings); + } +} diff --git a/src/main/java/com/github/prominence/openweathermap/api/utils/RequestUtils.java b/src/main/java/com/github/prominence/openweathermap/api/utils/RequestUtils.java index 1ef190d..8563403 100644 --- a/src/main/java/com/github/prominence/openweathermap/api/utils/RequestUtils.java +++ b/src/main/java/com/github/prominence/openweathermap/api/utils/RequestUtils.java @@ -70,6 +70,7 @@ public final class RequestUtils { * @return response from the request in String representation. * @throws IllegalArgumentException in case if provided parameter isn't a valid url for {@link URL} instance. */ + @Deprecated public static String getResponse(String url) { return getResponse(url, new TimeoutSettings()); } diff --git a/src/test/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapperTest.java b/src/test/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapperTest.java new file mode 100644 index 0000000..0ff37c0 --- /dev/null +++ b/src/test/java/com/github/prominence/openweathermap/api/mapper/RoadRiskResponseMapperTest.java @@ -0,0 +1,67 @@ +package com.github.prominence.openweathermap.api.mapper; + +import com.github.prominence.openweathermap.api.model.roadrisk.RoadRiskRecord; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class RoadRiskResponseMapperTest { + + @Test + void mapToObjects() { + final String jsonResponse = """ + [ + { + "dt": 1602702000, + "coord": [ + 7.27, + 44.04 + ], + "weather": { + "temp": 278.44, + "wind_speed": 2.27, + "wind_deg": 7, + "precipitation_intensity": 0.38, + "dew_point": 276.13 + }, + "road": { + "state": 2, + "temp": 293.85 + }, + "alerts": [ + { + "sender_name": "METEO-FRANCE", + "event": "Moderate thunderstorm warning", + "event_level": 2 + } + ] + }, + { + "dt": 1602702400, + "coord": [ + 7.37, + 45.04 + ], + "weather": { + "temp": 282.44, + "wind_speed": 1.84, + "wind_deg": 316, + "dew_point": 275.99 + }, + "road": { + "state": 1, + "temp": 293.85 + }, + "alerts": [ + ] + } + ] + """; + + final List roadRiskRecords = new RoadRiskResponseMapper().mapToObjects(jsonResponse); + assertNotNull(roadRiskRecords); + + } +} \ No newline at end of file