A bunch of global refactoring and improvements.

Improved coverage reports generation.
Updated docs.
Moved logic out of large mappers into small deserializers.
Implemented Geocoding API functionality.
Implemented Hourly forecast functionality.
Implemented Daily forecast functionality.
Renamed Coordinate class.
Reimplemented Current Weather API: removed multiple locations requests. Marked officially deprecated methods as @Deprecated.
Updated tests.
This commit is contained in:
Prominence 2022-04-30 01:35:45 +03:00
parent 8ca55b15f7
commit 4fdb48986e
No known key found for this signature in database
GPG Key ID: B5C2DFCB54798A7B
154 changed files with 7881 additions and 2429 deletions

7
.gitignore vendored
View File

@ -1,5 +1,6 @@
*.iml
.idea/
.idea
.gradle
build/
target/
build
target
out

View File

@ -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')
}
}

View File

@ -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 |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

View File

@ -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 <a href="https://openweathermap.org/api/hourly-forecast">API</a>.
* @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 <a href="https://openweathermap.org/api/hourly-forecast">API</a>.
* @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 <a href="https://openweathermap.org/api/one-call-api">API</a>.
* 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));
}
}

View File

@ -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<AtmosphericPressure> {
@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;
}
}

View File

@ -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<Clouds> {
@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;
}
}

View File

@ -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<Coordinates> {
@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;
}
}

View File

@ -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<GeocodingRecord> {
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<String, String> localNames = objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("local_names")), new TypeReference<Map<String, String>>() {});
Coordinates coordinates = objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Coordinates.class);
return new GeocodingRecord(name, localNames, coordinates, country);
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.Humidity;
import java.io.IOException;
public class HumidityDeserializer extends JsonDeserializer<Humidity> {
@Override
public Humidity deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rootNode = p.getCodec().readTree(p);
return Humidity.withValue((byte) (rootNode.get("humidity").asInt()));
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.Temperature;
import java.io.IOException;
public class TemperatureDeserializer extends JsonDeserializer<Temperature> {
@Override
public Temperature deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode mainNode = p.getCodec().readTree(p);
final UnitSystem unitSystem = (UnitSystem) ctxt.findInjectableValue("unitSystem", null, null);
final double tempValue = mainNode.get("temp").asDouble();
final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit());
final JsonNode feelsLikeNode = mainNode.get("feels_like");
if (feelsLikeNode != null) {
temperature.setFeelsLike(feelsLikeNode.asDouble());
}
final JsonNode tempMaxNode = mainNode.get("temp_max");
if (tempMaxNode != null) {
temperature.setMaxTemperature(tempMaxNode.asDouble());
}
final JsonNode tempMinNode = mainNode.get("temp_min");
if (tempMinNode != null) {
temperature.setMinTemperature(tempMinNode.asDouble());
}
return temperature;
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.WeatherState;
import java.io.IOException;
public class WeatherStateDeserializer extends JsonDeserializer<WeatherState> {
@Override
public WeatherState deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
JsonNode weatherNode = p.getCodec().readTree(p);
final WeatherState weatherState = new WeatherState(
weatherNode.get("id").asInt(),
weatherNode.get("main").asText(),
weatherNode.get("description").asText()
);
weatherState.setIconId(weatherNode.get("icon").asText());
return weatherState;
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.Wind;
import java.io.IOException;
public class WindDeserializer extends JsonDeserializer<Wind> {
@Override
public Wind deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode windNode = p.getCodec().readTree(p);
final UnitSystem unitSystem = (UnitSystem) ctxt.findInjectableValue("unitSystem", null, null);
JsonNode speedNode = windNode.get("speed");
if (speedNode == null) {
speedNode = windNode.get("wind_speed");
}
double speed = speedNode.asDouble();
final Wind wind = Wind.withValue(speed, unitSystem.getWindUnit());
JsonNode degNode = windNode.get("deg");
if (degNode == null) {
degNode = windNode.get("wind_deg");
}
if (degNode != null) {
wind.setDegrees(degNode.asDouble());
}
JsonNode gustNode = windNode.get("gust");
if (gustNode == null) {
gustNode = windNode.get("wind_gust");
}
if (gustNode != null) {
wind.setGust(gustNode.asDouble());
}
return wind;
}
}

View File

@ -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.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.ZipCodeGeocodingRecord;
import java.io.IOException;
public class ZipCodeGeocodingDeserializer extends JsonDeserializer<ZipCodeGeocodingRecord> {
private static final ObjectMapper objectMapper = new ObjectMapper();
public ZipCodeGeocodingDeserializer() {
final SimpleModule module = new SimpleModule();
module.addDeserializer(Coordinates.class, new CoordinatesDeserializer());
objectMapper.registerModule(module);
}
@Override
public ZipCodeGeocodingRecord deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
JsonNode rootNode = p.getCodec().readTree(p);
String zip = rootNode.get("zip").asText();
String name = rootNode.get("name").asText();
String country = rootNode.get("country").asText();
Coordinates coordinates = objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Coordinates.class);
return new ZipCodeGeocodingRecord(zip, name, coordinates, country);
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,60 @@
/*
* 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.onecall;
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.onecall.current.Alert;
import com.github.prominence.openweathermap.api.utils.JsonDeserializationUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class AlertDeserializer extends JsonDeserializer<Alert> {
@Override
public Alert deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode alertNode = p.getCodec().readTree(p);
Alert alert = new Alert();
alert.setSenderName(alertNode.get("sender_name").asText());
alert.setEventName(alertNode.get("event").asText());
alert.setStartTime(JsonDeserializationUtils.parseDateTime(alertNode.get("start")));
alert.setEndTime(JsonDeserializationUtils.parseDateTime(alertNode.get("end")));
alert.setDescription(alertNode.get("description").asText());
final JsonNode tagsNode = alertNode.get("tags");
if (tagsNode != null) {
List<String> tags = new ArrayList<>();
for (JsonNode tagNode : tagsNode) {
tags.add(tagNode.asText());
}
alert.setTags(tags);
}
return alert;
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.onecall;
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.onecall.AtmosphericPressure;
import java.io.IOException;
public class OneCallAtmosphericPressureDeserializer extends JsonDeserializer<AtmosphericPressure> {
@Override
public AtmosphericPressure deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rootNode = p.getCodec().readTree(p);
return AtmosphericPressure.withValue(rootNode.get("pressure").asDouble());
}
}

View File

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

View File

@ -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.onecall;
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.onecall.current.DailySnow;
import java.io.IOException;
public class OneCallDailySnowDeserializer extends JsonDeserializer<DailySnow> {
@Override
public DailySnow deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rootNode = p.getCodec().readTree(p);
final JsonNode valueNode = rootNode.get("snow");
if (valueNode != null) {
return DailySnow.withValue(valueNode.asDouble());
}
return null;
}
}

View File

@ -0,0 +1,56 @@
/*
* 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.onecall;
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.onecall.current.DailyTemperature;
import java.io.IOException;
public class OneCallDailyTemperatureDeserializer extends JsonDeserializer<DailyTemperature> {
@Override
public DailyTemperature deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rootNode = p.getCodec().readTree(p);
final DailyTemperature temperature = new DailyTemperature();
final JsonNode tempNode = rootNode.get("temp");
temperature.setMorning(tempNode.get("morn").asDouble());
temperature.setDay(tempNode.get("day").asDouble());
temperature.setEve(tempNode.get("eve").asDouble());
temperature.setNight(tempNode.get("night").asDouble());
temperature.setMin(tempNode.get("min").asDouble());
temperature.setMax(tempNode.get("max").asDouble());
final JsonNode feelsLikeNode = rootNode.get("feels_like");
temperature.setMorningFeelsLike(feelsLikeNode.get("morn").asDouble());
temperature.setDayFeelsLike(feelsLikeNode.get("day").asDouble());
temperature.setEveFeelsLike(feelsLikeNode.get("eve").asDouble());
temperature.setNightFeelsLike(feelsLikeNode.get("night").asDouble());
return temperature;
}
}

View File

@ -0,0 +1,47 @@
/*
* 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.onecall;
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.onecall.Rain;
import java.io.IOException;
public class OneCallRainDeserializer extends JsonDeserializer<Rain> {
@Override
public Rain deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rootNode = p.getCodec().readTree(p);
final JsonNode rainNode = rootNode.get("rain");
if (rainNode != null) {
final JsonNode oneHourNode = rainNode.get("1h");
if (oneHourNode != null) {
return Rain.withOneHourLevelValue(oneHourNode.asDouble());
}
}
return null;
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.onecall;
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.onecall.Rain;
import com.github.prominence.openweathermap.api.model.onecall.Snow;
import java.io.IOException;
public class OneCallSnowDeserializer extends JsonDeserializer<Snow> {
@Override
public Snow deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rootNode = p.getCodec().readTree(p);
final JsonNode snowNode = rootNode.get("snow");
if (snowNode != null) {
final JsonNode OneHourNode = snowNode.get("1h");
if (OneHourNode != null) {
Rain.withOneHourLevelValue(OneHourNode.asDouble());
}
}
return null;
}
}

View File

@ -0,0 +1,55 @@
/*
* 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.onecall;
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.UnitSystem;
import com.github.prominence.openweathermap.api.model.onecall.Temperature;
import java.io.IOException;
public class OneCallTemperatureDeserializer extends JsonDeserializer<Temperature> {
@Override
public Temperature deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rootNode = p.getCodec().readTree(p);
final UnitSystem unitSystem = (UnitSystem) ctxt.findInjectableValue("unitSystem", null, null);
final double tempValue = rootNode.get("temp").asDouble();
final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit());
final JsonNode tempFeelsLike = rootNode.get("feels_like");
if (tempFeelsLike != null) {
temperature.setFeelsLike(tempFeelsLike.asDouble());
}
final JsonNode dewPoint = rootNode.get("dew_point");
if (dewPoint != null) {
temperature.setDewPoint(dewPoint.asDouble());
}
return temperature;
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.weather;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.prominence.openweathermap.api.deserializer.CoordinatesDeserializer;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.model.weather.Location;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.TimeZone;
public class WeatherLocationDeserializer extends JsonDeserializer<Location> {
private final ObjectMapper objectMapper = new ObjectMapper();
public WeatherLocationDeserializer() {
final SimpleModule module = new SimpleModule();
module.addDeserializer(Coordinates.class, new CoordinatesDeserializer());
objectMapper.registerModule(module);
}
@Override
public Location deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rootNode = p.getCodec().readTree(p);
final Location location = Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText());
final JsonNode timezoneNode = rootNode.get("timezone");
if (timezoneNode != null) {
location.setZoneOffset(ZoneOffset.ofTotalSeconds(timezoneNode.asInt()));
}
final JsonNode sysNode = rootNode.get("sys");
if (sysNode != null) {
final JsonNode countryNode = sysNode.get("country");
if (countryNode != null) {
location.setCountryCode(countryNode.asText());
}
final JsonNode sunriseNode = sysNode.get("sunrise");
final JsonNode sunsetNode = sysNode.get("sunset");
if (sunriseNode != null) {
location.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunriseNode.asInt()), TimeZone.getDefault().toZoneId()));
}
if (sunsetNode != null) {
location.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunsetNode.asInt()), TimeZone.getDefault().toZoneId()));
}
}
final JsonNode coordNode = rootNode.get("coord");
if (coordNode != null) {
location.setCoordinate(objectMapper.readValue(objectMapper.treeAsTokens(coordNode), Coordinates.class));
}
return location;
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.weather;
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.weather.Rain;
import java.io.IOException;
public class WeatherRainDeserializer extends JsonDeserializer<Rain> {
@Override
public Rain deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode rainNode = p.getCodec().readTree(p);
if (rainNode != null) {
final JsonNode oneHourNode = rainNode.get("1h");
final JsonNode threeHourNode = rainNode.get("3h");
if (oneHourNode != null && threeHourNode != null) {
return Rain.withValues(oneHourNode.asDouble(), threeHourNode.asDouble());
} else if (oneHourNode != null) {
return Rain.withOneHourLevelValue(oneHourNode.asDouble());
} else if (threeHourNode != null) {
return Rain.withThreeHourLevelValue(threeHourNode.asDouble());
}
}
return null;
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.weather;
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.weather.Snow;
import java.io.IOException;
public class WeatherSnowDeserializer extends JsonDeserializer<Snow> {
@Override
public Snow deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
final JsonNode snowNode = p.getCodec().readTree(p);
if (snowNode != null) {
final JsonNode oneHourNode = snowNode.get("1h");
final JsonNode threeHourNode = snowNode.get("3h");
if (oneHourNode != null && threeHourNode != null) {
return Snow.withValues(oneHourNode.asDouble(), threeHourNode.asDouble());
} else if (oneHourNode != null) {
return Snow.withOneHourLevelValue(oneHourNode.asDouble());
} else if (threeHourNode != null) {
return Snow.withThreeHourLevelValue(threeHourNode.asDouble());
}
}
return null;
}
}

View File

@ -32,6 +32,11 @@ public enum SubscriptionPlan {
*/
FREE,
/**
* An alias that represents any of paid plans: startup, developer, professional or enterprise.
*/
PAID,
/**
* Startup subscription plan.
*/

View File

@ -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.mapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.prominence.openweathermap.api.model.WeatherState;
import com.github.prominence.openweathermap.api.utils.JsonDeserializationUtils;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractMapper {
protected final ObjectMapper objectMapper = new ObjectMapper();
protected LocalDateTime parseDateTime(JsonNode dateTimeNode) {
return JsonDeserializationUtils.parseDateTime(dateTimeNode);
}
protected ZoneId parseZoneId(JsonNode zoneIdNode) {
return JsonDeserializationUtils.parseZoneId(zoneIdNode);
}
protected ZoneOffset parseZoneOffset(JsonNode zoneOffsetNode) {
return JsonDeserializationUtils.parseZoneOffset(zoneOffsetNode);
}
protected List<WeatherState> parseWeatherStates(JsonNode weatherArrayNode) throws IOException {
List<WeatherState> weatherStateList = new ArrayList<>();
if (weatherArrayNode != null && weatherArrayNode.isArray()) {
for (JsonNode weatherNode : weatherArrayNode) {
weatherStateList.add(objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class));
}
}
return weatherStateList;
}
}

View File

@ -26,7 +26,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.prominence.openweathermap.api.enums.AirQualityIndex;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionDetails;
import com.github.prominence.openweathermap.api.model.air.pollution.AirPollutionRecord;
@ -37,7 +37,7 @@ import java.util.List;
import java.util.TimeZone;
/**
* The type Air pollution response mapper.
* Official API response documentation: <a href="https://openweathermap.org/api/air-pollution#fields">https://openweathermap.org/api/air-pollution#fields</a>.
*/
public class AirPollutionResponseMapper {
/**
@ -91,11 +91,11 @@ public class AirPollutionResponseMapper {
return airPollutionRecord;
}
private Coordinate parseCoordinate(JsonNode rootNode) {
private Coordinates parseCoordinate(JsonNode rootNode) {
final JsonNode latitudeNode = rootNode.get("lat");
final JsonNode longitudeNode = rootNode.get("lon");
if (latitudeNode != null && longitudeNode != null) {
return Coordinate.of(latitudeNode.asDouble(), longitudeNode.asDouble());
return Coordinates.of(latitudeNode.asDouble(), longitudeNode.asDouble());
}
return null;
}

View File

@ -22,76 +22,46 @@
package com.github.prominence.openweathermap.api.mapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.prominence.openweathermap.api.deserializer.*;
import com.github.prominence.openweathermap.api.deserializer.weather.WeatherLocationDeserializer;
import com.github.prominence.openweathermap.api.deserializer.weather.WeatherRainDeserializer;
import com.github.prominence.openweathermap.api.deserializer.weather.WeatherSnowDeserializer;
import com.github.prominence.openweathermap.api.model.weather.*;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.*;
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:
* Parameters:
* --- coord
* |- coord.lon City geo location, longitude
* |- coord.lat City geo location, latitude
* --- weather (more info Weather condition codes)
* |- weather.id Weather condition id
* |- weather.main Group of weather parameters (Rain, Snow, Extreme etc.)
* |- weather.description Weather condition within the group
* |- weather.icon Weather icon id
* --- base Internal parameter
* --- main
* |- main.temp Temperature. UnitSystem Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit.
* |- main.feels_like Temperature. This temperature parameter accounts for the human perception of weather. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit.
* |- main.pressure Atmospheric pressure (on the sea level, if there is no sea_level or grnd_level data), hPa
* |- main.humidity Humidity, %
* |- main.temp_min Minimum temperature at the moment. This is deviation from current temp that is possible for large cities and megalopolises geographically expanded (use these parameter optionally). UnitSystem Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit.
* |- main.temp_max Maximum temperature at the moment. This is deviation from current temp that is possible for large cities and megalopolises geographically expanded (use these parameter optionally). UnitSystem Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit.
* |- main.sea_level Atmospheric pressure on the sea level, hPa
* |- main.grnd_level Atmospheric pressure on the ground level, hPa
* --- wind
* |- wind.speed Wind speed. UnitSystem Default: meter/sec, Metric: meter/sec, Imperial: miles/hour.
* |- wind.deg Wind direction, degrees (meteorological)
* |- wind.gust Wind gust. Unit Default: meter/sec, Metric: meter/sec, Imperial: miles/hour
* --- clouds
* |- clouds.all Cloudiness, %
* --- rain
* |- rain.1h Rain volume for the last 1 hour, mm
* |- rain.3h Rain volume for the last 3 hours, mm
* --- snow
* |- snow.1h Snow volume for the last 1 hour, mm
* |- snow.3h Snow volume for the last 3 hours, mm
* --- dt Time of data calculation, unix, UTC
* --- sys
* |- sys.type Internal parameter
* |- sys.id Internal parameter
* |- sys.message Internal parameter
* |- sys.country Country code (GB, JP etc.)
* |- sys.sunrise Sunrise time, unix, UTC
* |- sys.sunset Sunset time, unix, UTC
* --- timezone Shift in seconds from UTC
* --- id City ID
* --- name City name
* --- cod Internal parameter
* Official API response documentation: <a href="https://openweathermap.org/current#current_JSON">https://openweathermap.org/current#current_JSON</a>.
* Ignored internal parameters: "root.cod", "sys.type", "sys.id", "sys.message".
*/
public class CurrentWeatherResponseMapper {
private final UnitSystem unitSystem;
public class CurrentWeatherResponseMapper extends AbstractMapper {
/**
* Instantiates a new Current weather response mapper.
*
* @param unitSystem the unit system
*/
public CurrentWeatherResponseMapper(UnitSystem unitSystem) {
this.unitSystem = unitSystem != null ? unitSystem : UnitSystem.STANDARD;
objectMapper.setInjectableValues(new InjectableValues.Std().addValue("unitSystem", unitSystem != null ? unitSystem : UnitSystem.STANDARD));
final SimpleModule module = new SimpleModule();
module.addDeserializer(WeatherState.class, new WeatherStateDeserializer());
module.addDeserializer(Temperature.class, new TemperatureDeserializer());
module.addDeserializer(AtmosphericPressure.class, new AtmosphericPressureDeserializer());
module.addDeserializer(Humidity.class, new HumidityDeserializer());
module.addDeserializer(Wind.class, new WindDeserializer());
module.addDeserializer(Rain.class, new WeatherRainDeserializer());
module.addDeserializer(Snow.class, new WeatherSnowDeserializer());
module.addDeserializer(Clouds.class, new CloudsDeserializer());
module.addDeserializer(Location.class, new WeatherLocationDeserializer());
objectMapper.registerModule(module);
}
/**
@ -100,218 +70,50 @@ public class CurrentWeatherResponseMapper {
* @param json the json string
* @return the weather object
*/
public Weather getSingle(String json) {
final ObjectMapper objectMapper = new ObjectMapper();
public Weather mapToWeather(String json) {
Weather weather;
try {
final JsonNode root = objectMapper.readTree(json);
weather = getSingle(root);
} catch (JsonProcessingException e) {
throw new RuntimeException("Cannot parse Weather response");
weather = mapToWeather(root);
} catch (IOException e) {
throw new RuntimeException("Cannot parse Weather response", e);
}
return weather;
}
private Weather getSingle(JsonNode rootNode) {
private Weather mapToWeather(JsonNode rootNode) throws IOException {
final JsonNode weatherArrayNode = rootNode.get("weather");
final JsonNode weatherNode = weatherArrayNode != null ? weatherArrayNode.get(0) : null;
final Weather weather = new Weather();
weather.setWeatherState(parseWeatherState(weatherNode));
weather.setTemperature(parseTemperature(rootNode));
weather.setAtmosphericPressure(parsePressure(rootNode));
weather.setHumidity(parseHumidity(rootNode));
weather.setWind(parseWind(rootNode));
weather.setRain(parseRain(rootNode));
weather.setSnow(parseSnow(rootNode));
weather.setClouds(parseClouds(rootNode));
weather.setLocation(parseLocation(rootNode));
final List<WeatherState> weatherStateList = new ArrayList<>();
if (weatherArrayNode != null && weatherArrayNode.isArray()) {
for (JsonNode weatherNode : weatherArrayNode) {
weatherStateList.add(objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class));
}
weather.setWeatherStates(weatherStateList);
}
weather.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("main")), Temperature.class));
weather.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("main")), AtmosphericPressure.class));
weather.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("main")), Humidity.class));
weather.setWind(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("wind")), Wind.class));
if (rootNode.has("rain")) {
weather.setRain(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("rain")), Rain.class));
}
if (rootNode.has("snow")) {
weather.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("snow")), Snow.class));
}
weather.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("clouds")), Clouds.class));
weather.setLocation(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Location.class));
final JsonNode dtNode = rootNode.get("dt");
if (dtNode != null) {
weather.setCalculationTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(dtNode.asInt()), TimeZone.getDefault().toZoneId()));
weather.setCalculationTime(parseDateTime(dtNode));
}
weather.setBase(rootNode.get("base").asText());
return weather;
}
/**
* Gets list of results.
*
* @param json the json string
* @return the list of weathers
*/
public List<Weather> getList(String json) {
final ObjectMapper objectMapper = new ObjectMapper();
final List<Weather> weatherList = new ArrayList<>();
try {
final JsonNode root = objectMapper.readTree(json);
final JsonNode listNode = root.get("list");
listNode.forEach(jsonNode -> weatherList.add(getSingle(jsonNode)));
} catch (JsonProcessingException e) {
throw new RuntimeException("Cannot parse Weather response");
}
return weatherList;
}
private WeatherState parseWeatherState(JsonNode weatherNode) {
if (weatherNode == null) {
return null;
}
final WeatherState weatherState = new WeatherState(
weatherNode.get("id").asInt(),
weatherNode.get("main").asText(),
weatherNode.get("description").asText()
);
weatherState.setIconId(weatherNode.get("icon").asText());
return weatherState;
}
private Temperature parseTemperature(JsonNode rootNode) {
final JsonNode mainNode = rootNode.get("main");
final double tempValue = mainNode.get("temp").asDouble();
final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit());
final JsonNode feelsLikeNode = mainNode.get("feels_like");
if (feelsLikeNode != null) {
temperature.setFeelsLike(feelsLikeNode.asDouble());
}
final JsonNode tempMaxNode = mainNode.get("temp_max");
if (tempMaxNode != null) {
temperature.setMaxTemperature(tempMaxNode.asDouble());
}
final JsonNode tempMinNode = mainNode.get("temp_min");
if (tempMinNode != null) {
temperature.setMinTemperature(tempMinNode.asDouble());
}
return temperature;
}
private AtmosphericPressure parsePressure(JsonNode rootNode) {
final JsonNode mainNode = rootNode.get("main");
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;
}
private Humidity parseHumidity(JsonNode rootNode) {
final JsonNode mainNode = rootNode.get("main");
return Humidity.withValue((byte) (mainNode.get("humidity").asInt()));
}
private Wind parseWind(JsonNode rootNode) {
final JsonNode windNode = rootNode.get("wind");
double speed = windNode.get("speed").asDouble();
final Wind wind = Wind.withValue(speed, unitSystem.getWindUnit());
final JsonNode degNode = windNode.get("deg");
if (degNode != null) {
wind.setDegrees(degNode.asDouble());
}
final JsonNode gustNode = windNode.get("gust");
if (gustNode != null) {
wind.setGust(gustNode.asDouble());
}
return wind;
}
private Rain parseRain(JsonNode rootNode) {
final JsonNode rainNode = rootNode.get("rain");
if (rainNode != null) {
final JsonNode oneHourNode = rainNode.get("1h");
final JsonNode threeHourNode = rainNode.get("3h");
if (oneHourNode != null && threeHourNode != null) {
return Rain.withValues(oneHourNode.asDouble(), threeHourNode.asDouble());
} else if (oneHourNode != null) {
return Rain.withOneHourLevelValue(oneHourNode.asDouble());
} else if (threeHourNode != null) {
return Rain.withThreeHourLevelValue(threeHourNode.asDouble());
}
}
return null;
}
private Snow parseSnow(JsonNode rootNode) {
final JsonNode snowNode = rootNode.get("snow");
if (snowNode != null) {
final JsonNode oneHourNode = snowNode.get("1h");
final JsonNode threeHourNode = snowNode.get("3h");
if (oneHourNode != null && threeHourNode != null) {
return Snow.withValues(oneHourNode.asDouble(), threeHourNode.asDouble());
} else if (oneHourNode != null) {
return Snow.withOneHourLevelValue(oneHourNode.asDouble());
} else if (threeHourNode != null) {
return Snow.withThreeHourLevelValue(threeHourNode.asDouble());
}
}
return null;
}
private Clouds parseClouds(JsonNode rootNode) {
final JsonNode cloudsNode = rootNode.get("clouds");
final JsonNode allValueNode = cloudsNode.get("all");
if (allValueNode != null) {
return Clouds.withValue((byte) allValueNode.asInt());
}
return null;
}
private Location parseLocation(JsonNode rootNode) {
final Location location = Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText());
final JsonNode timezoneNode = rootNode.get("timezone");
if (timezoneNode != null) {
location.setZoneOffset(ZoneOffset.ofTotalSeconds(timezoneNode.asInt()));
}
final JsonNode sysNode = rootNode.get("sys");
if (sysNode != null) {
final JsonNode countryNode = sysNode.get("country");
if (countryNode != null) {
location.setCountryCode(countryNode.asText());
}
final JsonNode sunriseNode = sysNode.get("sunrise");
final JsonNode sunsetNode = sysNode.get("sunset");
if (sunriseNode != null) {
location.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunriseNode.asInt()), TimeZone.getDefault().toZoneId()));
}
if (sunsetNode != null) {
location.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(sunsetNode.asInt()), TimeZone.getDefault().toZoneId()));
}
}
final JsonNode coordNode = rootNode.get("coord");
if (coordNode != null) {
location.setCoordinate(parseCoordinate(coordNode));
}
return location;
}
private Coordinate parseCoordinate(JsonNode rootNode) {
final JsonNode latitudeNode = rootNode.get("lat");
final JsonNode longitudeNode = rootNode.get("lon");
if (latitudeNode != null && longitudeNode != null) {
return Coordinate.of(latitudeNode.asDouble(), longitudeNode.asDouble());
}
return null;
}
}

