diff --git a/.gitignore b/.gitignore
index 9beb001..fdf0a01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*.iml
-.idea/
+.idea
.gradle
-build/
-target/
\ No newline at end of file
+build
+target
+out
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index b15edae..f31b2ce 100644
--- a/build.gradle
+++ b/build.gradle
@@ -114,8 +114,8 @@ jacocoTestReport {
dependsOn test // tests are required to run before generating the report
reports {
csv.required = false
- xml.enabled true
- xml.destination file("${buildDir}/reports/jacoco/report.xml")
+ xml.required = true
+ xml.outputLocation = layout.buildDirectory.file('reports/jacoco/report.xml')
html.outputLocation = layout.buildDirectory.dir('jacocoHtml')
}
}
diff --git a/docs/SNAPSHOT.md b/docs/SNAPSHOT.md
index 318ed74..5a74194 100644
--- a/docs/SNAPSHOT.md
+++ b/docs/SNAPSHOT.md
@@ -1,8 +1,11 @@
### Implemented features:
* Current weather data
-* 5 day / 3-hour forecast
+* Hourly forecast
* One Call API
+* Daily forecast
+* 5 day / 3-hour forecast
* Air Pollution
+* Geocoding API
Other:
@@ -159,7 +162,7 @@ You are able to set preferable options(via chain methods) and execute appropriat
| `getRain()` | Returns `Rain` instance that contains information about rain volume for the last one hour and/or the last 3 hours. Can be absent in case of no data. |
| `getSnow()` | Returns `Snow` instance that contains information about snow volume for the last one hour and/or the last 3 hours. Can be absent in case of no data. |
| `getClouds()` | Returns `Clouds` instance that contains information about cloudiness percentage. |
-| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset` and `coordinate`. |
+| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset` and `coordinates`. |
| `toString()` | Returns informative string for the whole available weather information. |
`toString()` output example:
@@ -218,7 +221,7 @@ You are able to set preferable options(via chain methods) and execute appropriat
| Method | Description |
|-------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset`, `coordinate` and `population`. |
+| `getLocation()` | Returns `Location` object. Available fields: `id`, `name`, `countryCode`, `sunrise` and `sunset` time, `zoneOffset`, `coordinates` and `population`. |
| `getWeatherForecasts()` | Returns list of `WeatherForecast` objects with forecast information. |
| `toString()` | Returns informative string for the whole available forecast information. |
@@ -227,7 +230,7 @@ You are able to set preferable options(via chain methods) and execute appropriat
A forecast for Minsk with 15 timestamps.
```
-`com.github.prominence.openweathermap.api.model.forecast.WeatherForecast`'s useful public methods(setters are not listed):
+`com.github.prominence.openweathermap.api.model.forecast.free.WeatherForecast`'s useful public methods(setters are not listed):
| Method | Description |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
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 c29d1eb..ec052c2 100644
--- a/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java
+++ b/src/main/java/com/github/prominence/openweathermap/api/OpenWeatherMapClient.java
@@ -26,11 +26,14 @@ import com.github.prominence.openweathermap.api.annotation.SubscriptionAvailabil
import com.github.prominence.openweathermap.api.conf.TimeoutSettings;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.request.air.pollution.AirPollutionRequester;
+import com.github.prominence.openweathermap.api.request.forecast.daily.DailyForecastRequester;
import com.github.prominence.openweathermap.api.request.forecast.free.FiveDayThreeHourStepForecastRequester;
+import com.github.prominence.openweathermap.api.request.forecast.hourly.FourDaysHourlyForecastRequester;
+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.weather.CurrentWeatherRequester;
-import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.ALL;
+import static com.github.prominence.openweathermap.api.enums.SubscriptionPlan.*;
/**
* The main public API client to communicate with OpenWeatherMap services.
@@ -74,6 +77,24 @@ public class OpenWeatherMapClient {
return new FiveDayThreeHourStepForecastRequester(new RequestSettings(apiKey, timeoutSettings));
}
+ /**
+ * Hourly forecast API.
+ * @return requester for retrieving hourly weather forecast information for 4 days.
+ */
+ @SubscriptionAvailability(plans = { DEVELOPER, PROFESSIONAL, ENTERPRISE })
+ public FourDaysHourlyForecastRequester forecastHourly4Days() {
+ return new FourDaysHourlyForecastRequester(new RequestSettings(apiKey, timeoutSettings));
+ }
+
+ /**
+ * Daily forecast API.
+ * @return requester for retrieving daily weather forecast information for 16 days.
+ */
+ @SubscriptionAvailability(plans = PAID)
+ public DailyForecastRequester forecastDaily16Days() {
+ return new DailyForecastRequester(new RequestSettings(apiKey, timeoutSettings));
+ }
+
/**
* One Call API.
* To get information about current weather, minute forecast for 1 hour, hourly forecast for 48 hours, daily forecast for 7 days and government weather alerts.
@@ -93,4 +114,9 @@ public class OpenWeatherMapClient {
public AirPollutionRequester airPollution() {
return new AirPollutionRequester(new RequestSettings(apiKey, timeoutSettings));
}
+
+ @SubscriptionAvailability(plans = ALL)
+ public GeocodingRequester geocoding() {
+ return new GeocodingRequester(new RequestSettings(apiKey, timeoutSettings));
+ }
}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/AtmosphericPressureDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/AtmosphericPressureDeserializer.java
new file mode 100644
index 0000000..16b0d93
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/AtmosphericPressureDeserializer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022 Alexey Zinchenko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.github.prominence.openweathermap.api.deserializer;
+
+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.AtmosphericPressure;
+
+import java.io.IOException;
+
+public class AtmosphericPressureDeserializer extends JsonDeserializer {
+ @Override
+ public AtmosphericPressure deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
+ final JsonNode mainNode = p.getCodec().readTree(p);
+
+ final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(mainNode.get("pressure").asDouble());
+
+ final JsonNode seaLevelNode = mainNode.get("sea_level");
+ final JsonNode groundLevelNode = mainNode.get("grnd_level");
+ if (seaLevelNode != null) {
+ atmosphericPressure.setSeaLevelValue(seaLevelNode.asDouble());
+ }
+ if (groundLevelNode != null) {
+ atmosphericPressure.setGroundLevelValue(groundLevelNode.asDouble());
+ }
+
+ return atmosphericPressure;
+ }
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/CloudsDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/CloudsDeserializer.java
new file mode 100644
index 0000000..a0a1ae9
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/CloudsDeserializer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2022 Alexey Zinchenko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.github.prominence.openweathermap.api.deserializer;
+
+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.Clouds;
+
+import java.io.IOException;
+
+public class CloudsDeserializer extends JsonDeserializer {
+ @Override
+ public Clouds deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
+ final JsonNode cloudsNode = p.getCodec().readTree(p);
+
+ final JsonNode allValueNode = cloudsNode.get("all");
+ if (allValueNode != null) {
+ return Clouds.withValue((byte) allValueNode.asInt());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/CoordinatesDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/CoordinatesDeserializer.java
new file mode 100644
index 0000000..975412c
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/CoordinatesDeserializer.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022 Alexey Zinchenko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.github.prominence.openweathermap.api.deserializer;
+
+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.Coordinates;
+
+import java.io.IOException;
+
+public class CoordinatesDeserializer extends JsonDeserializer {
+ @Override
+ public Coordinates deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JacksonException {
+ JsonNode rootNode = jp.getCodec().readTree(jp);
+ if (rootNode.has("lat") && rootNode.has("lon")) {
+ return Coordinates.of(rootNode.get("lat").asDouble(), rootNode.get("lon").asDouble());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/github/prominence/openweathermap/api/deserializer/GeocodingRecordDeserializer.java b/src/main/java/com/github/prominence/openweathermap/api/deserializer/GeocodingRecordDeserializer.java
new file mode 100644
index 0000000..1dec9bc
--- /dev/null
+++ b/src/main/java/com/github/prominence/openweathermap/api/deserializer/GeocodingRecordDeserializer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2022 Alexey Zinchenko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.github.prominence.openweathermap.api.deserializer;
+
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.github.prominence.openweathermap.api.model.Coordinates;
+import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord;
+
+import java.io.IOException;
+import java.util.Map;
+
+public class GeocodingRecordDeserializer extends JsonDeserializer {
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+
+ public GeocodingRecordDeserializer() {
+ final SimpleModule module = new SimpleModule();
+ module.addDeserializer(Coordinates.class, new CoordinatesDeserializer());
+ objectMapper.registerModule(module);
+ }
+
+ @Override
+ public GeocodingRecord deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JacksonException {
+ JsonNode rootNode = jp.getCodec().readTree(jp);
+ String name = rootNode.get("name").asText();
+ String country = rootNode.get("country").asText();
+ Map localNames = objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("local_names")), new TypeReference