View File

@ -0,0 +1,210 @@
/*
* 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.mapper;
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.Clouds;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.model.Humidity;
import com.github.prominence.openweathermap.api.model.WeatherState;
import com.github.prominence.openweathermap.api.model.Wind;
import com.github.prominence.openweathermap.api.model.forecast.daily.*;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
/**
* Official API response documentation: <a href="https://openweathermap.org/forecast16#JSON">https://openweathermap.org/forecast16#JSON</a>.
*/
public class DailyForecastResponseMapper {
private final ObjectMapper objectMapper = new ObjectMapper();
private final UnitSystem unitSystem;
public DailyForecastResponseMapper(UnitSystem unitSystem) {
this.unitSystem = unitSystem;
}
/**
* Maps forecast response into java object.
*
* @param json the json string
* @return the forecast
*/
public Forecast mapToForecast(String json) {
Forecast forecast;
try {
final 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) throws IOException {
final Forecast forecast = new Forecast();
forecast.setLocation(parseLocation(root.get("city")));
final List<WeatherForecast> forecasts = new ArrayList<>(root.get("cnt").asInt());
final JsonNode forecastListNode = root.get("list");
for (JsonNode forecastNode : forecastListNode) {
forecasts.add(parseWeatherForecast(forecastNode));
}
forecast.setWeatherForecasts(forecasts);
return forecast;
}
private WeatherForecast parseWeatherForecast(JsonNode rootNode) throws IOException {
final WeatherForecast weatherForecast = new WeatherForecast();
final JsonNode weatherArrayNode = rootNode.get("weather");
if (weatherArrayNode != null) {
final JsonNode weatherNode = weatherArrayNode.get(0);
weatherForecast.setWeatherState(parseWeatherState(weatherNode));
}
final JsonNode mainNode = rootNode.get("main");
weatherForecast.setTemperature(parseTemperature(mainNode));
weatherForecast.setAtmosphericPressure(parsePressure(mainNode));
weatherForecast.setHumidity(parseHumidity(mainNode));
weatherForecast.setClouds(parseClouds(rootNode));
weatherForecast.setWind(parseWind(rootNode));
weatherForecast.setRain(parseRain(rootNode));
weatherForecast.setSnow(parseSnow(rootNode));
weatherForecast.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(rootNode.get("dt").asLong()), TimeZone.getDefault().toZoneId()));
return weatherForecast;
}
private WeatherState parseWeatherState(JsonNode weatherNode) throws IOException {
if (weatherNode == null) {
return null;
}
return objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class);
}
private Temperature parseTemperature(JsonNode rootNode) {
final Temperature temperature = new Temperature();
final JsonNode tempNode = rootNode.get("temp");
temperature.setMorning(tempNode.get("morn").asDouble());
temperature.setDay(tempNode.get("day").asDouble());
temperature.setEve(tempNode.get("eve").asDouble());
temperature.setNight(tempNode.get("night").asDouble());
temperature.setMin(tempNode.get("min").asDouble());
temperature.setMax(tempNode.get("max").asDouble());
final JsonNode feelsLikeNode = rootNode.get("feels_like");
temperature.setMorningFeelsLike(feelsLikeNode.get("morn").asDouble());
temperature.setDayFeelsLike(feelsLikeNode.get("day").asDouble());
temperature.setEveFeelsLike(feelsLikeNode.get("eve").asDouble());
temperature.setNightFeelsLike(feelsLikeNode.get("night").asDouble());
return temperature;
}
private AtmosphericPressure parsePressure(JsonNode rootNode) {
return AtmosphericPressure.withValue(rootNode.get("pressure").asDouble());
}
private Humidity parseHumidity(JsonNode rootNode) {
return Humidity.withValue((byte) (rootNode.get("humidity").asInt()));
}
private Wind parseWind(JsonNode root) throws IOException {
final JsonNode windNode = root.get("wind");
return objectMapper.readValue(objectMapper.treeAsTokens(windNode), Wind.class);
}
private Rain parseRain(JsonNode root) {
final JsonNode rainNode = root.get("rain");
if (rainNode != null) {
final JsonNode threeHourNode = rainNode.get("3h");
if (threeHourNode != null) {
return Rain.withThreeHourLevelValue(threeHourNode.asDouble());
}
}
return null;
}
private Snow parseSnow(JsonNode root) {
final JsonNode snowNode = root.get("snow");
if (snowNode != null) {
final JsonNode threeHourNode = snowNode.get("3h");
if (threeHourNode != null) {
return Snow.withThreeHourLevelValue(threeHourNode.asDouble());
}
}
return null;
}
private Clouds parseClouds(JsonNode rootNode) {
final JsonNode cloudsNode = rootNode.get("clouds");
final JsonNode allValueNode = cloudsNode.get("all");
if (allValueNode != null) {
return Clouds.withValue((byte) allValueNode.asInt());
}
return null;
}
private Location parseLocation(JsonNode rootNode) {
final Location location = Location.withValues(rootNode.get("id").asInt(), rootNode.get("name").asText());
final JsonNode timezoneNode = rootNode.get("timezone");
if (timezoneNode != null) {
location.setZoneOffset(ZoneOffset.ofTotalSeconds(timezoneNode.asInt()));
}
final JsonNode countryNode = rootNode.get("country");
if (countryNode != null) {
location.setCountryCode(countryNode.asText());
}
final JsonNode coordNode = rootNode.get("coord");
if (coordNode != null) {
location.setCoordinate(parseCoordinate(coordNode));
}
return location;
}
private Coordinates parseCoordinate(JsonNode rootNode) {
final JsonNode latitudeNode = rootNode.get("lat");
final JsonNode longitudeNode = rootNode.get("lon");
if (latitudeNode != null && longitudeNode != null) {
return Coordinates.of(latitudeNode.asDouble(), longitudeNode.asDouble());
}
return null;
}
}

View File

@ -22,17 +22,19 @@
package com.github.prominence.openweathermap.api.mapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.prominence.openweathermap.api.deserializer.AtmosphericPressureDeserializer;
import com.github.prominence.openweathermap.api.deserializer.TemperatureDeserializer;
import com.github.prominence.openweathermap.api.deserializer.WeatherStateDeserializer;
import com.github.prominence.openweathermap.api.deserializer.WindDeserializer;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
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.Temperature;
import com.github.prominence.openweathermap.api.model.forecast.free.*;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
@ -41,53 +43,10 @@ import java.util.List;
import java.util.TimeZone;
/**
* Official API response documentation.
* Parameters(but the real response can differ):
* --- cod Internal parameter
* --- message Internal parameter
* --- cnt A number of timestamps returned in the API response
* --- list
* |- list.dt Time of data forecasted, unix, UTC
* |- list.main
* |- list.main.temp Temperature. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit.
* |- list.main.feels_like This temperature parameter accounts for the human perception of weather. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit.
* |- list.main.temp_min Minimum temperature at the moment of calculation. This is minimal forecasted temperature (within large megalopolises and urban areas), use this parameter optionally. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit.
* |- list.main.temp_max Maximum temperature at the moment of calculation. This is maximal forecasted temperature (within large megalopolises and urban areas), use this parameter optionally. Unit Default: Kelvin, Metric: Celsius, Imperial: Fahrenheit.
* |- list.main.pressure Atmospheric pressure on the sea level by default, hPa
* |- list.main.sea_level Atmospheric pressure on the sea level, hPa
* |- list.main.grnd_level Atmospheric pressure on the ground level, hPa
* |- list.main.humidity Humidity, %
* |- list.main.temp_kf Internal par
* |- list.weather
* |- list.weather.id Weather condition id
* |- list.weather.main Group of weather parameters (Rain, Snow, Extreme etc.)
* |- list.weather.description Weather condition within the group. You can get the output in your language.
* |- list.weather.icon Weather icon id
* |- list.clouds
* |- list.clouds.all Cloudiness, %
* |- list.wind
* |- list.wind.speed Wind speed. Unit Default: meter/sec, Metric: meter/sec, Imperial: miles/hour.
* |- list.wind.deg Wind direction, degrees (meteorological)
* |- list.visibility Average visibility, metres
* |- list.pop Probability of precipitation
* |- list.rain
* |- list.rain.3h Rain volume for last 3 hours, mm
* |- list.snow
* |- list.snow.3h Snow volume for last 3 hours
* |- list.sys
* |- list.sys.pod Part of the day (n - night, d - day)
* |- list.dt_txt Time of data forecasted, ISO, UTC
* --- city
* |- city.id City ID
* |- city.name City name
* |- city.coord
* |- city.coord.lat City geo location, latitude
* |- city.coord.lon City geo location, longitude
* |- city.country Country code (GB, JP etc.)
* |- city.timezone Shift in seconds from UTC
* Official API response documentation: <a href="https://openweathermap.org/forecast5#JSON">https://openweathermap.org/forecast5#JSON</a>.
*/
public class FiveDayThreeHourStepForecastResponseMapper {
private final UnitSystem unitSystem;
private final ObjectMapper objectMapper = new ObjectMapper();
/**
* Instantiates a new forecast response mapper.
@ -95,7 +54,14 @@ public class FiveDayThreeHourStepForecastResponseMapper {
* @param unitSystem the unit system
*/
public FiveDayThreeHourStepForecastResponseMapper(UnitSystem unitSystem) {
this.unitSystem = unitSystem;
objectMapper.setInjectableValues(new InjectableValues.Std().addValue("unitSystem", unitSystem != null ? unitSystem : UnitSystem.STANDARD));
final SimpleModule module = new SimpleModule();
module.addDeserializer(WeatherState.class, new WeatherStateDeserializer());
module.addDeserializer(Temperature.class, new TemperatureDeserializer());
module.addDeserializer(AtmosphericPressure.class, new AtmosphericPressureDeserializer());
module.addDeserializer(Wind.class, new WindDeserializer());
objectMapper.registerModule(module);
}
/**
@ -105,33 +71,35 @@ public class FiveDayThreeHourStepForecastResponseMapper {
* @return the forecast
*/
public Forecast mapToForecast(String json) {
final ObjectMapper objectMapper = new ObjectMapper();
Forecast forecast;
try {
final JsonNode root = objectMapper.readTree(json);
forecast = mapToForecast(root);
} catch (JsonProcessingException e) {
throw new RuntimeException("Cannot parse Forecast response");
} catch (IOException e) {
throw new RuntimeException("Cannot parse Forecast response", e);
}
return forecast;
}
private Forecast mapToForecast(JsonNode root) {
private Forecast mapToForecast(JsonNode root) throws IOException {
final Forecast forecast = new Forecast();
forecast.setLocation(parseLocation(root.get("city")));
final List<WeatherForecast> forecasts = new ArrayList<>(root.get("cnt").asInt());
final JsonNode forecastListNode = root.get("list");
forecastListNode.forEach(forecastNode -> forecasts.add(parseWeatherForecast(forecastNode)));
for (JsonNode forecastNode : forecastListNode) {
forecasts.add(parseWeatherForecast(forecastNode));
}
forecast.setWeatherForecasts(forecasts);
return forecast;
}
private WeatherForecast parseWeatherForecast(JsonNode rootNode) {
private WeatherForecast parseWeatherForecast(JsonNode rootNode) throws IOException {
final WeatherForecast weatherForecast = new WeatherForecast();
final JsonNode weatherArrayNode = rootNode.get("weather");
if (weatherArrayNode != null) {
@ -159,70 +127,28 @@ public class FiveDayThreeHourStepForecastResponseMapper {
return weatherForecast;
}
private WeatherState parseWeatherState(JsonNode weatherNode) {
private WeatherState parseWeatherState(JsonNode weatherNode) throws IOException {
if (weatherNode == null) {
return null;
}
final WeatherState weatherState = new WeatherState(
weatherNode.get("id").asInt(),
weatherNode.get("main").asText(),
weatherNode.get("description").asText()
);
weatherState.setIconId(weatherNode.get("icon").asText());
return weatherState;
return objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class);
}
private Temperature parseTemperature(JsonNode rootNode) {
final double tempValue = rootNode.get("temp").asDouble();
final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit());
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("feels_like");
if (tempFeelsLike != null) {
temperature.setFeelsLike(tempFeelsLike.asDouble());
}
return temperature;
private Temperature parseTemperature(JsonNode rootNode) throws IOException {
return objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Temperature.class);
}
private AtmosphericPressure parsePressure(JsonNode rootNode) {
final AtmosphericPressure atmosphericPressure = AtmosphericPressure.withValue(rootNode.get("pressure").asDouble());
final JsonNode seaLevelNode = rootNode.get("sea_level");
final JsonNode groundLevelNode = rootNode.get("grnd_level");
if (seaLevelNode != null) {
atmosphericPressure.setSeaLevelValue(seaLevelNode.asDouble());
}
if (groundLevelNode != null) {
atmosphericPressure.setGroundLevelValue(groundLevelNode.asDouble());
}
return atmosphericPressure;
private AtmosphericPressure parsePressure(JsonNode rootNode) throws IOException {
return objectMapper.readValue(objectMapper.treeAsTokens(rootNode), AtmosphericPressure.class);
}
private Humidity parseHumidity(JsonNode rootNode) {
return Humidity.withValue((byte) (rootNode.get("humidity").asInt()));
}
private Wind parseWind(JsonNode root) {
private Wind parseWind(JsonNode root) throws IOException {
final JsonNode windNode = root.get("wind");
double speed = windNode.get("speed").asDouble();
final Wind wind = Wind.withValue(speed, unitSystem.getWindUnit());
final JsonNode degNode = windNode.get("deg");
if (degNode != null) {
wind.setDegrees(degNode.asDouble());
}
return wind;
return objectMapper.readValue(objectMapper.treeAsTokens(windNode), Wind.class);
}
private Rain parseRain(JsonNode root) {
@ -292,11 +218,11 @@ public class FiveDayThreeHourStepForecastResponseMapper {
return location;
}
private Coordinate parseCoordinate(JsonNode rootNode) {
private Coordinates parseCoordinate(JsonNode rootNode) {
final JsonNode latitudeNode = rootNode.get("lat");
final JsonNode longitudeNode = rootNode.get("lon");
if (latitudeNode != null && longitudeNode != null) {
return Coordinate.of(latitudeNode.asDouble(), longitudeNode.asDouble());
return Coordinates.of(latitudeNode.asDouble(), longitudeNode.asDouble());
}
return null;
}

View File

@ -0,0 +1,64 @@
/*
* 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.mapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.prominence.openweathermap.api.deserializer.GeocodingRecordDeserializer;
import com.github.prominence.openweathermap.api.deserializer.ZipCodeGeocodingDeserializer;
import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingRecord;
import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord;
import java.util.List;
/**
* Official API response documentation: <a href="https://openweathermap.org/api/geocoding-api">https://openweathermap.org/api/geocoding-api</a>.
*/
public class GeocodingResponseMapper {
private static final ObjectMapper objectMapper = new ObjectMapper();
public GeocodingResponseMapper() {
final SimpleModule module = new SimpleModule();
module.addDeserializer(GeocodingRecord.class, new GeocodingRecordDeserializer());
module.addDeserializer(ZipCodeGeocodingRecord.class, new ZipCodeGeocodingDeserializer());
objectMapper.registerModule(module);
}
public List<GeocodingRecord> mapGeocodingResponse(String json) {
try {
return objectMapper.readValue(json, new TypeReference<List<GeocodingRecord>>() {});
} catch (JsonProcessingException e) {
throw new RuntimeException("Cannot parse ReverseGeocoding response.", e);
}
}
public ZipCodeGeocodingRecord mapZipCodeGeocodingResponse(String json) {
try {
return objectMapper.readValue(json, ZipCodeGeocodingRecord.class);
} catch (JsonProcessingException e) {
throw new RuntimeException("Cannot parse GeocodingInfo response.", e);
}
}
}

View File

@ -0,0 +1,143 @@
/*
* 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.mapper;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.prominence.openweathermap.api.deserializer.*;
import com.github.prominence.openweathermap.api.deserializer.forecast.hourly.HourlyForecastLocationDeserializer;
import com.github.prominence.openweathermap.api.deserializer.forecast.hourly.HourlyForecastRainDeserializer;
import com.github.prominence.openweathermap.api.deserializer.forecast.hourly.HourlyForecastSnowDeserializer;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.*;
import com.github.prominence.openweathermap.api.model.forecast.hourly.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Official API response documentation: <a href="https://openweathermap.org/api/hourly-forecast#JSON">https://openweathermap.org/api/hourly-forecast#JSON</a>.
*/
public class HourlyForecastResponseMapper extends AbstractMapper {
/**
* Instantiates a new forecast response mapper.
*
* @param unitSystem the unit system
*/
public HourlyForecastResponseMapper(UnitSystem unitSystem) {
objectMapper.setInjectableValues(new InjectableValues.Std().addValue("unitSystem", unitSystem != null ? unitSystem : UnitSystem.STANDARD));
final SimpleModule module = new SimpleModule();
module.addDeserializer(WeatherState.class, new WeatherStateDeserializer());
module.addDeserializer(Temperature.class, new TemperatureDeserializer());
module.addDeserializer(AtmosphericPressure.class, new AtmosphericPressureDeserializer());
module.addDeserializer(Wind.class, new WindDeserializer());
module.addDeserializer(Humidity.class, new HumidityDeserializer());
module.addDeserializer(Clouds.class, new CloudsDeserializer());
module.addDeserializer(Rain.class, new HourlyForecastRainDeserializer());
module.addDeserializer(Snow.class, new HourlyForecastSnowDeserializer());
module.addDeserializer(Location.class, new HourlyForecastLocationDeserializer());
objectMapper.registerModule(module);
}
/**
* Maps forecast response into java object.
*
* @param json the json string
* @return the forecast
*/
public HourlyForecast mapToForecast(String json) {
HourlyForecast hourlyForecast;
try {
final JsonNode root = objectMapper.readTree(json);
hourlyForecast = mapToForecast(root);
} catch (IOException e) {
throw new RuntimeException("Cannot parse Forecast response");
}
return hourlyForecast;
}
private HourlyForecast mapToForecast(JsonNode root) throws IOException {
final HourlyForecast hourlyForecast = new HourlyForecast();
hourlyForecast.setLocation(objectMapper.readValue(objectMapper.treeAsTokens(root.get("city")), Location.class));
final List<WeatherForecast> forecasts = new ArrayList<>(root.get("cnt").asInt());
final JsonNode forecastListNode = root.get("list");
for (JsonNode forecastNode : forecastListNode) {
forecasts.add(parseWeatherForecast(forecastNode));
}
hourlyForecast.setWeatherForecasts(forecasts);
return hourlyForecast;
}
private WeatherForecast parseWeatherForecast(JsonNode rootNode) throws IOException {
final WeatherForecast weatherForecast = new WeatherForecast();
final JsonNode weatherArrayNode = rootNode.get("weather");
if (weatherArrayNode != null && weatherArrayNode.isArray()) {
List<WeatherState> weatherStateList = new ArrayList<>();
for (JsonNode weatherNode : weatherArrayNode) {
weatherStateList.add(objectMapper.readValue(objectMapper.treeAsTokens(weatherNode), WeatherState.class));
}
weatherForecast.setWeatherStates(weatherStateList);
}
final JsonNode mainNode = rootNode.get("main");
weatherForecast.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(mainNode), Temperature.class));
weatherForecast.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(mainNode), AtmosphericPressure.class));
weatherForecast.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(mainNode), Humidity.class));
weatherForecast.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("clouds")), Clouds.class));
weatherForecast.setWind(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("wind")), Wind.class));
if (rootNode.has("rain")) {
weatherForecast.setRain(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("rain")), Rain.class));
}
if (rootNode.has("snow")) {
weatherForecast.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(rootNode.get("snow")), Snow.class));
}
final JsonNode sysNode = rootNode.get("sys");
if (sysNode != null) {
weatherForecast.setDayTime("d".equals(sysNode.get("pod").asText()) ? DayTime.DAY : DayTime.NIGHT);
}
if (rootNode.has("visibility")) {
weatherForecast.setAverageVisibilityInMetres(rootNode.get("visibility").asInt());
}
if (rootNode.has("pop")) {
weatherForecast.setProbabilityOfPrecipitation(rootNode.get("pop").asDouble());
}
weatherForecast.setForecastTime(parseDateTime(rootNode.get("dt")));
weatherForecast.setForecastTimeISO(rootNode.get("dt_txt").asText());
return weatherForecast;
}
}

View File

@ -22,41 +22,55 @@
package com.github.prominence.openweathermap.api.mapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.github.prominence.openweathermap.api.deserializer.*;
import com.github.prominence.openweathermap.api.deserializer.onecall.*;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.model.Clouds;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Humidity;
import com.github.prominence.openweathermap.api.model.WeatherState;
import com.github.prominence.openweathermap.api.model.*;
import com.github.prominence.openweathermap.api.model.onecall.AtmosphericPressure;
import com.github.prominence.openweathermap.api.model.onecall.Temperature;
import com.github.prominence.openweathermap.api.model.onecall.*;
import com.github.prominence.openweathermap.api.model.onecall.current.*;
import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeather;
import com.github.prominence.openweathermap.api.model.onecall.historical.HourlyHistorical;
import com.github.prominence.openweathermap.api.model.onecall.historical.HistoricalWeatherData;
import com.github.prominence.openweathermap.api.model.onecall.historical.HourlyHistorical;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;
/**
* Object mapper for OneCall API response.
* Official API response documentation:
* <ul>
* <li></li><a href="https://openweathermap.org/api/one-call-api#parameter">https://openweathermap.org/api/one-call-api#parameter</a></li>
* <li></li><a href="https://openweathermap.org/api/one-call-api#hist_parameter">https://openweathermap.org/api/one-call-api#hist_parameter</a></li>
* </ul>
*/
public class OneCallWeatherResponseMapper {
private final UnitSystem unitSystem;
public class OneCallWeatherResponseMapper extends AbstractMapper {
/**
* Instantiates a new forecast response mapper.
*
* @param unitSystem the unit system
*/
public OneCallWeatherResponseMapper(UnitSystem unitSystem) {
this.unitSystem = unitSystem;
objectMapper.setInjectableValues(new InjectableValues.Std().addValue("unitSystem", unitSystem != null ? unitSystem : UnitSystem.STANDARD));
final SimpleModule module = new SimpleModule();
module.addDeserializer(Coordinates.class, new CoordinatesDeserializer());
module.addDeserializer(AtmosphericPressure.class, new OneCallAtmosphericPressureDeserializer());
module.addDeserializer(Temperature.class, new OneCallTemperatureDeserializer());
module.addDeserializer(WeatherState.class, new WeatherStateDeserializer());
module.addDeserializer(Humidity.class, new HumidityDeserializer());
module.addDeserializer(Wind.class, new WindDeserializer());
module.addDeserializer(Clouds.class, new CloudsDeserializer());
module.addDeserializer(Rain.class, new OneCallRainDeserializer());
module.addDeserializer(Snow.class, new OneCallSnowDeserializer());
module.addDeserializer(DailyTemperature.class, new OneCallDailyTemperatureDeserializer());
module.addDeserializer(DailyRain.class, new OneCallDailyRainDeserializer());
module.addDeserializer(DailySnow.class, new OneCallDailySnowDeserializer());
module.addDeserializer(Alert.class, new AlertDeserializer());
objectMapper.registerModule(module);
}
/**
@ -66,13 +80,12 @@ public class OneCallWeatherResponseMapper {
* @return the current data object
*/
public CurrentWeatherData mapToCurrent(String json) {
final ObjectMapper objectMapper = new ObjectMapper();
CurrentWeatherData currentData;
try {
final JsonNode root = objectMapper.readTree(json);
currentData = mapToCurrent(root);
} catch (JsonProcessingException e) {
throw new RuntimeException("Cannot parse OneCall response");
} catch (IOException e) {
throw new RuntimeException("Cannot parse OneCall response", e);
}
return currentData;
@ -85,23 +98,23 @@ public class OneCallWeatherResponseMapper {
* @return the current data object
*/
public HistoricalWeatherData mapToHistorical(String json) {
final ObjectMapper objectMapper = new ObjectMapper();
HistoricalWeatherData historicalData;
try {
final JsonNode root = objectMapper.readTree(json);
historicalData = mapToHistorical(root);
} catch (JsonProcessingException e) {
} catch (IOException e) {
throw new RuntimeException("Cannot parse OneCall response");
}
return historicalData;
}
private CurrentWeatherData mapToCurrent(JsonNode rootNode) {
private CurrentWeatherData mapToCurrent(JsonNode rootNode) throws IOException {
final CurrentWeatherData currentData = new CurrentWeatherData();
currentData.setCoordinate(Coordinate.of(rootNode.get("lat").asDouble(), rootNode.get("lon").asDouble()));
currentData.setTimezone(ZoneId.of(rootNode.get("timezone").asText()));
currentData.setTimezoneOffset(ZoneOffset.ofTotalSeconds(rootNode.get("timezone_offset").asInt()));
currentData.setCoordinate(objectMapper.readValue(objectMapper.treeAsTokens(rootNode), Coordinates.class));
currentData.setTimezone(parseZoneId(rootNode.get("timezone")));
currentData.setTimezoneOffset(parseZoneOffset(rootNode.get("timezone_offset")));
currentData.setCurrent(parseCurrent(rootNode.get("current")));
currentData.setMinutelyList(parseMinutelyList(rootNode.get("minutely")));
currentData.setHourlyList(parseHourlyList(rootNode.get("hourly")));
@ -111,28 +124,31 @@ public class OneCallWeatherResponseMapper {
return currentData;
}
private Current parseCurrent(JsonNode currentNode) {
private Current parseCurrent(JsonNode currentNode) throws IOException {
if (currentNode == null) {
return null;
}
final Current current = new Current();
current.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("dt").asInt()), TimeZone.getDefault().toZoneId()));
current.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("sunrise").asInt()), TimeZone.getDefault().toZoneId()));
current.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("sunset").asInt()), TimeZone.getDefault().toZoneId()));
current.setForecastTime(parseDateTime(currentNode.get("dt")));
current.setSunriseTime(parseDateTime(currentNode.get("sunrise")));
current.setSunsetTime(parseDateTime(currentNode.get("sunset")));
current.setWeatherStates(parseWeatherStates(currentNode.get("weather")));
current.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Temperature.class));
current.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), AtmosphericPressure.class));
current.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Humidity.class));
current.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Clouds.class));
current.setWeatherState(parseWeatherState(currentNode.get("weather").get(0)));
current.setTemperature(parseTemperature(currentNode));
current.setAtmosphericPressure(parsePressure(currentNode));
current.setHumidity(parseHumidity(currentNode));
current.setClouds(parseClouds(currentNode));
current.setUvIndex(currentNode.get("uvi").asDouble());
final JsonNode visibilityNode = currentNode.get("visibility");
if (visibilityNode != null) {
current.setVisibilityInMetres(visibilityNode.asDouble());
}
current.setWind(parseWind(currentNode));
current.setRain(parseRain(currentNode));
current.setSnow(parseSnow(currentNode));
current.setWind(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Wind.class));
current.setRain(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Rain.class));
current.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Snow.class));
return current;
}
@ -144,7 +160,7 @@ public class OneCallWeatherResponseMapper {
final List<Minutely> minutelyList = new ArrayList<>();
for (final JsonNode minutelyNode : minutelyListNode) {
minutelyList.add(Minutely.withValue(
LocalDateTime.ofInstant(Instant.ofEpochSecond(minutelyNode.get("dt").asInt()), TimeZone.getDefault().toZoneId()),
parseDateTime(minutelyNode.get("dt")),
minutelyNode.get("precipitation").asDouble()
));
}
@ -152,20 +168,21 @@ public class OneCallWeatherResponseMapper {
return minutelyList;
}
private List<Hourly> parseHourlyList(JsonNode hourlyListNode) {
private List<Hourly> parseHourlyList(JsonNode hourlyListNode) throws IOException {
if (hourlyListNode == null) {
return null;
}
final List<Hourly> hourlyList = new ArrayList<>();
for (final JsonNode hourlyNode : hourlyListNode) {
final Hourly hourly = new Hourly();
hourly.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(hourlyNode.get("dt").asInt()), TimeZone.getDefault().toZoneId()));
hourly.setForecastTime(parseDateTime(hourlyNode.get("dt")));
hourly.setWeatherState(parseWeatherState(hourlyNode.get("weather").get(0)));
hourly.setTemperature(parseTemperature(hourlyNode));
hourly.setAtmosphericPressure(parsePressure(hourlyNode));
hourly.setHumidity(parseHumidity(hourlyNode));
hourly.setClouds(parseClouds(hourlyNode));
hourly.setWeatherStates(parseWeatherStates(hourlyNode.get("weather")));
hourly.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Temperature.class));
hourly.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), AtmosphericPressure.class));
hourly.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Humidity.class));
hourly.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Clouds.class));
final JsonNode uviNode = hourlyNode.get("uvi");
if (uviNode != null) {
@ -176,13 +193,13 @@ public class OneCallWeatherResponseMapper {
if (visibilityNode != null) {
hourly.setVisibilityInMetres(visibilityNode.asDouble());
}
hourly.setWind(parseWind(hourlyNode));
hourly.setWind(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Wind.class));
final JsonNode popNode = hourlyNode.get("pop");
if (popNode != null) {
hourly.setProbabilityOfPrecipitation(popNode.asDouble());
}
hourly.setRain(parseRain(hourlyNode));
hourly.setSnow(parseSnow(hourlyNode));
hourly.setRain(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Rain.class));
hourly.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Snow.class));
hourlyList.add(hourly);
}
@ -190,39 +207,40 @@ public class OneCallWeatherResponseMapper {
return hourlyList;
}
private List<Daily> parseDailyList(JsonNode dailyListNode) {
private List<Daily> parseDailyList(JsonNode dailyListNode) throws IOException {
if (dailyListNode == null) {
return null;
}
final List<Daily> dailyList = new ArrayList<>();
for (final JsonNode dailyNode : dailyListNode) {
final Daily daily = new Daily();
daily.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(dailyNode.get("dt").asInt()), TimeZone.getDefault().toZoneId()));
daily.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(dailyNode.get("sunrise").asInt()), TimeZone.getDefault().toZoneId()));
daily.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(dailyNode.get("sunset").asInt()), TimeZone.getDefault().toZoneId()));
daily.setForecastTime(parseDateTime(dailyNode.get("dt")));
daily.setSunriseTime(parseDateTime(dailyNode.get("sunrise")));
daily.setSunsetTime(parseDateTime(dailyNode.get("sunset")));
final JsonNode moonriseTimeNode = dailyNode.get("moonrise");
if (moonriseTimeNode != null) {
daily.setMoonriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(moonriseTimeNode.asInt()), TimeZone.getDefault().toZoneId()));
daily.setMoonriseTime(parseDateTime(moonriseTimeNode));
}
final JsonNode moonsetTimeNode = dailyNode.get("moonset");
if (moonsetTimeNode != null) {
daily.setMoonsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(moonsetTimeNode.asInt()), TimeZone.getDefault().toZoneId()));
daily.setMoonsetTime(parseDateTime(moonsetTimeNode));
}
final JsonNode moonPhaseNode = dailyNode.get("moon_phase");
if (moonPhaseNode != null) {
daily.setMoonPhase(new MoonPhase(moonPhaseNode.asDouble()));
}
daily.setWeatherState(parseWeatherState(dailyNode.get("weather").get(0)));
daily.setTemperature(parseDailyTemperature(dailyNode));
daily.setAtmosphericPressure(parsePressure(dailyNode));
daily.setHumidity(parseHumidity(dailyNode));
daily.setWind(parseWind(dailyNode));
daily.setClouds(parseClouds(dailyNode));
daily.setWeatherStates(parseWeatherStates(dailyNode.get("weather")));
daily.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), DailyTemperature.class));
daily.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), AtmosphericPressure.class));
daily.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), Humidity.class));
daily.setWind(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), Wind.class));
daily.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), Clouds.class));
daily.setUvIndex(dailyNode.get("uvi").asDouble());
daily.setProbabilityOfPrecipitation(dailyNode.get("pop").asDouble());
daily.setRain(parseDailyRain(dailyNode));
daily.setSnow(parseDailySnow(dailyNode));
daily.setRain(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), DailyRain.class));
daily.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(dailyNode), DailySnow.class));
dailyList.add(daily);
}
@ -230,213 +248,87 @@ public class OneCallWeatherResponseMapper {
return dailyList;
}
private List<Alert> parseAlerts(JsonNode alertsNode) {
if (alertsNode == null) {
private List<Alert> parseAlerts(JsonNode alertsNode) throws IOException {
if (alertsNode == null || !alertsNode.isArray()) {
return null;
}
final List<Alert> alerts = new ArrayList<>();
for (final JsonNode alertNode : alertsNode) {
Alert alert = new Alert();
alert.setSenderName(alertNode.get("sender_name").asText());
alert.setEventName(alertNode.get("event").asText());
alert.setStartTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(alertNode.get("start").asInt()), TimeZone.getDefault().toZoneId()));
alert.setEndTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(alertNode.get("end").asInt()), TimeZone.getDefault().toZoneId()));
alert.setDescription(alertNode.get("description").asText());
alerts.add(alert);
alerts.add(objectMapper.readValue(objectMapper.treeAsTokens(alertNode), Alert.class));
}
return alerts;
}
private HistoricalWeatherData mapToHistorical(JsonNode rootNode) {
private HistoricalWeatherData mapToHistorical(JsonNode rootNode) throws IOException {
final HistoricalWeatherData historicalData = new HistoricalWeatherData();
historicalData.setCoordinate(Coordinate.of(rootNode.get("lat").asDouble(), rootNode.get("lon").asDouble()));
historicalData.setTimezone(ZoneId.of(rootNode.get("timezone").asText()));
historicalData.setTimezoneOffset(ZoneOffset.ofTotalSeconds(rootNode.get("timezone_offset").asInt()));
historicalData.setCoordinate(Coordinates.of(rootNode.get("lat").asDouble(), rootNode.get("lon").asDouble()));
historicalData.setTimezone(parseZoneId(rootNode.get("timezone")));
historicalData.setTimezoneOffset(parseZoneOffset(rootNode.get("timezone_offset")));
historicalData.setHistoricalWeather(parseHistoricalWeather(rootNode.get("current")));
historicalData.setHourlyList(parseHourlyHistoricalList(rootNode.get("hourly")));
return historicalData;
}
private HistoricalWeather parseHistoricalWeather(JsonNode currentNode) {
private HistoricalWeather parseHistoricalWeather(JsonNode currentNode) throws IOException {
if (currentNode == null) {
return null;
}
final HistoricalWeather historicalWeather = new HistoricalWeather();
historicalWeather.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("dt").asInt()), TimeZone.getDefault().toZoneId()));
historicalWeather.setSunriseTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("sunrise").asInt()), TimeZone.getDefault().toZoneId()));
historicalWeather.setSunsetTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(currentNode.get("sunset").asInt()), TimeZone.getDefault().toZoneId()));
historicalWeather.setForecastTime(parseDateTime(currentNode.get("dt")));
historicalWeather.setSunriseTime(parseDateTime(currentNode.get("sunrise")));
historicalWeather.setSunsetTime(parseDateTime(currentNode.get("sunset")));
final JsonNode weatherListNode = currentNode.get("weather");
if (weatherListNode != null) {
historicalWeather.setWeatherState(parseWeatherState(weatherListNode.get(0)));
historicalWeather.setWeatherStates(parseWeatherStates(currentNode.get("weather")));
historicalWeather.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Temperature.class));
historicalWeather.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), AtmosphericPressure.class));
historicalWeather.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Humidity.class));
historicalWeather.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Clouds.class));
final JsonNode uviNode = currentNode.get("uvi");
if (uviNode != null) {
historicalWeather.setUvIndex(uviNode.asDouble());
}
historicalWeather.setTemperature(parseTemperature(currentNode));
historicalWeather.setAtmosphericPressure(parsePressure(currentNode));
historicalWeather.setHumidity(parseHumidity(currentNode));
historicalWeather.setClouds(parseClouds(currentNode));
historicalWeather.setUvIndex(currentNode.get("uvi").asDouble());
final JsonNode visibilityMode = currentNode.get("visibility");
if (visibilityMode != null) {
historicalWeather.setVisibilityInMetres(visibilityMode.asDouble());
final JsonNode visibilityNode = currentNode.get("visibility");
if (visibilityNode != null) {
historicalWeather.setVisibilityInMetres(visibilityNode.asDouble());
}
historicalWeather.setWind(parseWind(currentNode));
historicalWeather.setRain(parseRain(currentNode));
historicalWeather.setSnow(parseSnow(currentNode));
historicalWeather.setWind(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Wind.class));
historicalWeather.setRain(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Rain.class));
historicalWeather.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(currentNode), Snow.class));
return historicalWeather;
}
private List<HourlyHistorical> parseHourlyHistoricalList(JsonNode hourlyListNode) {
private List<HourlyHistorical> parseHourlyHistoricalList(JsonNode hourlyListNode) throws IOException {
if (hourlyListNode == null) {
return null;
}
final List<HourlyHistorical> hourlyList = new ArrayList<>();
for (final JsonNode hourlyNode : hourlyListNode) {
final HourlyHistorical hourly = new HourlyHistorical();
hourly.setForecastTime(LocalDateTime.ofInstant(Instant.ofEpochSecond(hourlyNode.get("dt").asInt()), TimeZone.getDefault().toZoneId()));
hourly.setForecastTime(parseDateTime(hourlyNode.get("dt")));
hourly.setWeatherState(parseWeatherState(hourlyNode.get("weather").get(0)));
hourly.setTemperature(parseTemperature(hourlyNode));
hourly.setAtmosphericPressure(parsePressure(hourlyNode));
hourly.setHumidity(parseHumidity(hourlyNode));
hourly.setClouds(parseClouds(hourlyNode));
hourly.setWeatherStates(parseWeatherStates(hourlyNode.get("weather")));
hourly.setTemperature(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Temperature.class));
hourly.setAtmosphericPressure(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), AtmosphericPressure.class));
hourly.setHumidity(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Humidity.class));
hourly.setClouds(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Clouds.class));
final JsonNode visibilityNode = hourlyNode.get("visibility");
if (visibilityNode != null) {
hourly.setVisibilityInMetres(visibilityNode.asDouble());
}
hourly.setWind(parseWind(hourlyNode));
hourly.setRain(parseRain(hourlyNode));
hourly.setSnow(parseSnow(hourlyNode));
hourly.setWind(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Wind.class));
hourly.setRain(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Rain.class));
hourly.setSnow(objectMapper.readValue(objectMapper.treeAsTokens(hourlyNode), Snow.class));
hourlyList.add(hourly);
}
return hourlyList;
}
private WeatherState parseWeatherState(JsonNode weatherNode) {
if (weatherNode == null) {
return null;
}
final WeatherState weatherState = new WeatherState(
weatherNode.get("id").asInt(),
weatherNode.get("main").asText(),
weatherNode.get("description").asText()
);
weatherState.setIconId(weatherNode.get("icon").asText());
return weatherState;
}
private Temperature parseTemperature(JsonNode rootNode) {
final double tempValue = rootNode.get("temp").asDouble();
final Temperature temperature = Temperature.withValue(tempValue, unitSystem.getTemperatureUnit());
final JsonNode tempFeelsLike = rootNode.get("feels_like");
if (tempFeelsLike != null) {
temperature.setFeelsLike(tempFeelsLike.asDouble());
}
final JsonNode dewPoint = rootNode.get("dew_point");
if (dewPoint != null) {
temperature.setDewPoint(dewPoint.asDouble());
}
return temperature;
}
private DailyTemperature parseDailyTemperature(JsonNode dailyNode) {
final DailyTemperature temperature = new DailyTemperature();
final JsonNode tempNode = dailyNode.get("temp");
temperature.setMorning(tempNode.get("morn").asDouble());
temperature.setDay(tempNode.get("day").asDouble());
temperature.setEve(tempNode.get("eve").asDouble());
temperature.setNight(tempNode.get("night").asDouble());
temperature.setMin(tempNode.get("min").asDouble());
temperature.setMax(tempNode.get("max").asDouble());
final JsonNode feelsLikeNode = dailyNode.get("feels_like");
temperature.setMorningFeelsLike(feelsLikeNode.get("morn").asDouble());
temperature.setDayFeelsLike(feelsLikeNode.get("day").asDouble());
temperature.setEveFeelsLike(feelsLikeNode.get("eve").asDouble());
temperature.setNightFeelsLike(feelsLikeNode.get("night").asDouble());
return temperature;
}
private AtmosphericPressure parsePressure(JsonNode rootNode) {
return AtmosphericPressure.withValue(rootNode.get("pressure").asDouble());
}
private Humidity parseHumidity(JsonNode rootNode) {
return Humidity.withValue((byte) (rootNode.get("humidity").asInt()));
}
private Wind parseWind(JsonNode rootNode) {
final JsonNode windSpeedNode = rootNode.get("wind_speed");
if (windSpeedNode == null) {
return null;
}
final Wind wind = Wind.withValue(windSpeedNode.asDouble(), unitSystem.getWindUnit());
final JsonNode degNode = rootNode.get("wind_deg");
if (degNode != null) {
wind.setDegrees(degNode.asDouble());
}
final JsonNode gustNode = rootNode.get("wind_gust");
if (gustNode != null) {
wind.setGust(gustNode.asDouble());
}
return wind;
}
private Rain parseRain(JsonNode root) {
final JsonNode rainNode = root.get("rain");
if (rainNode != null) {
final JsonNode oneHourNode = rainNode.get("1h");
if (oneHourNode != null) {
return Rain.withOneHourLevelValue(oneHourNode.asDouble());
}
}
return null;
}
private DailyRain parseDailyRain(JsonNode dailyNode) {
final JsonNode valueNode = dailyNode.get("rain");
if (valueNode != null) {
return DailyRain.withValue(valueNode.asDouble());
}
return null;
}
private Snow parseSnow(JsonNode root) {
final JsonNode snowNode = root.get("snow");
if (snowNode != null) {
final JsonNode OneHourNode = snowNode.get("1h");
if (OneHourNode != null) {
Rain.withOneHourLevelValue(OneHourNode.asDouble());
}
}
return null;
}
private DailySnow parseDailySnow(JsonNode dailyNode) {
final JsonNode valueNode = dailyNode.get("snow");
if (valueNode != null) {
return DailySnow.withValue(valueNode.asDouble());
}
return null;
}
private Clouds parseClouds(JsonNode rootNode) {
final JsonNode cloudsNode = rootNode.get("clouds");
if (cloudsNode != null) {
return Clouds.withValue((byte) cloudsNode.asInt());
}
return null;
}
}

View File

@ -48,11 +48,12 @@ public class AtmosphericPressure {
/**
* Static method for {@link AtmosphericPressure} creation with value checking.
*
* @param value atmospheric pressure value.
* @return instantiated {@link AtmosphericPressure} object.
*/
public static AtmosphericPressure withValue(double value) {
if (value < 0) {
if (value < 0) {
throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range.");
}
return new AtmosphericPressure(value);
@ -74,7 +75,7 @@ public class AtmosphericPressure {
* @throws IllegalArgumentException in case if provided value isn't in allowed range.
*/
public void setValue(double value) {
if (value < 0) {
if (value < 0) {
throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range.");
}
this.value = value;
@ -96,7 +97,7 @@ public class AtmosphericPressure {
* @throws IllegalArgumentException in case if provided value isn't in allowed range.
*/
public void setSeaLevelValue(double seaLevelValue) {
if (seaLevelValue < 0) {
if (seaLevelValue < 0) {
throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range.");
}
this.seaLevelValue = seaLevelValue;
@ -118,7 +119,7 @@ public class AtmosphericPressure {
* @throws IllegalArgumentException in case if provided value isn't in allowed range.
*/
public void setGroundLevelValue(double groundLevelValue) {
if (groundLevelValue < 0) {
if (groundLevelValue < 0) {
throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range.");
}
this.groundLevelValue = groundLevelValue;

View File

@ -45,11 +45,12 @@ public class Clouds {
/**
* Static method for {@link Clouds} creation with value checking.
*
* @param value clouds percentage value.
* @return instantiated {@link Clouds} object.
*/
public static Clouds withValue(byte value) {
if (value < 0 || value > 100) {
if (value < 0 || value > 100) {
throw new IllegalArgumentException("Cloudiness value must be in [0, 100] range.");
}
return new Clouds(value);

View File

@ -22,34 +22,40 @@
package com.github.prominence.openweathermap.api.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Objects;
/**
* Represents some location by its latitude and longitude.
*/
public class Coordinate {
public class Coordinates {
@JsonProperty("lat")
private double latitude;
@JsonProperty("lon")
private double longitude;
private Coordinate() {
private Coordinates() {
}
/**
* Method for {@link Coordinate} creation with correctness check.
* @param latitude latitude
* Method for {@link Coordinates} creation with correctness check.
*
* @param latitude latitude
* @param longitude longitude
* @return coordinate object.
*/
public static Coordinate of(double latitude, double longitude) {
final Coordinate coordinate = new Coordinate();
coordinate.setLatitude(latitude);
coordinate.setLongitude(longitude);
return coordinate;
public static Coordinates of(double latitude, double longitude) {
final Coordinates coordinates = new Coordinates();
coordinates.setLatitude(latitude);
coordinates.setLongitude(longitude);
return coordinates;
}
/**
* Sets latitude with checks.
*
* @param latitude latitude value
*/
public void setLatitude(double latitude) {
@ -61,6 +67,7 @@ public class Coordinate {
/**
* Sets longitude with checks.
*
* @param longitude longitude value
*/
public void setLongitude(double longitude) {
@ -72,6 +79,7 @@ public class Coordinate {
/**
* Returns latitude.
*
* @return latitude
*/
public double getLatitude() {
@ -80,6 +88,7 @@ public class Coordinate {
/**
* Returns longitude.
*
* @return longitude
*/
public double getLongitude() {
@ -89,8 +98,8 @@ public class Coordinate {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Coordinate)) return false;
Coordinate that = (Coordinate) o;
if (!(o instanceof Coordinates)) return false;
Coordinates that = (Coordinates) o;
return Double.compare(that.latitude, latitude) == 0 &&
Double.compare(that.longitude, longitude) == 0;
}

View File

@ -27,13 +27,13 @@ import java.util.Objects;
/**
* Represents coordinate rectangle by its bottom-left and top-right coordinates.
*/
public class CoordinateRectangle {
public class CoordinatesRectangle {
private final double longitudeLeft;
private final double latitudeBottom;
private final double longitudeRight;
private final double latitudeTop;
private CoordinateRectangle(double longitudeLeft, double latitudeBottom, double longitudeRight, double latitudeTop) {
private CoordinatesRectangle(double longitudeLeft, double latitudeBottom, double longitudeRight, double latitudeTop) {
this.longitudeLeft = longitudeLeft;
this.latitudeBottom = latitudeBottom;
this.longitudeRight = longitudeRight;
@ -41,21 +41,21 @@ public class CoordinateRectangle {
}
/**
* Method for {@link CoordinateRectangle} creation with correctness check.
* Method for {@link CoordinatesRectangle} creation with correctness check.
* @param longitudeLeft left longitude
* @param latitudeBottom bottom latitude
* @param longitudeRight right longitude
* @param latitudeTop tip latitude
* @return coordinate rectangle object.
*/
public static CoordinateRectangle withValues(double longitudeLeft, double latitudeBottom, double longitudeRight, double latitudeTop) {
public static CoordinatesRectangle withValues(double longitudeLeft, double latitudeBottom, double longitudeRight, double latitudeTop) {
if (latitudeBottom < -90 || latitudeTop < -90 || latitudeBottom > 90 || latitudeTop > 90) {
throw new IllegalArgumentException("Latitude value must be in the next range: [-90.0; 90.0].");
}
if (longitudeLeft < -180 || longitudeRight < -180 || longitudeLeft > 180 || longitudeRight > 180) {
throw new IllegalArgumentException("Longitude value must be in the next range: [-180.0; 180.0].");
}
return new CoordinateRectangle(longitudeLeft, latitudeBottom, longitudeRight, latitudeTop);
return new CoordinatesRectangle(longitudeLeft, latitudeBottom, longitudeRight, latitudeTop);
}
/**
@ -101,8 +101,8 @@ public class CoordinateRectangle {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CoordinateRectangle)) return false;
CoordinateRectangle rectangle = (CoordinateRectangle) o;
if (!(o instanceof CoordinatesRectangle)) return false;
CoordinatesRectangle rectangle = (CoordinatesRectangle) o;
return Double.compare(rectangle.longitudeLeft, longitudeLeft) == 0 &&
Double.compare(rectangle.latitudeBottom, latitudeBottom) == 0 &&
Double.compare(rectangle.longitudeRight, longitudeRight) == 0 &&
@ -187,14 +187,14 @@ public class CoordinateRectangle {
}
/**
* Builds {@link CoordinateRectangle} object with correctness check.
* @return {@link CoordinateRectangle} built object.
* Builds {@link CoordinatesRectangle} object with correctness check.
* @return {@link CoordinatesRectangle} built object.
*/
public CoordinateRectangle build() {
public CoordinatesRectangle build() {
if (longitudeLeft == null || latitudeBottom == null || longitudeRight == null || latitudeTop == null) {
throw new IllegalStateException("Not all fields were set.");
}
return new CoordinateRectangle(longitudeLeft, latitudeBottom, longitudeRight, latitudeTop);
return new CoordinatesRectangle(longitudeLeft, latitudeBottom, longitudeRight, latitudeTop);
}
}
}

View File

@ -45,11 +45,12 @@ public class Humidity {
/**
* Creates {@link Humidity} object with correctness check.
*
* @param value humidity
* @return created {@link Humidity} object
*/
public static Humidity withValue(byte value) {
if (value < 0 || value > 100) {
if (value < 0 || value > 100) {
throw new IllegalArgumentException("Humidity value must be in [0, 100] range.");
}
return new Humidity(value);
@ -71,7 +72,7 @@ public class Humidity {
* @throws IllegalArgumentException in case if provided value isn't in allowed range.
*/
public void setValue(int value) {
if (value < 0 || value > 100) {
if (value < 0 || value > 100) {
throw new IllegalArgumentException("Humidity value must be in [0, 100] range.");
}
this.value = value;

View File

@ -41,8 +41,9 @@ public class Temperature {
/**
* Creates {@link Temperature} object with correctness check.
*
* @param value temperature value
* @param unit temperature unit
* @param unit temperature unit
* @return temperature object
*/
public static Temperature withValue(double value, String unit) {
@ -54,6 +55,7 @@ public class Temperature {
/**
* Returns temperature value.
*
* @return value
*/
public double getValue() {
@ -62,6 +64,7 @@ public class Temperature {
/**
* Sets temperature value.
*
* @param value temperature
*/
public void setValue(double value) {
@ -70,6 +73,7 @@ public class Temperature {
/**
* Returns maximal temperature value.
*
* @return maximal temperature value
*/
public Double getMaxTemperature() {
@ -78,6 +82,7 @@ public class Temperature {
/**
* Sets maximal temperature value.
*
* @param maxTemperature maximal temperature
*/
public void setMaxTemperature(Double maxTemperature) {
@ -86,6 +91,7 @@ public class Temperature {
/**
* Returns minimal temperature value.
*
* @return minimal temperature value
*/
public Double getMinTemperature() {
@ -94,6 +100,7 @@ public class Temperature {
/**
* Sets minimal temperature value.
*
* @param minTemperature minimal temperature
*/
public void setMinTemperature(Double minTemperature) {
@ -102,6 +109,7 @@ public class Temperature {
/**
* Returns 'feels like' temperature value.
*
* @return 'feels like' temperature value
*/
public Double getFeelsLike() {
@ -110,6 +118,7 @@ public class Temperature {
/**
* Sets 'feels like' temperature value.
*
* @param feelsLike 'feels like' temperature
*/
public void setFeelsLike(Double feelsLike) {
@ -118,6 +127,7 @@ public class Temperature {
/**
* Returns temperature unit.
*
* @return unit
*/
public String getUnit() {
@ -126,6 +136,7 @@ public class Temperature {
/**
* Sets temperature unit with correctness check.
*
* @param unit temperature unit
*/
public void setUnit(String unit) {
@ -138,8 +149,7 @@ public class Temperature {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Temperature)) return false;
Temperature that = (Temperature) o;
if (!(o instanceof Temperature that)) return false;
return Double.compare(that.value, value) == 0 &&
Objects.equals(maxTemperature, that.maxTemperature) &&
Objects.equals(minTemperature, that.minTemperature) &&

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
* 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
@ -20,7 +20,7 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.weather;
package com.github.prominence.openweathermap.api.model;
import java.util.Objects;
@ -46,8 +46,9 @@ public class Wind {
/**
* Creates {@link Wind} object with correctness check.
*
* @param speed the speed
* @param unit the unitSystem
* @param unit the unitSystem
* @return wind object
*/
public static Wind withValue(double speed, String unit) {
@ -83,6 +84,7 @@ public class Wind {
/**
* Gets gust value.
*
* @return the gust
*/
public Double getGust() {
@ -91,6 +93,7 @@ public class Wind {
/**
* Sets gust value.
*
* @param gust the gust.
*/
public void setGust(double gust) {
@ -115,7 +118,7 @@ public class Wind {
* @param degrees the degrees
*/
public void setDegrees(double degrees) {
if (degrees < 0 || degrees > 360) {
if (degrees < 0 || degrees > 360) {
throw new IllegalArgumentException("Wind direction value must be in [0, 360] range.");
}
this.degrees = degrees;

View File

@ -24,7 +24,7 @@
package com.github.prominence.openweathermap.api.model.air.pollution;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import java.util.List;
import java.util.Objects;
@ -33,7 +33,7 @@ import java.util.Objects;
* The type Air pollution.
*/
public class AirPollutionDetails {
private Coordinate coordinate;
private Coordinates coordinates;
private List<AirPollutionRecord> airPollutionRecords;
/**
@ -41,17 +41,17 @@ public class AirPollutionDetails {
*
* @return the coordinate
*/
public Coordinate getCoordinate() {
return coordinate;
public Coordinates getCoordinate() {
return coordinates;
}
/**
* Sets coordinate.
*
* @param coordinate the coordinate
* @param coordinates the coordinate
*/
public void setCoordinate(Coordinate coordinate) {
this.coordinate = coordinate;
public void setCoordinate(Coordinates coordinates) {
this.coordinates = coordinates;
}
/**
@ -77,11 +77,11 @@ public class AirPollutionDetails {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AirPollutionDetails that = (AirPollutionDetails) o;
return Objects.equals(coordinate, that.coordinate) && Objects.equals(airPollutionRecords, that.airPollutionRecords);
return Objects.equals(coordinates, that.coordinates) && Objects.equals(airPollutionRecords, that.airPollutionRecords);
}
@Override
public int hashCode() {
return Objects.hash(coordinate, airPollutionRecords);
return Objects.hash(coordinates, airPollutionRecords);
}
}

View File

@ -1,145 +0,0 @@
/*
* 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;
/**
* Represents wind information.
*/
public class Wind {
private double speed;
private Double degrees;
private String unit;
/**
* Instantiates a new Wind.
*
* @param speed the speed
* @param unit the unitSystem
*/
private Wind(double speed, String unit) {
this.speed = speed;
this.unit = unit;
}
/**
* Creates {@link Wind} object with correctness check
* @param speed the wind
* @param unit the unitSystem
* @return created wind object
*/
public static Wind withValue(double speed, String unit) {
if (speed < 0) {
throw new IllegalArgumentException("Wind speed value must be in positive or zero.");
}
if (unit == null) {
throw new IllegalArgumentException("Unit must be set.");
}
return new Wind(speed, unit);
}
/**
* Gets speed.
*
* @return the speed
*/
public double getSpeed() {
return speed;
}
/**
* Sets speed.
*
* @param speed the speed
*/
public void setSpeed(double speed) {
if (speed < 0) {
throw new IllegalArgumentException("Wind speed value must be in positive or zero.");
}
this.speed = speed;
}
/**
* Gets degrees.
*
* @return the degrees
*/
public Double getDegrees() {
return degrees;
}
/**
* Sets degrees.
*
* @param degrees the degrees
*/
public void setDegrees(double degrees) {
if (degrees < 0 || degrees > 360) {
throw new IllegalArgumentException("Wind direction value must be in [0, 360] range.");
}
this.degrees = degrees;
}
/**
* Gets unitSystem.
*
* @return the unitSystem
*/
public String getUnit() {
return unit;
}
/**
* Sets unitSystem.
*
* @param unit the unitSystem
*/
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 Wind)) return false;
Wind wind = (Wind) o;
return Double.compare(wind.speed, speed) == 0 &&
Objects.equals(degrees, wind.degrees) &&
Objects.equals(unit, wind.unit);
}
@Override
public int hashCode() {
return Objects.hash(speed, degrees, unit);
}
@Override
public String toString() {
return "Wind speed: " + speed + " " + unit +
", degrees: " + degrees;
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.daily;
import java.util.Objects;
/**
* The AtmosphericPressure type represents atmospheric pressure value.
* Its value can only be a double in [0, +) range.
*/
public class AtmosphericPressure {
private static final String DEFAULT_UNIT = "hPa";
private double seaLevelValue;
private AtmosphericPressure() {
}
/**
* Static method for {@link AtmosphericPressure} creation with value checking.
* @param seaLevelValue atmospheric pressure value.
* @return instantiated {@link AtmosphericPressure} object.
*/
public static AtmosphericPressure withValue(double seaLevelValue) {
final AtmosphericPressure atmosphericPressure = new AtmosphericPressure();
atmosphericPressure.setSeaLevelValue(seaLevelValue);
return atmosphericPressure;
}
/**
* Gets sea level value.
*
* @return the sea level value.
*/
public Double getSeaLevelValue() {
return seaLevelValue;
}
/**
* Sets sea level value.
*
* @param seaLevelValue the sea level value.
* @throws IllegalArgumentException in case if provided value isn't in allowed range.
*/
public void setSeaLevelValue(double seaLevelValue) {
if (seaLevelValue < 0) {
throw new IllegalArgumentException("Atmospheric pressure value must be in [0, +∞) range.");
}
this.seaLevelValue = seaLevelValue;
}
/**
* Returns pressure unitSystem. Constantly equals to 'hPa'.
*
* @return the pressure unitSystem.
*/
public String getUnit() {
return DEFAULT_UNIT;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AtmosphericPressure that = (AtmosphericPressure) o;
return Double.compare(that.seaLevelValue, seaLevelValue) == 0;
}
@Override
public int hashCode() {
return Objects.hash(seaLevelValue);
}
@Override
public String toString() {
return "Pressure: " + seaLevelValue + ' ' + getUnit();
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.model.forecast.daily;
import java.util.List;
import java.util.Objects;
/**
* Represents information about forecast for different timestamps.
*/
public class Forecast {
private Location location;
private List<WeatherForecast> weatherForecasts;
/**
* Returns location information.
* @return location
*/
public Location getLocation() {
return location;
}
/**
* Sets forecast location.
* @param location forecast location
*/
public void setLocation(Location location) {
this.location = location;
}
/**
* Returns list of weather forecasts for different timestamps.
* @return list of forecast-per-timestamp information.
*/
public List<WeatherForecast> getWeatherForecasts() {
return weatherForecasts;
}
/**
* Sets list of weather forecasts for different timestamps.
* @param weatherForecasts list of forecast information
*/
public void setWeatherForecasts(List<WeatherForecast> weatherForecasts) {
this.weatherForecasts = weatherForecasts;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Forecast forecast = (Forecast) o;
return Objects.equals(location, forecast.location) && Objects.equals(weatherForecasts, forecast.weatherForecasts);
}
@Override
public int hashCode() {
return Objects.hash(location, weatherForecasts);
}
@Override
public String toString() {
return "A forecast for " + location.getName() + " with " + weatherForecasts.size() + " timestamps.";
}
}

View File

@ -0,0 +1,198 @@
/*
* 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.model.forecast.daily;
import com.github.prominence.openweathermap.api.model.Coordinates;
import java.time.ZoneOffset;
import java.util.Objects;
/**
* Represents location information.
*/
public class Location {
private int id;
private String name;
private String countryCode;
private ZoneOffset zoneOffset;
private Coordinates coordinates;
private Long population;
private Location(int id, String name) {
this.id = id;
this.name = name;
}
/**
* Creates {@link Location} object with correctness check.
* @param id location id
* @param name location name
* @return location object
*/
public static Location withValues(int id, String name) {
if (name == null) {
throw new IllegalArgumentException("Name must be set.");
}
return new Location(id, name);
}
/**
* Returns ID.
* @return location ID
*/
public int getId() {
return id;
}
/**
* Sets location ID.
* @param id location id
*/
public void setId(int id) {
this.id = id;
}
/**
* Returns location name.
* @return location name
*/
public String getName() {
return name;
}
/**
* Sets location name.
* @param name location name
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns country code.
* @return location country code
*/
public String getCountryCode() {
return countryCode;
}
/**
* Sets location country code.
* @param countryCode location country code
*/
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
/**
* Returns location timezone offset.
* @return timezone offset
*/
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
/**
* Sets location timezone offset.
* @param zoneOffset timezone offset
*/
public void setZoneOffset(ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset;
}
/**
* Returns location coordinates.
* @return location coordinates.
*/
public Coordinates getCoordinate() {
return coordinates;
}
/**
* Sets location coordinates.
* @param coordinates location coordinates
*/
public void setCoordinate(Coordinates coordinates) {
this.coordinates = coordinates;
}
/**
* Sets location population.
* @return location population
*/
public Long getPopulation() {
return population;
}
/**
* Sets location population.
* @param population location 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(zoneOffset, location.zoneOffset) &&
Objects.equals(coordinates, location.coordinates) &&
Objects.equals(population, location.population);
}
@Override
public int hashCode() {
return Objects.hash(id, name, countryCode, zoneOffset, coordinates, population);
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();
if (coordinates != null) {
stringBuilder.append(coordinates);
stringBuilder.append(". ");
}
stringBuilder.append("ID: ");
stringBuilder.append(id);
stringBuilder.append(", Name: ");
stringBuilder.append(name);
if (countryCode != null) {
stringBuilder.append('(');
stringBuilder.append(countryCode);
stringBuilder.append(')');
}
if (population != null) {
stringBuilder.append(", Population: ");
stringBuilder.append(population);
}
return stringBuilder.toString();
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.model.forecast.daily;
import java.util.Objects;
/**
* Represents rain information.
*/
public class Rain {
private static final String DEFAULT_UNIT = "mm";
private double level;
private Rain(double level) {
this.level = level;
}
/**
* Creates {@link Rain} object with correctness check.
* @param threeHourLevel 3-hour rain level value
* @return rain object.
*/
public static Rain withThreeHourLevelValue(double threeHourLevel) {
if (threeHourLevel < 0) {
throw new IllegalArgumentException("Rain level value cannot be negative.");
}
return new Rain(threeHourLevel);
}
/**
* Returns 3-hour rain level value.
* @return 3-hour rain level value
*/
public double getLevel() {
return level;
}
/**
* Sets 3-hour rain level value with correctness check.
* @param level 3-hour rain level value
*/
public void setLevel(double level) {
if (level < 0) {
throw new IllegalArgumentException("Rain level value cannot be negative.");
}
this.level = level;
}
/**
* Returns rain level unit of measure. Currently is constant.
* @return rain level unit of measure
*/
public String getUnit() {
return DEFAULT_UNIT;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Rain rain = (Rain) o;
return Double.compare(rain.level, level) == 0;
}
@Override
public int hashCode() {
return Objects.hash(level);
}
@Override
public String toString() {
return "3-hour rain level: " +
level + ' ' +
getUnit();
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.model.forecast.daily;
import java.util.Objects;
/**
* Represents snow information.
*/
public class Snow {
private static final String DEFAULT_UNIT = "mm";
private double level;
private Snow(double level) {
this.level = level;
}
/**
* Creates {@link Snow} object with correctness check.
* @param threeHourLevel 3-hour snow level value
* @return snow object.
*/
public static Snow withThreeHourLevelValue(double threeHourLevel) {
if (threeHourLevel < 0) {
throw new IllegalArgumentException("Snow level value cannot be negative.");
}
return new Snow(threeHourLevel);
}
/**
* Returns 3-hour snow level value.
* @return 3-hour snow level value
*/
public double getLevel() {
return level;
}
/**
* Sets 3-hour snow level value with correctness check.
* @param level 3-hour snow level value
*/
public void setLevel(double level) {
if (level < 0) {
throw new IllegalArgumentException("Snow level value cannot be negative.");
}
this.level = level;
}
/**
* Returns snow level unit of measure. Currently is constant.
* @return snow level unit of measure
*/
public String getUnit() {
return DEFAULT_UNIT;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Snow snow = (Snow) o;
return Double.compare(snow.level, level) == 0;
}
@Override
public int hashCode() {
return Objects.hash(level);
}
@Override
public String toString() {
return "3-hour snow level: " +
level + ' ' +
getUnit();
}
}

View File

@ -0,0 +1,263 @@
/*
* 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.daily;
import java.util.Objects;
/**
* The type Daily temperature.
*/
public class Temperature {
private Double morning;
private Double morningFeelsLike;
private Double day;
private Double dayFeelsLike;
private Double eve;
private Double eveFeelsLike;
private Double night;
private Double nightFeelsLike;
private Double min;
private Double max;
private String unit;
/**
* Gets morning temperature.
*
* @return the morning
*/
public Double getMorning() {
return morning;
}
/**
* Sets morning temperature.
*
* @param morning the morning
*/
public void setMorning(Double morning) {
this.morning = morning;
}
/**
* Gets morning feels like temperature.
*
* @return the morning feels like temperature
*/
public Double getMorningFeelsLike() {
return morningFeelsLike;
}
/**
* Sets morning feels like temperature.
*
* @param morningFeelsLike the morning feels like temperature
*/
public void setMorningFeelsLike(Double morningFeelsLike) {
this.morningFeelsLike = morningFeelsLike;
}
/**
* Gets day temperature.
*
* @return the day temperature
*/
public Double getDay() {
return day;
}
/**
* Sets day temperature.
*
* @param day the day temperature
*/
public void setDay(Double day) {
this.day = day;
}
/**
* Gets day feels like temperature.
*
* @return the day feels like temperature
*/
public Double getDayFeelsLike() {
return dayFeelsLike;
}
/**
* Sets day feels like temperature.
*
* @param dayFeelsLike the day feels like temperature
*/
public void setDayFeelsLike(Double dayFeelsLike) {
this.dayFeelsLike = dayFeelsLike;
}
/**
* Gets eve temperature.
*
* @return the eve temperature
*/
public Double getEve() {
return eve;
}
/**
* Sets eve temperature.
*
* @param eve the eve temperature
*/
public void setEve(Double eve) {
this.eve = eve;
}
/**
* Gets eve feels like temperature.
*
* @return the eve feels like temperature
*/
public Double getEveFeelsLike() {
return eveFeelsLike;
}
/**
* Sets eve feels like temperature.
*
* @param eveFeelsLike the eve feels like temperature
*/
public void setEveFeelsLike(Double eveFeelsLike) {
this.eveFeelsLike = eveFeelsLike;
}
/**
* Gets night temperature.
*
* @return the night temperature
*/
public Double getNight() {
return night;
}
/**
* Sets night temperature.
*
* @param night the night temperature
*/
public void setNight(Double night) {
this.night = night;
}
/**
* Gets night feels like temperature.
*
* @return the night feels like temperature
*/
public Double getNightFeelsLike() {
return nightFeelsLike;
}
/**
* Sets night feels like temperature.
*
* @param nightFeelsLike the night feels like temperature
*/
public void setNightFeelsLike(Double nightFeelsLike) {
this.nightFeelsLike = nightFeelsLike;
}
/**
* Gets min temperature.
*
* @return the min temperature
*/
public Double getMin() {
return min;
}
/**
* Sets min temperature.
*
* @param min the min temperature
*/
public void setMin(Double min) {
this.min = min;
}
/**
* Gets max temperature.
*
* @return the max temperature
*/
public Double getMax() {
return max;
}
/**
* Sets max temperature.
*
* @param max the max temperature
*/
public void setMax(Double max) {
this.max = max;
}
/**
* Gets unit temperature.
*
* @return the unit temperature
*/
public String getUnit() {
return unit;
}
/**
* Sets unit temperature.
*
* @param unit the unit temperature
*/
public void setUnit(String unit) {
this.unit = unit;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Temperature that = (Temperature) o;
return Objects.equals(morning, that.morning) &&
Objects.equals(morningFeelsLike, that.morningFeelsLike) &&
Objects.equals(day, that.day) &&
Objects.equals(dayFeelsLike, that.dayFeelsLike) &&
Objects.equals(eve, that.eve) &&
Objects.equals(eveFeelsLike, that.eveFeelsLike) &&
Objects.equals(night, that.night) &&
Objects.equals(nightFeelsLike, that.nightFeelsLike) &&
Objects.equals(min, that.min) &&
Objects.equals(max, that.max) &&
Objects.equals(unit, that.unit);
}
@Override
public int hashCode() {
return Objects.hash(morning, morningFeelsLike, day, dayFeelsLike, eve, eveFeelsLike, night, nightFeelsLike, min, max, unit);
}
}

View File

@ -0,0 +1,278 @@
/*
* 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.model.forecast.daily;
import com.github.prominence.openweathermap.api.model.Clouds;
import com.github.prominence.openweathermap.api.model.Humidity;
import com.github.prominence.openweathermap.api.model.WeatherState;
import com.github.prominence.openweathermap.api.model.Wind;
import java.time.LocalDateTime;
import java.util.Objects;
/**
* Represents weather forecast information for a particular timestamp.
*/
public class WeatherForecast {
private LocalDateTime forecastTime;
private LocalDateTime sunriseTime;
private LocalDateTime sunsetTime;
private WeatherState weatherState;
private Temperature temperature;
private AtmosphericPressure atmosphericPressure;
private Humidity humidity;
private Wind wind;
private Rain rain;
private Snow snow;
private Clouds clouds;
/**
* Gets forecast time.
*
* @return the forecast time
*/
public LocalDateTime getForecastTime() {
return forecastTime;
}
/**
* Sets forecast time.
*
* @param forecastTime the forecast time
*/
public void setForecastTime(LocalDateTime forecastTime) {
this.forecastTime = forecastTime;
}
/**
* Gets weather state.
*
* @return the weather state
*/
public WeatherState getWeatherState() {
return weatherState;
}
/**
* Sets weather state.
*
* @param weatherState the weather state
*/
public void setWeatherState(WeatherState weatherState) {
this.weatherState = weatherState;
}
/**
* Gets temperature.
*
* @return the temperature
*/
public Temperature getTemperature() {
return temperature;
}
/**
* Sets temperature.
*
* @param temperature the temperature
*/
public void setTemperature(Temperature temperature) {
this.temperature = temperature;
}
/**
* Gets atmospheric pressure.
*
* @return the atmospheric pressure
*/
public AtmosphericPressure getAtmosphericPressure() {
return atmosphericPressure;
}
/**
* Sets atmospheric pressure.
*
* @param atmosphericPressure the atmospheric pressure
*/
public void setAtmosphericPressure(AtmosphericPressure atmosphericPressure) {
this.atmosphericPressure = atmosphericPressure;
}
/**
* Gets humidity.
*
* @return the humidity
*/
public Humidity getHumidity() {
return humidity;
}
/**
* Sets humidity.
*
* @param humidity the humidity
*/
public void setHumidity(Humidity humidity) {
this.humidity = humidity;
}
/**
* Gets wind.
*
* @return the wind
*/
public Wind getWind() {
return wind;
}
/**
* Sets wind.
*
* @param wind the wind
*/
public void setWind(Wind wind) {
this.wind = wind;
}
/**
* Gets rain.
*
* @return the rain
*/
public Rain getRain() {
return rain;
}
/**
* Sets rain.
*
* @param rain the rain
*/
public void setRain(Rain rain) {
this.rain = rain;
}
/**
* Gets snow.
*
* @return the snow
*/
public Snow getSnow() {
return snow;
}
/**
* Sets snow.
*
* @param snow the snow
*/
public void setSnow(Snow snow) {
this.snow = snow;
}
/**
* Gets clouds.
*
* @return the clouds
*/
public Clouds getClouds() {
return clouds;
}
/**
* Sets clouds.
*
* @param clouds the clouds
*/
public void setClouds(Clouds clouds) {
this.clouds = clouds;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WeatherForecast that = (WeatherForecast) o;
return Objects.equals(forecastTime, that.forecastTime) &&
Objects.equals(weatherState, that.weatherState) &&
Objects.equals(temperature, that.temperature) &&
Objects.equals(atmosphericPressure, that.atmosphericPressure) &&
Objects.equals(humidity, that.humidity) &&
Objects.equals(wind, that.wind) &&
Objects.equals(rain, that.rain) &&
Objects.equals(snow, that.snow) &&
Objects.equals(clouds, that.clouds);
}
@Override
public int hashCode() {
return Objects.hash(forecastTime, weatherState, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds);
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Timestamp: ");
stringBuilder.append(forecastTime);
if (weatherState != null) {
stringBuilder.append(", Weather: ");
stringBuilder.append(weatherState.getDescription());
}
if (temperature != null) {
stringBuilder.append(", Min temperature: ");
stringBuilder.append(temperature.getMin());
stringBuilder.append(temperature.getUnit());
stringBuilder.append(", Max temperature: ");
stringBuilder.append(temperature.getMax());
stringBuilder.append(temperature.getUnit());
}
if (atmosphericPressure != null) {
stringBuilder.append(", ");
stringBuilder.append(atmosphericPressure.getSeaLevelValue());
stringBuilder.append(' ');
stringBuilder.append(atmosphericPressure.getUnit());
}
if (clouds != null) {
stringBuilder.append(", ");
stringBuilder.append(clouds.toString());
}
if (rain != null) {
stringBuilder.append(", Rain: ");
stringBuilder.append(rain.getLevel());
stringBuilder.append(' ');
stringBuilder.append(rain.getUnit());
}
if (snow != null) {
stringBuilder.append(", Snow: ");
stringBuilder.append(snow.getLevel());
stringBuilder.append(' ');
stringBuilder.append(snow.getUnit());
}
return stringBuilder.toString();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
* 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
@ -20,7 +20,7 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
package com.github.prominence.openweathermap.api.model.forecast.free;
import java.util.List;
import java.util.Objects;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
* 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
@ -20,9 +20,9 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
package com.github.prominence.openweathermap.api.model.forecast.free;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
@ -40,7 +40,7 @@ public class Location {
private LocalDateTime sunsetTime;
private ZoneOffset zoneOffset;
private Coordinate coordinate;
private Coordinates coordinates;
private Long population;
@ -162,16 +162,16 @@ public class Location {
* Returns location coordinates.
* @return location coordinates.
*/
public Coordinate getCoordinate() {
return coordinate;
public Coordinates getCoordinate() {
return coordinates;
}
/**
* Sets location coordinates.
* @param coordinate location coordinates
* @param coordinates location coordinates
*/
public void setCoordinate(Coordinate coordinate) {
this.coordinate = coordinate;
public void setCoordinate(Coordinates coordinates) {
this.coordinates = coordinates;
}
/**
@ -201,20 +201,20 @@ public class Location {
Objects.equals(sunriseTime, location.sunriseTime) &&
Objects.equals(sunsetTime, location.sunsetTime) &&
Objects.equals(zoneOffset, location.zoneOffset) &&
Objects.equals(coordinate, location.coordinate) &&
Objects.equals(coordinates, location.coordinates) &&
Objects.equals(population, location.population);
}
@Override
public int hashCode() {
return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinate, population);
return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinates, population);
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();
if (coordinate != null) {
stringBuilder.append(coordinate.toString());
if (coordinates != null) {
stringBuilder.append(coordinates.toString());
stringBuilder.append(". ");
}
stringBuilder.append("ID: ");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
* 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
@ -20,7 +20,7 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
package com.github.prominence.openweathermap.api.model.forecast.free;
import java.util.Objects;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
* 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
@ -20,7 +20,7 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
package com.github.prominence.openweathermap.api.model.forecast.free;
import java.util.Objects;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
* 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
@ -20,9 +20,10 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.model.forecast;
package com.github.prominence.openweathermap.api.model.forecast.free;
import com.github.prominence.openweathermap.api.model.*;
import com.github.prominence.openweathermap.api.model.Wind;
import java.time.LocalDateTime;
import java.util.Objects;

View File

@ -0,0 +1,84 @@
/*
* 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.model.forecast.hourly;
import java.util.List;
import java.util.Objects;
/**
* Represents information about forecast for different timestamps.
*/
public class HourlyForecast {
private Location location;
private List<WeatherForecast> weatherForecasts;
/**
* Returns location information.
* @return location
*/
public Location getLocation() {
return location;
}
/**
* Sets forecast location.
* @param location forecast location
*/
public void setLocation(Location location) {
this.location = location;
}
/**
* Returns list of weather forecasts for different timestamps.
* @return list of forecast-per-timestamp information.
*/
public List<WeatherForecast> getWeatherForecasts() {
return weatherForecasts;
}
/**
* Sets list of weather forecasts for different timestamps.
* @param weatherForecasts list of forecast information
*/
public void setWeatherForecasts(List<WeatherForecast> weatherForecasts) {
this.weatherForecasts = weatherForecasts;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HourlyForecast hourlyForecast = (HourlyForecast) o;
return Objects.equals(location, hourlyForecast.location) && Objects.equals(weatherForecasts, hourlyForecast.weatherForecasts);
}
@Override
public int hashCode() {
return Objects.hash(location, weatherForecasts);
}
@Override
public String toString() {
return "A forecast for " + location.getName() + " with " + weatherForecasts.size() + " timestamps.";
}
}

View File

@ -0,0 +1,211 @@
/*
* 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.model.forecast.hourly;
import com.github.prominence.openweathermap.api.model.Coordinates;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Objects;
/**
* Represents location information.
*/
public class Location {
private int id;
private String name;
private String countryCode;
private LocalDateTime sunriseTime;
private LocalDateTime sunsetTime;
private ZoneOffset zoneOffset;
private Coordinates coordinates;
private Location(int id, String name) {
this.id = id;
this.name = name;
}
/**
* Creates {@link Location} object with correctness check.
* @param id location id
* @param name location name
* @return location object
*/
public static Location withValues(int id, String name) {
if (name == null) {
throw new IllegalArgumentException("Name must be set.");
}
return new Location(id, name);
}
/**
* Returns ID.
* @return location ID
*/
public int getId() {
return id;
}
/**
* Sets location ID.
* @param id location id
*/
public void setId(int id) {
this.id = id;
}
/**
* Returns location name.
* @return location name
*/
public String getName() {
return name;
}
/**
* Sets location name.
* @param name location name
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns country code.
* @return location country code
*/
public String getCountryCode() {
return countryCode;
}
/**
* Sets location country code.
* @param countryCode location country code
*/
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
/**
* Returns location sunrise time.
* @return sunrise time
*/
public LocalDateTime getSunriseTime() {
return sunriseTime;
}
/**
* Sets location sunrise time.
* @param sunriseTime sunrise time
*/
public void setSunriseTime(LocalDateTime sunriseTime) {
this.sunriseTime = sunriseTime;
}
/**
* Returns location sunset time.
* @return sunset time
*/
public LocalDateTime getSunsetTime() {
return sunsetTime;
}
/**
* Sets location sunset time.
* @param sunsetTime sunset time
*/
public void setSunsetTime(LocalDateTime sunsetTime) {
this.sunsetTime = sunsetTime;
}
/**
* Returns location timezone offset.
* @return timezone offset
*/
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
/**
* Sets location timezone offset.
* @param zoneOffset timezone offset
*/
public void setZoneOffset(ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset;
}
/**
* Returns location coordinates.
* @return location coordinates.
*/
public Coordinates getCoordinate() {
return coordinates;
}
/**
* Sets location coordinates.
* @param coordinates location coordinates
*/
public void setCoordinate(Coordinates coordinates) {
this.coordinates = coordinates;
}
@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(sunriseTime, location.sunriseTime) &&
Objects.equals(sunsetTime, location.sunsetTime) &&
Objects.equals(zoneOffset, location.zoneOffset) &&
Objects.equals(coordinates, location.coordinates);
}
@Override
public int hashCode() {
return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinates);
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();
if (coordinates != null) {
stringBuilder.append(coordinates.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(')');
}
return stringBuilder.toString();
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.model.forecast.hourly;
import java.util.Objects;
/**
* Represents rain information.
*/
public class Rain {
private static final String DEFAULT_UNIT = "mm";
private double oneHourLevel;
private Rain(double oneHourLevel) {
this.oneHourLevel = oneHourLevel;
}
/**
* Creates {@link Rain} object with correctness check.
* @param oneHourLevel 1-hour rain level value
* @return rain object.
*/
public static Rain withOneHourLevelValue(double oneHourLevel) {
if (oneHourLevel < 0) {
throw new IllegalArgumentException("Rain level value cannot be negative.");
}
return new Rain(oneHourLevel);
}
/**
* Returns 1-hour rain level value.
* @return 1-hour rain level value
*/
public double getOneHourLevel() {
return oneHourLevel;
}
/**
* Sets 1-hour rain level value with correctness check.
* @param oneHourLevel 1-hour rain level value
*/
public void setOneHourLevel(double oneHourLevel) {
if (oneHourLevel < 0) {
throw new IllegalArgumentException("Rain level value cannot be negative.");
}
this.oneHourLevel = oneHourLevel;
}
/**
* Returns rain level unit of measure. Currently, is constant.
* @return rain level unit of measure
*/
public String getUnit() {
return DEFAULT_UNIT;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Rain rain = (Rain) o;
return Double.compare(rain.oneHourLevel, oneHourLevel) == 0;
}
@Override
public int hashCode() {
return Objects.hash(oneHourLevel);
}
@Override
public String toString() {
return "1-hour rain level: " +
oneHourLevel + ' ' +
getUnit();
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.model.forecast.hourly;
import java.util.Objects;
/**
* Represents snow information.
*/
public class Snow {
private static final String DEFAULT_UNIT = "mm";
private double oneHourLevel;
private Snow(double oneHourLevel) {
this.oneHourLevel = oneHourLevel;
}
/**
* Creates {@link Snow} object with correctness check.
* @param oneHourLevel 1-hour snow level value
* @return snow object.
*/
public static Snow withOneHourLevelValue(double oneHourLevel) {
if (oneHourLevel < 0) {
throw new IllegalArgumentException("Snow level value cannot be negative.");
}
return new Snow(oneHourLevel);
}
/**
* Returns 1-hour snow level value.
* @return 1-hour snow level value
*/
public double getOneHourLevel() {
return oneHourLevel;
}
/**
* Sets 1-hour snow level value with correctness check.
* @param oneHourLevel 1-hour snow level value
*/
public void setOneHourLevel(double oneHourLevel) {
if (oneHourLevel < 0) {
throw new IllegalArgumentException("Snow level value cannot be negative.");
}
this.oneHourLevel = oneHourLevel;
}
/**
* Returns snow level unit of measure. Currently, is constant.
* @return snow level unit of measure
*/
public String getUnit() {
return DEFAULT_UNIT;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Snow snow = (Snow) o;
return Double.compare(snow.oneHourLevel, oneHourLevel) == 0;
}
@Override
public int hashCode() {
return Objects.hash(oneHourLevel);
}
@Override
public String toString() {
return "1-hour snow level: " +
oneHourLevel + ' ' +
getUnit();
}
}

View File

@ -0,0 +1,338 @@
/*
* 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.model.forecast.hourly;
import com.github.prominence.openweathermap.api.model.*;
import com.github.prominence.openweathermap.api.model.Wind;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
* Represents weather forecast information for a particular timestamp.
*/
public class WeatherForecast {
private LocalDateTime forecastTime;
private List<WeatherState> weatherStates;
private Temperature temperature;
private AtmosphericPressure atmosphericPressure;
private Humidity humidity;
private Wind wind;
private Rain rain;
private Snow snow;
private Clouds clouds;
private String forecastTimeISO;
private DayTime dayTime;
private Integer averageVisibilityInMetres;
private Double probabilityOfPrecipitation;
/**
* Gets forecast time.
*
* @return the forecast time
*/
public LocalDateTime getForecastTime() {
return forecastTime;
}
/**
* Sets forecast time.
*
* @param forecastTime the forecast time
*/
public void setForecastTime(LocalDateTime forecastTime) {
this.forecastTime = forecastTime;
}
/**
* Gets weather state.
*
* @return the weather state
*/
public List<WeatherState> getWeatherStates() {
return weatherStates;
}
/**
* Sets weather state.
*
* @param weatherStates the weather state
*/
public void setWeatherStates(List<WeatherState> weatherStates) {
this.weatherStates = weatherStates;
}
/**
* Gets temperature.
*
* @return the temperature
*/
public Temperature getTemperature() {
return temperature;
}
/**
* Sets temperature.
*
* @param temperature the temperature
*/
public void setTemperature(Temperature temperature) {
this.temperature = temperature;
}
/**
* Gets atmospheric pressure.
*
* @return the atmospheric pressure
*/
public AtmosphericPressure getAtmosphericPressure() {
return atmosphericPressure;
}
/**
* Sets atmospheric pressure.
*
* @param atmosphericPressure the atmospheric pressure
*/
public void setAtmosphericPressure(AtmosphericPressure atmosphericPressure) {
this.atmosphericPressure = atmosphericPressure;
}
/**
* Gets humidity.
*
* @return the humidity
*/
public Humidity getHumidity() {
return humidity;
}
/**
* Sets humidity.
*
* @param humidity the humidity
*/
public void setHumidity(Humidity humidity) {
this.humidity = humidity;
}
/**
* Gets wind.
*
* @return the wind
*/
public Wind getWind() {
return wind;
}
/**
* Sets wind.
*
* @param wind the wind
*/
public void setWind(Wind wind) {
this.wind = wind;
}
/**
* Gets rain.
*
* @return the rain
*/
public Rain getRain() {
return rain;
}
/**
* Sets rain.
*
* @param rain the rain
*/
public void setRain(Rain rain) {
this.rain = rain;
}
/**
* Gets snow.
*
* @return the snow
*/
public Snow getSnow() {
return snow;
}
/**
* Sets snow.
*
* @param snow the snow
*/
public void setSnow(Snow snow) {
this.snow = snow;
}
/**
* Gets clouds.
*
* @return the clouds
*/
public Clouds getClouds() {
return clouds;
}
/**
* Sets clouds.
*
* @param clouds the clouds
*/
public void setClouds(Clouds clouds) {
this.clouds = clouds;
}
/**
* Gets forecast time iso.
*
* @return the forecast time iso
*/
public String getForecastTimeISO() {
return forecastTimeISO;
}
/**
* Sets forecast time iso.
*
* @param forecastTimeISO the forecast time iso
*/
public void setForecastTimeISO(String forecastTimeISO) {
this.forecastTimeISO = forecastTimeISO;
}
/**
* Gets day time.
*
* @return the day time
*/
public DayTime getDayTime() {
return dayTime;
}
/**
* Sets day time.
*
* @param dayTime the day time
*/
public void setDayTime(DayTime dayTime) {
this.dayTime = dayTime;
}
public Integer getAverageVisibilityInMetres() {
return averageVisibilityInMetres;
}
public void setAverageVisibilityInMetres(Integer averageVisibilityInMetres) {
this.averageVisibilityInMetres = averageVisibilityInMetres;
}
public Double getProbabilityOfPrecipitation() {
return probabilityOfPrecipitation;
}
public void setProbabilityOfPrecipitation(Double probabilityOfPrecipitation) {
this.probabilityOfPrecipitation = probabilityOfPrecipitation;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WeatherForecast that = (WeatherForecast) o;
return Objects.equals(forecastTime, that.forecastTime) &&
Objects.equals(weatherStates, that.weatherStates) &&
Objects.equals(temperature, that.temperature) &&
Objects.equals(atmosphericPressure, that.atmosphericPressure) &&
Objects.equals(humidity, that.humidity) &&
Objects.equals(wind, that.wind) &&
Objects.equals(rain, that.rain) &&
Objects.equals(snow, that.snow) &&
Objects.equals(clouds, that.clouds) &&
Objects.equals(forecastTimeISO, that.forecastTimeISO) &&
dayTime == that.dayTime &&
Objects.equals(averageVisibilityInMetres, that.averageVisibilityInMetres) &&
Objects.equals(probabilityOfPrecipitation, that.probabilityOfPrecipitation);
}
@Override
public int hashCode() {
return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, forecastTimeISO, dayTime, averageVisibilityInMetres, probabilityOfPrecipitation);
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Timestamp: ");
stringBuilder.append(forecastTimeISO);
if (weatherStates != null && weatherStates.size() > 0) {
stringBuilder.append(", Weather: ");
stringBuilder.append(weatherStates.get(0).getDescription());
}
if (temperature != null) {
stringBuilder.append(", ");
stringBuilder.append(temperature.getValue());
stringBuilder.append(' ');
stringBuilder.append(temperature.getUnit());
}
if (atmosphericPressure != null) {
stringBuilder.append(", ");
stringBuilder.append(atmosphericPressure.getValue());
stringBuilder.append(' ');
stringBuilder.append(atmosphericPressure.getUnit());
}
if (clouds != null) {
stringBuilder.append(", ");
stringBuilder.append(clouds);
}
if (rain != null) {
stringBuilder.append(", Rain: ");
stringBuilder.append(rain.getOneHourLevel());
stringBuilder.append(' ');
stringBuilder.append(rain.getUnit());
}
if (snow != null) {
stringBuilder.append(", Snow: ");
stringBuilder.append(snow.getOneHourLevel());
stringBuilder.append(' ');
stringBuilder.append(snow.getUnit());
}
if (averageVisibilityInMetres != null) {
stringBuilder.append(", Average visibility: ");
stringBuilder.append(averageVisibilityInMetres);
stringBuilder.append(" metres");
}
return stringBuilder.toString();
}
}

View File

@ -0,0 +1,84 @@
/*
* 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.model.geocoding;
import com.github.prominence.openweathermap.api.model.Coordinates;
import java.util.Map;
import java.util.Objects;
public final class GeocodingRecord {
private final String name;
private final Map<String, String> localNames;
private final Coordinates coordinates;
private final String countryCode;
public GeocodingRecord(String name, Map<String, String> localNames, Coordinates coordinates, String countryCode) {
this.name = name;
this.localNames = localNames;
this.coordinates = coordinates;
this.countryCode = countryCode;
}
public String getName() {
return name;
}
public Map<String, String> getLocalNames() {
return localNames;
}
public Coordinates getCoordinates() {
return coordinates;
}
public String getCountryCode() {
return countryCode;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (GeocodingRecord) obj;
return Objects.equals(this.name, that.name) &&
Objects.equals(this.localNames, that.localNames) &&
Objects.equals(this.coordinates, that.coordinates) &&
Objects.equals(this.countryCode, that.countryCode);
}
@Override
public int hashCode() {
return Objects.hash(name, localNames, coordinates, countryCode);
}
@Override
public String toString() {
return "GeocodingRecord[" +
"name=" + name + ", " +
"localNames=" + localNames + ", " +
"coordinates=" + coordinates + ", " +
"countryCode=" + countryCode + ']';
}
}

View File

@ -0,0 +1,83 @@
/*
* 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.model.geocoding;
import com.github.prominence.openweathermap.api.model.Coordinates;
import java.util.Objects;
public final class ZipCodeGeocodingRecord {
private final String zip;
private final String name;
private final Coordinates coordinates;
private final String countryCode;
public ZipCodeGeocodingRecord(String zip, String name, Coordinates coordinates, String countryCode) {
this.zip = zip;
this.name = name;
this.coordinates = coordinates;
this.countryCode = countryCode;
}
public String getZip() {
return zip;
}
public String getName() {
return name;
}
public Coordinates getCoordinates() {
return coordinates;
}
public String getCountryCode() {
return countryCode;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (ZipCodeGeocodingRecord) obj;
return Objects.equals(this.zip, that.zip) &&
Objects.equals(this.name, that.name) &&
Objects.equals(this.coordinates, that.coordinates) &&
Objects.equals(this.countryCode, that.countryCode);
}
@Override
public int hashCode() {
return Objects.hash(zip, name, coordinates, countryCode);
}
@Override
public String toString() {
return "ZipCodeGeocodingRecord[" +
"zip=" + zip + ", " +
"name=" + name + ", " +
"coordinates=" + coordinates + ", " +
"countryCode=" + countryCode + ']';
}
}

View File

@ -25,8 +25,10 @@ package com.github.prominence.openweathermap.api.model.onecall;
import com.github.prominence.openweathermap.api.model.Clouds;
import com.github.prominence.openweathermap.api.model.Humidity;
import com.github.prominence.openweathermap.api.model.WeatherState;
import com.github.prominence.openweathermap.api.model.Wind;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
@ -37,7 +39,7 @@ public class Current {
protected LocalDateTime sunriseTime;
protected LocalDateTime sunsetTime;
protected WeatherState weatherState;
protected List<WeatherState> weatherStates;
protected Temperature temperature;
protected AtmosphericPressure atmosphericPressure;
protected Humidity humidity;
@ -107,17 +109,17 @@ public class Current {
*
* @return the weather state
*/
public WeatherState getWeatherState() {
return weatherState;
public List<WeatherState> getWeatherStates() {
return weatherStates;
}
/**
* Sets weather state.
*
* @param weatherState the weather state
* @param weatherStates the weather state
*/
public void setWeatherState(WeatherState weatherState) {
this.weatherState = weatherState;
public void setWeatherStates(List<WeatherState> weatherStates) {
this.weatherStates = weatherStates;
}
/**
@ -296,7 +298,7 @@ public class Current {
return Objects.equals(forecastTime, current.forecastTime) &&
Objects.equals(sunriseTime, current.sunriseTime) &&
Objects.equals(sunsetTime, current.sunsetTime) &&
Objects.equals(weatherState, current.weatherState) &&
Objects.equals(weatherStates, current.weatherStates) &&
Objects.equals(temperature, current.temperature) &&
Objects.equals(atmosphericPressure, current.atmosphericPressure) &&
Objects.equals(humidity, current.humidity) &&
@ -310,7 +312,7 @@ public class Current {
@Override
public int hashCode() {
return Objects.hash(forecastTime, sunriseTime, sunsetTime, weatherState, temperature, atmosphericPressure, humidity, clouds, uvIndex, visibilityInMetres, wind, rain, snow);
return Objects.hash(forecastTime, sunriseTime, sunsetTime, weatherStates, temperature, atmosphericPressure, humidity, clouds, uvIndex, visibilityInMetres, wind, rain, snow);
}
@Override

View File

@ -1,159 +0,0 @@
/*
* 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.onecall;
import java.util.Objects;
/**
* The type Wind.
*/
public class Wind {
private double speed;
private Double degrees;
private Double gust;
private String unit;
private Wind() {
}
/**
* Creates {@link Wind} object with correctness check.
* @param speed the speed
* @param unit the unitSystem
* @return wind object
*/
public static Wind withValue(double speed, String unit) {
final Wind wind = new Wind();
wind.setSpeed(speed);
wind.setUnit(unit);
return wind;
}
/**
* Gets speed.
*
* @return the speed
*/
public double getSpeed() {
return speed;
}
/**
* Sets speed.
*
* @param speed the speed
*/
public void setSpeed(double speed) {
if (speed < 0) {
throw new IllegalArgumentException("Wind speed value must be in positive or zero.");
}
this.speed = speed;
}
/**
* Gets gust value.
* @return the gust
*/
public Double getGust() {
return gust;
}
/**
* Sets gust value.
* @param gust the gust.
*/
public void setGust(double gust) {
if (gust < 0) {
throw new IllegalArgumentException("Gust value must be positive or zero.");
}
this.gust = gust;
}
/**
* Gets degrees.
*
* @return the degrees
*/
public Double getDegrees() {
return degrees;
}
/**
* Sets degrees.
*
* @param degrees the degrees
*/
public void setDegrees(double degrees) {
if (degrees < 0 || degrees > 360) {
throw new IllegalArgumentException("Wind direction value must be in [0, 360] range.");
}
this.degrees = degrees;
}
/**
* Gets unitSystem.
*
* @return the unitSystem
*/
public String getUnit() {
return unit;
}
/**
* Sets unitSystem.
*
* @param unit the unitSystem
*/
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 Wind)) return false;
Wind wind = (Wind) o;
return Double.compare(wind.speed, speed) == 0 &&
Objects.equals(degrees, wind.degrees) &&
Objects.equals(gust, wind.gust) &&
Objects.equals(unit, wind.unit);
}
@Override
public int hashCode() {
return Objects.hash(speed, degrees, gust, unit);
}
@Override
public String toString() {
String output = "Wind speed: " + speed + " " + unit +
", degrees: " + degrees;
if (gust != null) {
output += ", Gust: " + gust + " " + unit;
}
return output;
}
}

View File

@ -23,6 +23,7 @@
package com.github.prominence.openweathermap.api.model.onecall.current;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
@ -35,6 +36,8 @@ public class Alert {
private LocalDateTime endTime;
private String description;
private List<String> tags;
/**
* Instantiates a new Alert.
*/
@ -49,13 +52,15 @@ public class Alert {
* @param startTime the start time
* @param endTime the end time
* @param description the description
* @param tags the tags
*/
public Alert(String senderName, String eventName, LocalDateTime startTime, LocalDateTime endTime, String description) {
public Alert(String senderName, String eventName, LocalDateTime startTime, LocalDateTime endTime, String description, List<String> tags) {
this.senderName = senderName;
this.eventName = eventName;
this.startTime = startTime;
this.endTime = endTime;
this.description = description;
this.tags = tags;
}
/**
@ -148,6 +153,14 @@ public class Alert {
this.description = description;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -157,12 +170,13 @@ public class Alert {
Objects.equals(eventName, alert.eventName) &&
Objects.equals(startTime, alert.startTime) &&
Objects.equals(endTime, alert.endTime) &&
Objects.equals(description, alert.description);
Objects.equals(description, alert.description) &&
Objects.equals(tags, alert.tags);
}
@Override
public int hashCode() {
return Objects.hash(senderName, eventName, startTime, endTime, description);
return Objects.hash(senderName, eventName, startTime, endTime, description, tags);
}
@Override

View File

@ -22,7 +22,7 @@
package com.github.prominence.openweathermap.api.model.onecall.current;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.model.onecall.Current;
import java.time.ZoneId;
@ -34,7 +34,7 @@ import java.util.Objects;
* The type Current weather data.
*/
public class CurrentWeatherData {
private Coordinate coordinate;
private Coordinates coordinates;
private ZoneId timezone;
private ZoneOffset timezoneOffset;
@ -49,17 +49,17 @@ public class CurrentWeatherData {
*
* @return the coordinate
*/
public Coordinate getCoordinate() {
return coordinate;
public Coordinates getCoordinate() {
return coordinates;
}
/**
* Sets coordinate.
*
* @param coordinate the coordinate
* @param coordinates the coordinate
*/
public void setCoordinate(Coordinate coordinate) {
this.coordinate = coordinate;
public void setCoordinate(Coordinates coordinates) {
this.coordinates = coordinates;
}
/**
@ -193,7 +193,7 @@ public class CurrentWeatherData {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CurrentWeatherData that = (CurrentWeatherData) o;
return Objects.equals(coordinate, that.coordinate) &&
return Objects.equals(coordinates, that.coordinates) &&
Objects.equals(timezone, that.timezone) &&
Objects.equals(timezoneOffset, that.timezoneOffset) &&
Objects.equals(current, that.current) &&
@ -205,11 +205,11 @@ public class CurrentWeatherData {
@Override
public int hashCode() {
return Objects.hash(coordinate, timezone, timezoneOffset, current, minutelyList, hourlyList, dailyList, alerts);
return Objects.hash(coordinates, timezone, timezoneOffset, current, minutelyList, hourlyList, dailyList, alerts);
}
@Override
public String toString() {
return "Current weather data for " + coordinate + ".";
return "Current weather data for " + coordinates + ".";
}
}

View File

@ -26,9 +26,10 @@ import com.github.prominence.openweathermap.api.model.Clouds;
import com.github.prominence.openweathermap.api.model.Humidity;
import com.github.prominence.openweathermap.api.model.WeatherState;
import com.github.prominence.openweathermap.api.model.onecall.AtmosphericPressure;
import com.github.prominence.openweathermap.api.model.onecall.Wind;
import com.github.prominence.openweathermap.api.model.Wind;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
@ -43,7 +44,7 @@ public class Daily {
private LocalDateTime moonsetTime;
private MoonPhase moonPhase;
private WeatherState weatherState;
private List<WeatherState> weatherStates;
private DailyTemperature temperature;
private AtmosphericPressure atmosphericPressure;
private Humidity humidity;
@ -167,17 +168,17 @@ public class Daily {
*
* @return the weather state
*/
public WeatherState getWeatherState() {
return weatherState;
public List<WeatherState> getWeatherStates() {
return weatherStates;
}
/**
* Sets weather state.
*
* @param weatherState the weather state
* @param weatherStates the weather state
*/
public void setWeatherState(WeatherState weatherState) {
this.weatherState = weatherState;
public void setWeatherStates(List<WeatherState> weatherStates) {
this.weatherStates = weatherStates;
}
/**
@ -372,7 +373,7 @@ public class Daily {
Objects.equals(moonriseTime, daily.moonriseTime) &&
Objects.equals(moonsetTime, daily.moonsetTime) &&
Objects.equals(moonPhase, daily.moonPhase) &&
Objects.equals(weatherState, daily.weatherState) &&
Objects.equals(weatherStates, daily.weatherStates) &&
Objects.equals(temperature, daily.temperature) &&
Objects.equals(atmosphericPressure, daily.atmosphericPressure) &&
Objects.equals(humidity, daily.humidity) &&
@ -386,7 +387,7 @@ public class Daily {
@Override
public int hashCode() {
return Objects.hash(forecastTime, sunriseTime, sunsetTime, moonriseTime, moonsetTime, moonPhase, weatherState, temperature, atmosphericPressure, humidity, wind, clouds, uvIndex, probabilityOfPrecipitation, rain, snow);
return Objects.hash(forecastTime, sunriseTime, sunsetTime, moonriseTime, moonsetTime, moonPhase, weatherStates, temperature, atmosphericPressure, humidity, wind, clouds, uvIndex, probabilityOfPrecipitation, rain, snow);
}
@Override
@ -395,9 +396,9 @@ public class Daily {
stringBuilder.append("Weather on ");
stringBuilder.append(forecastTime);
stringBuilder.append(".");
if (weatherState != null) {
if (weatherStates != null && weatherStates.size() > 0) {
stringBuilder.append(" Weather: ");
stringBuilder.append(weatherState.getDescription());
stringBuilder.append(weatherStates.get(0).getDescription());
stringBuilder.append('.');
}
if (temperature != null) {

View File

@ -25,9 +25,11 @@ package com.github.prominence.openweathermap.api.model.onecall.current;
import com.github.prominence.openweathermap.api.model.Clouds;
import com.github.prominence.openweathermap.api.model.Humidity;
import com.github.prominence.openweathermap.api.model.WeatherState;
import com.github.prominence.openweathermap.api.model.Wind;
import com.github.prominence.openweathermap.api.model.onecall.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
@ -36,7 +38,7 @@ import java.util.Objects;
public class Hourly {
private LocalDateTime forecastTime;
private WeatherState weatherState;
private List<WeatherState> weatherStates;
private Temperature temperature;
private AtmosphericPressure atmosphericPressure;
private Humidity humidity;
@ -71,17 +73,17 @@ public class Hourly {
*
* @return the weather state
*/
public WeatherState getWeatherState() {
return weatherState;
public List<WeatherState> getWeatherStates() {
return weatherStates;
}
/**
* Sets weather state.
*
* @param weatherState the weather state
* @param weatherStates the weather state
*/
public void setWeatherState(WeatherState weatherState) {
this.weatherState = weatherState;
public void setWeatherStates(List<WeatherState> weatherStates) {
this.weatherStates = weatherStates;
}
/**
@ -286,7 +288,7 @@ public class Hourly {
if (o == null || getClass() != o.getClass()) return false;
Hourly hourly = (Hourly) o;
return Objects.equals(forecastTime, hourly.forecastTime) &&
Objects.equals(weatherState, hourly.weatherState) &&
Objects.equals(weatherStates, hourly.weatherStates) &&
Objects.equals(temperature, hourly.temperature) &&
Objects.equals(atmosphericPressure, hourly.atmosphericPressure) &&
Objects.equals(humidity, hourly.humidity) &&
@ -301,7 +303,7 @@ public class Hourly {
@Override
public int hashCode() {
return Objects.hash(forecastTime, weatherState, temperature, atmosphericPressure, humidity, uvIndex, clouds, visibilityInMetres, wind, probabilityOfPrecipitation, rain, snow);
return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, uvIndex, clouds, visibilityInMetres, wind, probabilityOfPrecipitation, rain, snow);
}
@Override

View File

@ -22,7 +22,7 @@
package com.github.prominence.openweathermap.api.model.onecall.historical;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import java.time.ZoneId;
import java.time.ZoneOffset;
@ -33,7 +33,7 @@ import java.util.Objects;
* The type Historical weather data.
*/
public class HistoricalWeatherData {
private Coordinate coordinate;
private Coordinates coordinates;
private ZoneId timezone;
private ZoneOffset timezoneOffset;
@ -45,17 +45,17 @@ public class HistoricalWeatherData {
*
* @return the coordinate
*/
public Coordinate getCoordinate() {
return coordinate;
public Coordinates getCoordinate() {
return coordinates;
}
/**
* Sets coordinate.
*
* @param coordinate the coordinate
* @param coordinates the coordinate
*/
public void setCoordinate(Coordinate coordinate) {
this.coordinate = coordinate;
public void setCoordinate(Coordinates coordinates) {
this.coordinates = coordinates;
}
/**
@ -135,7 +135,7 @@ public class HistoricalWeatherData {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HistoricalWeatherData that = (HistoricalWeatherData) o;
return Objects.equals(coordinate, that.coordinate) &&
return Objects.equals(coordinates, that.coordinates) &&
Objects.equals(timezone, that.timezone) &&
Objects.equals(timezoneOffset, that.timezoneOffset) &&
Objects.equals(historicalWeather, that.historicalWeather) &&
@ -144,11 +144,11 @@ public class HistoricalWeatherData {
@Override
public int hashCode() {
return Objects.hash(coordinate, timezone, timezoneOffset, historicalWeather, hourlyList);
return Objects.hash(coordinates, timezone, timezoneOffset, historicalWeather, hourlyList);
}
@Override
public String toString() {
return "Historical weather data for " + coordinate + ".";
return "Historical weather data for " + coordinates + ".";
}
}

View File

@ -25,9 +25,11 @@ package com.github.prominence.openweathermap.api.model.onecall.historical;
import com.github.prominence.openweathermap.api.model.Clouds;
import com.github.prominence.openweathermap.api.model.Humidity;
import com.github.prominence.openweathermap.api.model.WeatherState;
import com.github.prominence.openweathermap.api.model.Wind;
import com.github.prominence.openweathermap.api.model.onecall.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
@ -36,7 +38,7 @@ import java.util.Objects;
public class HourlyHistorical {
private LocalDateTime forecastTime;
private WeatherState weatherState;
private List<WeatherState> weatherStates;
private Temperature temperature;
private AtmosphericPressure atmosphericPressure;
private Humidity humidity;
@ -69,17 +71,17 @@ public class HourlyHistorical {
*
* @return the weather state
*/
public WeatherState getWeatherState() {
return weatherState;
public List<WeatherState> getWeatherStates() {
return weatherStates;
}
/**
* Sets weather state.
*
* @param weatherState the weather state
* @param weatherStates the weather state
*/
public void setWeatherState(WeatherState weatherState) {
this.weatherState = weatherState;
public void setWeatherStates(List<WeatherState> weatherStates) {
this.weatherStates = weatherStates;
}
/**
@ -232,7 +234,7 @@ public class HourlyHistorical {
if (o == null || getClass() != o.getClass()) return false;
HourlyHistorical that = (HourlyHistorical) o;
return Objects.equals(forecastTime, that.forecastTime) &&
Objects.equals(weatherState, that.weatherState) &&
Objects.equals(weatherStates, that.weatherStates) &&
Objects.equals(temperature, that.temperature) &&
Objects.equals(atmosphericPressure, that.atmosphericPressure) &&
Objects.equals(humidity, that.humidity) &&
@ -245,7 +247,7 @@ public class HourlyHistorical {
@Override
public int hashCode() {
return Objects.hash(forecastTime, weatherState, temperature, atmosphericPressure, humidity, clouds, visibilityInMetres, wind, rain, snow);
return Objects.hash(forecastTime, weatherStates, temperature, atmosphericPressure, humidity, clouds, visibilityInMetres, wind, rain, snow);
}
@Override

View File

@ -22,7 +22,7 @@
package com.github.prominence.openweathermap.api.model.weather;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
@ -40,7 +40,7 @@ public class Location {
private LocalDateTime sunsetTime;
private ZoneOffset zoneOffset;
private Coordinate coordinate;
private Coordinates coordinates;
private Location(int id, String name) {
this.id = id;
@ -49,7 +49,8 @@ public class Location {
/**
* Creates {@link Location} object with correctness check.
* @param id location id
*
* @param id location id
* @param name location name
* @return location object
*/
@ -62,6 +63,7 @@ public class Location {
/**
* Returns ID.
*
* @return location ID
*/
public int getId() {
@ -70,6 +72,7 @@ public class Location {
/**
* Sets location ID.
*
* @param id location id
*/
public void setId(int id) {
@ -78,6 +81,7 @@ public class Location {
/**
* Returns location name.
*
* @return location name
*/
public String getName() {
@ -86,6 +90,7 @@ public class Location {
/**
* Sets location name.
*
* @param name location name
*/
public void setName(String name) {
@ -94,6 +99,7 @@ public class Location {
/**
* Returns country code.
*
* @return location country code
*/
public String getCountryCode() {
@ -102,6 +108,7 @@ public class Location {
/**
* Sets location country code.
*
* @param countryCode location country code
*/
public void setCountryCode(String countryCode) {
@ -110,6 +117,7 @@ public class Location {
/**
* Returns location sunrise time.
*
* @return sunrise time
*/
public LocalDateTime getSunriseTime() {
@ -118,6 +126,7 @@ public class Location {
/**
* Sets location sunrise time.
*
* @param sunriseTime sunrise time
*/
public void setSunriseTime(LocalDateTime sunriseTime) {
@ -126,6 +135,7 @@ public class Location {
/**
* Returns location sunset time.
*
* @return sunset time
*/
public LocalDateTime getSunsetTime() {
@ -134,6 +144,7 @@ public class Location {
/**
* Sets location sunset time.
*
* @param sunsetTime sunset time
*/
public void setSunsetTime(LocalDateTime sunsetTime) {
@ -142,6 +153,7 @@ public class Location {
/**
* Returns location timezone offset.
*
* @return timezone offset
*/
public ZoneOffset getZoneOffset() {
@ -150,6 +162,7 @@ public class Location {
/**
* Sets location timezone offset.
*
* @param zoneOffset timezone offset
*/
public void setZoneOffset(ZoneOffset zoneOffset) {
@ -158,18 +171,20 @@ public class Location {
/**
* Returns location coordinates.
*
* @return location coordinates.
*/
public Coordinate getCoordinate() {
return coordinate;
public Coordinates getCoordinate() {
return coordinates;
}
/**
* Sets location coordinates.
* @param coordinate location coordinates
*
* @param coordinates location coordinates
*/
public void setCoordinate(Coordinate coordinate) {
this.coordinate = coordinate;
public void setCoordinate(Coordinates coordinates) {
this.coordinates = coordinates;
}
@Override
@ -183,19 +198,19 @@ public class Location {
Objects.equals(sunriseTime, location.sunriseTime) &&
Objects.equals(sunsetTime, location.sunsetTime) &&
Objects.equals(zoneOffset, location.zoneOffset) &&
Objects.equals(coordinate, location.coordinate);
Objects.equals(coordinates, location.coordinates);
}
@Override
public int hashCode() {
return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinate);
return Objects.hash(id, name, countryCode, sunriseTime, sunsetTime, zoneOffset, coordinates);
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();
if (coordinate != null) {
stringBuilder.append(coordinate.toString());
if (coordinates != null) {
stringBuilder.append(coordinates.toString());
stringBuilder.append(". ");
}
stringBuilder.append("ID: ");

View File

@ -25,6 +25,7 @@ package com.github.prominence.openweathermap.api.model.weather;
import com.github.prominence.openweathermap.api.model.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
/**
@ -33,7 +34,7 @@ import java.util.Objects;
public class Weather {
private LocalDateTime calculationTime;
private WeatherState weatherState;
private List<WeatherState> weatherStates;
private Temperature temperature;
private AtmosphericPressure atmosphericPressure;
private Humidity humidity;
@ -45,6 +46,8 @@ public class Weather {
private Location location;
private String base;
/**
* Gets calculated on.
*
@ -68,17 +71,17 @@ public class Weather {
*
* @return the weather state
*/
public WeatherState getWeatherState() {
return weatherState;
public List<WeatherState> getWeatherStates() {
return weatherStates;
}
/**
* Sets weather state.
*
* @param weatherState the weather state
* @param weatherStates the weather state
*/
public void setWeatherState(WeatherState weatherState) {
this.weatherState = weatherState;
public void setWeatherStates(List<WeatherState> weatherStates) {
this.weatherStates = weatherStates;
}
/**
@ -225,13 +228,20 @@ public class Weather {
this.location = location;
}
public String getBase() {
return base;
}
public void setBase(String base) {
this.base = base;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Weather)) return false;
Weather weather = (Weather) o;
if (!(o instanceof Weather weather)) return false;
return Objects.equals(calculationTime, weather.calculationTime) &&
Objects.equals(weatherState, weather.weatherState) &&
Objects.equals(weatherStates, weather.weatherStates) &&
Objects.equals(temperature, weather.temperature) &&
Objects.equals(atmosphericPressure, weather.atmosphericPressure) &&
Objects.equals(humidity, weather.humidity) &&
@ -239,12 +249,13 @@ public class Weather {
Objects.equals(rain, weather.rain) &&
Objects.equals(snow, weather.snow) &&
Objects.equals(clouds, weather.clouds) &&
Objects.equals(location, weather.location);
Objects.equals(location, weather.location) &&
Objects.equals(base, weather.base);
}
@Override
public int hashCode() {
return Objects.hash(calculationTime, weatherState, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, location);
return Objects.hash(calculationTime, weatherStates, temperature, atmosphericPressure, humidity, wind, rain, snow, clouds, location, base);
}
@Override
@ -261,9 +272,9 @@ public class Weather {
stringBuilder.append(')');
}
}
if (weatherState != null) {
if (weatherStates != null && weatherStates.size() > 0) {
stringBuilder.append(", Weather: ");
stringBuilder.append(weatherState.getDescription());
stringBuilder.append(weatherStates.get(0).getDescription());
}
if (temperature != null) {
stringBuilder.append(", ");
@ -279,7 +290,7 @@ public class Weather {
}
if (clouds != null) {
stringBuilder.append(", ");
stringBuilder.append(clouds.toString());
stringBuilder.append(clouds);
}
if (rain != null && rain.getOneHourLevel() != null) {
stringBuilder.append(", Rain: ");

View File

@ -41,7 +41,9 @@ public class RequestSettings {
private final Map<String, String> requestParameters = new HashMap<>(8);
private final StringBuilder urlAppenderBuilder = new StringBuilder("");
private final StringBuilder urlAppenderBuilder = new StringBuilder();
private String subdomain = "api";
private Language language = Language.ENGLISH;
private UnitSystem unitSystem = UnitSystem.STANDARD;
@ -56,6 +58,14 @@ public class RequestSettings {
return timeoutSettings;
}
public String getSubdomain() {
return subdomain;
}
public void setSubdomain(String subdomain) {
this.subdomain = subdomain;
}
public UnitSystem getUnitSystem() {
return unitSystem;
}

View File

@ -42,7 +42,7 @@ public class AirPollutionAsyncRequestTerminator {
*
* @param requestSettings request settings object.
*/
public AirPollutionAsyncRequestTerminator(RequestSettings requestSettings) {
AirPollutionAsyncRequestTerminator(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}

View File

@ -37,7 +37,7 @@ public class AirPollutionRequestCustomizer {
*
* @param requestSettings request settings object.
*/
public AirPollutionRequestCustomizer(RequestSettings requestSettings) {
AirPollutionRequestCustomizer(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}

View File

@ -40,7 +40,7 @@ public class AirPollutionRequestTerminator {
*
* @param requestSettings request settings object.
*/
public AirPollutionRequestTerminator(RequestSettings requestSettings) {
AirPollutionRequestTerminator(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}

View File

@ -39,20 +39,20 @@ public class AirPollutionRequester {
*/
public AirPollutionRequester(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
requestSettings.appendToURL("data/2.5/air_pollution");
}
public CurrentAirPollutionRequester current() {
requestSettings.appendToURL("air_pollution");
return new CurrentAirPollutionRequester(requestSettings);
}
public ForecastAirPollutionRequester forecast() {
requestSettings.appendToURL("air_pollution/forecast");
requestSettings.appendToURL("/forecast");
return new ForecastAirPollutionRequester(requestSettings);
}
public HistoricalAirPollutionRequester historical() {
requestSettings.appendToURL("air_pollution/history");
requestSettings.appendToURL("/history");
return new HistoricalAirPollutionRequester(requestSettings);
}
}

View File

@ -22,7 +22,7 @@
package com.github.prominence.openweathermap.api.request.air.pollution;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.request.RequestSettings;
/**
@ -36,13 +36,13 @@ public class CurrentAirPollutionRequester {
*
* @param requestSettings request settings object.
*/
public CurrentAirPollutionRequester(RequestSettings requestSettings) {
CurrentAirPollutionRequester(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public AirPollutionRequestCustomizer byCoordinate(Coordinate coordinate) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude()));
public AirPollutionRequestCustomizer byCoordinates(Coordinates coordinates) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude()));
return new AirPollutionRequestCustomizer(requestSettings);
}
}

View File

@ -22,7 +22,7 @@
package com.github.prominence.openweathermap.api.request.air.pollution;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.request.RequestSettings;
/**
@ -36,13 +36,13 @@ public class ForecastAirPollutionRequester {
*
* @param requestSettings request settings object.
*/
public ForecastAirPollutionRequester(RequestSettings requestSettings) {
ForecastAirPollutionRequester(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public AirPollutionRequestCustomizer byCoordinate(Coordinate coordinate) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude()));
public AirPollutionRequestCustomizer byCoordinates(Coordinates coordinates) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude()));
return new AirPollutionRequestCustomizer(requestSettings);
}
}

View File

@ -22,7 +22,7 @@
package com.github.prominence.openweathermap.api.request.air.pollution;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.request.RequestSettings;
/**
@ -36,13 +36,13 @@ public class HistoricalAirPollutionRequester {
*
* @param requestSettings request settings object.
*/
public HistoricalAirPollutionRequester(RequestSettings requestSettings) {
HistoricalAirPollutionRequester(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public AirPollutionRequestCustomizer byCoordinateAndPeriod(Coordinate coordinate, long startUnixTime, long endUnixTime) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude()));
public AirPollutionRequestCustomizer byCoordinateAndPeriod(Coordinates coordinates, long startUnixTime, long endUnixTime) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude()));
requestSettings.putRequestParameter("start", String.valueOf(startUnixTime));
requestSettings.putRequestParameter("end", String.valueOf(endUnixTime));
return new AirPollutionRequestCustomizer(requestSettings);

View File

@ -20,34 +20,25 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.request.weather.multiple;
package com.github.prominence.openweathermap.api.request.forecast.daily;
import com.github.prominence.openweathermap.api.enums.ResponseType;
import com.github.prominence.openweathermap.api.model.weather.Weather;
import com.github.prominence.openweathermap.api.mapper.DailyForecastResponseMapper;
import com.github.prominence.openweathermap.api.model.forecast.daily.Forecast;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* The type Multiple result current weather async request terminator.
*/
public class MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator {
class DailyForecastAsyncRequestTerminator {
private final RequestSettings requestSettings;
/**
* Instantiates a new Multiple result current weather async request terminator.
*
* @param requestSettings request settings object.
*/
MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator(RequestSettings requestSettings) {
DailyForecastAsyncRequestTerminator(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public CompletableFuture<List<Weather>> asJava() {
return CompletableFuture.supplyAsync(() -> new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getList(getRawResponse()));
public CompletableFuture<Forecast> asJava() {
return CompletableFuture.supplyAsync(() -> new DailyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse()));
}
public CompletableFuture<String> asJSON() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
* 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
@ -20,42 +20,48 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.request.weather.multiple;
package com.github.prominence.openweathermap.api.request.forecast.daily;
import com.github.prominence.openweathermap.api.enums.Language;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class DailyForecastRequestCustomizer {
private static final Logger logger = LoggerFactory.getLogger(DailyForecastRequestCustomizer.class);
/**
* The type Multiple result current weather request customizer.
*/
public class MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer {
private final RequestSettings requestSettings;
/**
* Instantiates a new Multiple result current weather request customizer.
*
* @param requestSettings request settings object.
*/
MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer(RequestSettings requestSettings) {
public DailyForecastRequestCustomizer(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer language(Language language) {
public DailyForecastRequestCustomizer language(Language language) {
requestSettings.setLanguage(language);
return this;
}
public MultipleResultCitiesInCircleCurrentWeatherRequestCustomizer unitSystem(UnitSystem unitSystem) {
public DailyForecastRequestCustomizer unitSystem(UnitSystem unitSystem) {
requestSettings.setUnitSystem(unitSystem);
return this;
}
public MultipleResultCitiesInCircleCurrentWeatherRequestTerminator retrieve() {
return new MultipleResultCitiesInCircleCurrentWeatherRequestTerminator(requestSettings);
public DailyForecastRequestCustomizer numberOfDays(int numberOfDays) {
int days = numberOfDays;
if (days > 16) {
logger.warn("Cannot use more than 16 days for this api request. Please, specify 16 or less days. !!! Requesting information for 16 days...");
days = 16;
}
requestSettings.putRequestParameter("cnt", Integer.toString(days));
return this;
}
public MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator retrieveAsync() {
return new MultipleResultCitiesInCircleCurrentWeatherAsyncRequestTerminator(requestSettings);
public DailyForecastRequestTerminator retrieve() {
return new DailyForecastRequestTerminator(requestSettings);
}
}
public DailyForecastAsyncRequestTerminator retrieveAsync() {
return new DailyForecastAsyncRequestTerminator(requestSettings);
}
}

View File

@ -20,33 +20,23 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.request.weather.multiple;
package com.github.prominence.openweathermap.api.request.forecast.daily;
import com.github.prominence.openweathermap.api.enums.ResponseType;
import com.github.prominence.openweathermap.api.model.weather.Weather;
import com.github.prominence.openweathermap.api.mapper.DailyForecastResponseMapper;
import com.github.prominence.openweathermap.api.model.forecast.daily.Forecast;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
import java.util.List;
/**
* The type Multiple result current weather request terminator.
*/
public class MultipleResultCitiesInCircleCurrentWeatherRequestTerminator {
class DailyForecastRequestTerminator {
private final RequestSettings requestSettings;
/**
* Instantiates a new Multiple result current weather request terminator.
*
* @param requestSettings request settings object.
*/
MultipleResultCitiesInCircleCurrentWeatherRequestTerminator(RequestSettings requestSettings) {
DailyForecastRequestTerminator(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public List<Weather> asJava() {
return new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getList(getRawResponse());
public Forecast asJava() {
return new DailyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse());
}
public String asJSON() {

View File

@ -0,0 +1,41 @@
/*
* 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.forecast.daily;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.request.RequestSettings;
public class DailyForecastRequester {
private final RequestSettings requestSettings;
public DailyForecastRequester(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
this.requestSettings.appendToURL("data/2.5/forecast/hourly");
}
public DailyForecastRequestCustomizer byCoordinates(Coordinates coordinates) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude()));
return new DailyForecastRequestCustomizer(requestSettings);
}
}

View File

@ -24,7 +24,7 @@ package com.github.prominence.openweathermap.api.request.forecast.free;
import com.github.prominence.openweathermap.api.enums.ResponseType;
import com.github.prominence.openweathermap.api.mapper.FiveDayThreeHourStepForecastResponseMapper;
import com.github.prominence.openweathermap.api.model.forecast.Forecast;
import com.github.prominence.openweathermap.api.model.forecast.free.Forecast;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
@ -33,7 +33,7 @@ import java.util.concurrent.CompletableFuture;
/**
* Async request terminator.
*/
public class FiveDayThreeHourStepForecastAsyncRequestTerminator {
class FiveDayThreeHourStepForecastAsyncRequestTerminator {
private final RequestSettings requestSettings;
/**

View File

@ -29,7 +29,7 @@ import com.github.prominence.openweathermap.api.request.RequestSettings;
/**
* The forecast request customizer.
*/
public class FiveDayThreeHourStepForecastRequestCustomizer {
class FiveDayThreeHourStepForecastRequestCustomizer {
private final RequestSettings requestSettings;
/**

View File

@ -24,14 +24,14 @@ package com.github.prominence.openweathermap.api.request.forecast.free;
import com.github.prominence.openweathermap.api.enums.ResponseType;
import com.github.prominence.openweathermap.api.mapper.FiveDayThreeHourStepForecastResponseMapper;
import com.github.prominence.openweathermap.api.model.forecast.Forecast;
import com.github.prominence.openweathermap.api.model.forecast.free.Forecast;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
/**
* The forecast request terminator.
*/
public class FiveDayThreeHourStepForecastRequestTerminator {
class FiveDayThreeHourStepForecastRequestTerminator {
private final RequestSettings requestSettings;
/**

View File

@ -22,7 +22,7 @@
package com.github.prominence.openweathermap.api.request.forecast.free;
import com.github.prominence.openweathermap.api.model.Coordinate;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.request.RequestSettings;
/**
@ -38,7 +38,7 @@ public class FiveDayThreeHourStepForecastRequester {
*/
public FiveDayThreeHourStepForecastRequester(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
this.requestSettings.appendToURL("forecast");
this.requestSettings.appendToURL("data/2.5/forecast");
}
public FiveDayThreeHourStepForecastRequestCustomizer byCityName(String cityName) {
@ -61,9 +61,9 @@ public class FiveDayThreeHourStepForecastRequester {
return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings);
}
public FiveDayThreeHourStepForecastRequestCustomizer byCoordinate(Coordinate coordinate) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinate.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinate.getLongitude()));
public FiveDayThreeHourStepForecastRequestCustomizer byCoordinates(Coordinates coordinates) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude()));
return new FiveDayThreeHourStepForecastRequestCustomizer(requestSettings);
}

View File

@ -20,39 +20,36 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.request.weather.multiple;
package com.github.prominence.openweathermap.api.request.forecast.hourly;
import com.github.prominence.openweathermap.api.model.weather.Weather;
import com.github.prominence.openweathermap.api.enums.ResponseType;
import com.github.prominence.openweathermap.api.mapper.HourlyForecastResponseMapper;
import com.github.prominence.openweathermap.api.model.forecast.hourly.HourlyForecast;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* The type Multiple result current weather async request terminator.
*/
public class MultipleResultCurrentWeatherAsyncRequestTerminator {
class FourDaysHourlyForecastAsyncRequestTerminator {
private final RequestSettings requestSettings;
/**
* Instantiates a new Multiple result current weather async request terminator.
*
* @param requestSettings request settings object.
*/
MultipleResultCurrentWeatherAsyncRequestTerminator(RequestSettings requestSettings) {
FourDaysHourlyForecastAsyncRequestTerminator(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public CompletableFuture<List<Weather>> asJava() {
return CompletableFuture.supplyAsync(() -> new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getList(getRawResponse()));
public CompletableFuture<HourlyForecast> asJava() {
return CompletableFuture.supplyAsync(() -> new HourlyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse()));
}
public CompletableFuture<String> asJSON() {
return CompletableFuture.supplyAsync(this::getRawResponse);
}
public CompletableFuture<String> asXML() {
requestSettings.setResponseType(ResponseType.XML);
return CompletableFuture.supplyAsync(this::getRawResponse);
}
private String getRawResponse() {
return RequestUtils.getResponse(requestSettings);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Alexey Zinchenko
* 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
@ -20,42 +20,33 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.request.weather.multiple;
package com.github.prominence.openweathermap.api.request.forecast.hourly;
import com.github.prominence.openweathermap.api.enums.Language;
import com.github.prominence.openweathermap.api.enums.UnitSystem;
import com.github.prominence.openweathermap.api.request.RequestSettings;
/**
* The type Multiple result current weather request customizer.
*/
public class MultipleResultCurrentWeatherRequestCustomizer {
class FourDaysHourlyForecastRequestCustomizer {
private final RequestSettings requestSettings;
/**
* Instantiates a new Multiple result current weather request customizer.
*
* @param requestSettings request settings object.
*/
MultipleResultCurrentWeatherRequestCustomizer(RequestSettings requestSettings) {
public FourDaysHourlyForecastRequestCustomizer(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public MultipleResultCurrentWeatherRequestCustomizer language(Language language) {
public FourDaysHourlyForecastRequestCustomizer language(Language language) {
requestSettings.setLanguage(language);
return this;
}
public MultipleResultCurrentWeatherRequestCustomizer unitSystem(UnitSystem unitSystem) {
requestSettings.setUnitSystem(unitSystem);
public FourDaysHourlyForecastRequestCustomizer count(int numberOfTimestamps) {
requestSettings.putRequestParameter("cnt", Integer.toString(numberOfTimestamps));
return this;
}
public MultipleResultCurrentWeatherRequestTerminator retrieve() {
return new MultipleResultCurrentWeatherRequestTerminator(requestSettings);
public FourDaysHourlyForecastRequestTerminator retrieve() {
return new FourDaysHourlyForecastRequestTerminator(requestSettings);
}
public MultipleResultCurrentWeatherAsyncRequestTerminator retrieveAsync() {
return new MultipleResultCurrentWeatherAsyncRequestTerminator(requestSettings);
public FourDaysHourlyForecastAsyncRequestTerminator retrieveAsync() {
return new FourDaysHourlyForecastAsyncRequestTerminator(requestSettings);
}
}
}

View File

@ -20,38 +20,34 @@
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.request.weather.multiple;
package com.github.prominence.openweathermap.api.request.forecast.hourly;
import com.github.prominence.openweathermap.api.model.weather.Weather;
import com.github.prominence.openweathermap.api.enums.ResponseType;
import com.github.prominence.openweathermap.api.mapper.HourlyForecastResponseMapper;
import com.github.prominence.openweathermap.api.model.forecast.hourly.HourlyForecast;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.mapper.CurrentWeatherResponseMapper;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
import java.util.List;
/**
* The type Multiple result current weather request terminator.
*/
public class MultipleResultCurrentWeatherRequestTerminator {
class FourDaysHourlyForecastRequestTerminator {
private final RequestSettings requestSettings;
/**
* Instantiates a new Multiple result current weather request terminator.
*
* @param requestSettings request settings object.
*/
MultipleResultCurrentWeatherRequestTerminator(RequestSettings requestSettings) {
FourDaysHourlyForecastRequestTerminator(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public List<Weather> asJava() {
return new CurrentWeatherResponseMapper(requestSettings.getUnitSystem()).getList(getRawResponse());
public HourlyForecast asJava() {
return new HourlyForecastResponseMapper(requestSettings.getUnitSystem()).mapToForecast(getRawResponse());
}
public String asJSON() {
return getRawResponse();
}
public String asXML() {
requestSettings.setResponseType(ResponseType.XML);
return getRawResponse();
}
private String getRawResponse() {
return RequestUtils.getResponse(requestSettings);
}

View File

@ -0,0 +1,42 @@
/*
* 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.forecast.hourly;
import com.github.prominence.openweathermap.api.model.Coordinates;
import com.github.prominence.openweathermap.api.request.RequestSettings;
public class FourDaysHourlyForecastRequester {
private final RequestSettings requestSettings;
public FourDaysHourlyForecastRequester(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
this.requestSettings.appendToURL("data/2.5/forecast/hourly");
this.requestSettings.setSubdomain("pro");
}
public FourDaysHourlyForecastRequestCustomizer byCoordinates(Coordinates coordinates) {
requestSettings.putRequestParameter("lat", String.valueOf(coordinates.getLatitude()));
requestSettings.putRequestParameter("lon", String.valueOf(coordinates.getLongitude()));
return new FourDaysHourlyForecastRequestCustomizer(requestSettings);
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2022 Alexey Zinchenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.prominence.openweathermap.api.request.geocoding;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.request.geocoding.direct.DirectGeocodingRequester;
import com.github.prominence.openweathermap.api.request.geocoding.reverse.ReverseGeocodingRequester;
public class GeocodingRequester {
private final RequestSettings requestSettings;
public GeocodingRequester(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
this.requestSettings.appendToURL("geo/1.0");
}
public DirectGeocodingRequester direct() {
return new DirectGeocodingRequester(requestSettings);
}
public ReverseGeocodingRequester reverse() {
return new ReverseGeocodingRequester(requestSettings);
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.geocoding.direct;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
public class DirectGeocodingRequestAsyncTerminator<R> {
private final RequestSettings requestSettings;
private final Function<String, R> mapperFunction;
DirectGeocodingRequestAsyncTerminator(RequestSettings requestSettings, Function<String, R> mapperFunction) {
this.requestSettings = requestSettings;
this.mapperFunction = mapperFunction;
}
public CompletableFuture<R> asJava() {
return CompletableFuture.supplyAsync(() -> mapperFunction.apply(getRawResponse()));
}
public CompletableFuture<String> asJSON() {
return CompletableFuture.supplyAsync(this::getRawResponse);
}
private String getRawResponse() {
return RequestUtils.getResponse(requestSettings);
}
}

View File

@ -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.request.geocoding.direct;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.request.geocoding.reverse.ReverseGeocodingRequestAsyncTerminator;
import com.github.prominence.openweathermap.api.request.geocoding.reverse.ReverseGeocodingRequestTerminator;
import java.util.function.Function;
public class DirectGeocodingRequestCustomizer<R> {
private final RequestSettings requestSettings;
private final Function<String, R> mapperFunction;
DirectGeocodingRequestCustomizer(RequestSettings requestSettings, Function<String, R> mapperFunction) {
this.requestSettings = requestSettings;
this.mapperFunction = mapperFunction;
}
public DirectGeocodingRequestCustomizer<R> limit(int locationsNumber) {
requestSettings.putRequestParameter("limit", Integer.toString(locationsNumber));
return this;
}
public DirectGeocodingRequestTerminator<R> retrieve() {
return new DirectGeocodingRequestTerminator<R>(requestSettings, mapperFunction);
}
public DirectGeocodingRequestAsyncTerminator<R> retrieveAsync() {
return new DirectGeocodingRequestAsyncTerminator<R>(requestSettings, mapperFunction);
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.geocoding.direct;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import com.github.prominence.openweathermap.api.utils.RequestUtils;
import java.util.function.Function;
public class DirectGeocodingRequestTerminator<R> {
private final RequestSettings requestSettings;
private final Function<String, R> mapperFunction;
DirectGeocodingRequestTerminator(RequestSettings requestSettings, Function<String, R> mapperFunction) {
this.requestSettings = requestSettings;
this.mapperFunction = mapperFunction;
}
public R asJava() {
return mapperFunction.apply(asJSON());
}
public String asJSON() {
return getRawResponse();
}
private String getRawResponse() {
return RequestUtils.getResponse(requestSettings);
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.geocoding.direct;
import com.github.prominence.openweathermap.api.mapper.GeocodingResponseMapper;
import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord;
import com.github.prominence.openweathermap.api.model.geocoding.ZipCodeGeocodingRecord;
import com.github.prominence.openweathermap.api.request.RequestSettings;
import java.util.List;
public class DirectGeocodingRequester {
private final RequestSettings requestSettings;
public DirectGeocodingRequester(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public DirectGeocodingRequestCustomizer<List<GeocodingRecord>> byLocationName(String cityName, String stateCode, String countryCode) {
requestSettings.appendToURL("direct");
requestSettings.putRequestParameter("q", cityName + "," + stateCode + "," + countryCode);
return new DirectGeocodingRequestCustomizer<>(requestSettings, (String json) -> new GeocodingResponseMapper().mapGeocodingResponse(json));
}
public DirectGeocodingRequestCustomizer<ZipCodeGeocodingRecord> byZipCode(String zipCode, String countryCode) {
requestSettings.appendToURL("zip");
requestSettings.putRequestParameter("zip", zipCode + "," + countryCode);
return new DirectGeocodingRequestCustomizer<>(requestSettings, (String json) -> new GeocodingResponseMapper().mapZipCodeGeocodingResponse(json));
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.geocoding.reverse;
import com.github.prominence.openweathermap.api.mapper.GeocodingResponseMapper;
import com.github.prominence.openweathermap.api.model.geocoding.GeocodingRecord;
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;
public class ReverseGeocodingRequestAsyncTerminator {
private final RequestSettings requestSettings;
ReverseGeocodingRequestAsyncTerminator(RequestSettings requestSettings) {
this.requestSettings = requestSettings;
}
public CompletableFuture<List<GeocodingRecord>> asJava() {
return CompletableFuture.supplyAsync(() -> new GeocodingResponseMapper().mapGeocodingResponse(getRawResponse()));
}
public CompletableFuture<String> asJSON() {
return CompletableFuture.supplyAsync(this::getRawResponse);
}
private String getRawResponse() {
return RequestUtils.getResponse(requestSettings);
}
}

Some files were not shown because too many files have changed in this diff Show More