mirror of
https://bitbucket.org/akapribot/owm-japis.git
synced 2025-04-29 00:38:11 -07:00
v2.5.0.3 - Lots of new features and changes. It's exciting. :)
This commit is contained in:
parent
a3156175a3
commit
a573686f24
143 changed files with 9372 additions and 26935 deletions
248
src/main/java/net/aksingh/owmjapis/AbstractForecast.java
Normal file
248
src/main/java/net/aksingh/owmjapis/AbstractForecast.java
Normal file
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 Ashutosh Kumar Singh <me@aksingh.net>
|
||||
*
|
||||
* 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 net.aksingh.owmjapis;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides default behaviours and implementations for:
|
||||
* 1. {@link net.aksingh.owmjapis.HourlyForecast}
|
||||
* 2. {@link net.aksingh.owmjapis.DailyForecast}
|
||||
* It defines common methods like <code>has</code>, <code>get</code> and some others.
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/27
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
public abstract class AbstractForecast extends AbstractResponse {
|
||||
/*
|
||||
JSON Keys
|
||||
*/
|
||||
final String JSON_FORECAST_LIST = "list";
|
||||
|
||||
/*
|
||||
Instance variables
|
||||
*/
|
||||
private final double message;
|
||||
|
||||
private final City city;
|
||||
private final int forecastCount;
|
||||
|
||||
/*
|
||||
Constructors
|
||||
*/
|
||||
AbstractForecast() {
|
||||
super();
|
||||
|
||||
this.message = Double.NaN;
|
||||
this.forecastCount = 0;
|
||||
this.city = null;
|
||||
}
|
||||
|
||||
AbstractForecast(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
|
||||
final String JSON_MESSAGE = "message";
|
||||
final String JSON_CITY = "city";
|
||||
final String JSON_FORECAST_COUNT = "cnt";
|
||||
|
||||
this.message = (jsonObj != null) ? jsonObj.optDouble(JSON_MESSAGE, Double.NaN) : Double.NaN;
|
||||
|
||||
this.city = (jsonObj != null) ? new City(jsonObj.optJSONObject(JSON_CITY)) : null;
|
||||
|
||||
this.forecastCount = (jsonObj != null) ? jsonObj.optInt(JSON_FORECAST_COUNT, 0) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if message is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasMessage() {
|
||||
return (this.message != Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if count of forecasts is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasForecastCount() {
|
||||
return (this.forecastCount != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if message is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasCityInstance() {
|
||||
return (this.city != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Message if available, otherwise <code>Double.NaN</code>.
|
||||
*/
|
||||
public double getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Count of forecasts if available, otherwise <code>0</code>.
|
||||
*/
|
||||
public int getForecastCount() {
|
||||
return this.forecastCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return City's instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public City getCityInstance() {
|
||||
return this.city;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides default behaviours for City
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
*/
|
||||
public static class City {
|
||||
private final String JSON_CITY_ID = "id";
|
||||
private final String JSON_CITY_NAME = "name";
|
||||
private final String JSON_CITY_COUNTRY_CODE = "country";
|
||||
private final String JSON_CITY_POPULATION = "population";
|
||||
private final String JSON_CITY_COORD = "coord";
|
||||
|
||||
private final long cityID;
|
||||
private final String cityName;
|
||||
private final String countryCode;
|
||||
private final long population;
|
||||
|
||||
private final Coord coord;
|
||||
|
||||
City() {
|
||||
this.cityID = Long.MIN_VALUE;
|
||||
this.cityName = null;
|
||||
this.countryCode = null;
|
||||
this.population = Long.MIN_VALUE;
|
||||
|
||||
this.coord = new Coord();
|
||||
}
|
||||
|
||||
City(JSONObject jsonObj) {
|
||||
this.cityID = (jsonObj != null) ? jsonObj.optLong(this.JSON_CITY_ID, Long.MIN_VALUE) : Long.MIN_VALUE;
|
||||
this.cityName = (jsonObj != null) ? jsonObj.optString(this.JSON_CITY_NAME, null) : null;
|
||||
this.countryCode = (jsonObj != null) ? jsonObj.optString(this.JSON_CITY_COUNTRY_CODE, null) : null;
|
||||
this.population = (jsonObj != null) ? jsonObj.optLong(this.JSON_CITY_POPULATION, Long.MIN_VALUE) : Long.MIN_VALUE;
|
||||
|
||||
JSONObject jsonObjCoord = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_CITY_COORD) : null;
|
||||
this.coord = (jsonObjCoord != null) ? new Coord(jsonObjCoord) : null;
|
||||
}
|
||||
|
||||
public boolean hasCityCode() {
|
||||
return (this.cityID != Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
public boolean hasCityName() {
|
||||
return (this.cityName != null);
|
||||
}
|
||||
|
||||
public boolean hasCountryCode() {
|
||||
return (this.countryCode != null);
|
||||
}
|
||||
|
||||
public boolean hasCityPopulation() {
|
||||
return (this.population != Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Coord instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasCoordInstance() {
|
||||
return (coord != null);
|
||||
}
|
||||
|
||||
public long getCityCode() {
|
||||
return this.cityID;
|
||||
}
|
||||
|
||||
public String getCityName() {
|
||||
return this.cityName;
|
||||
}
|
||||
|
||||
public String getCountryCode() {
|
||||
return this.countryCode;
|
||||
}
|
||||
|
||||
public long getCityPopulation() {
|
||||
return this.population;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Coord instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Coord getCoordInstance() {
|
||||
return this.coord;
|
||||
}
|
||||
|
||||
|
||||
public static class Coord extends AbstractWeather.Coord {
|
||||
|
||||
Coord() {
|
||||
super();
|
||||
}
|
||||
|
||||
Coord(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses forecast data (one element in the forecastList) and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/27
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
public abstract static class Forecast extends AbstractWeather {
|
||||
Forecast() {
|
||||
super();
|
||||
}
|
||||
|
||||
Forecast(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
}
|
||||
}
|
||||
}
|
92
src/main/java/net/aksingh/owmjapis/AbstractResponse.java
Normal file
92
src/main/java/net/aksingh/owmjapis/AbstractResponse.java
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 Ashutosh Kumar Singh <me@aksingh.net>
|
||||
*
|
||||
* 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 net.aksingh.owmjapis;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides default behaviours and implementations for the response from OWM.org
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/28
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
abstract class AbstractResponse {
|
||||
/*
|
||||
Instance variables
|
||||
*/
|
||||
private final int responseCode;
|
||||
private final String rawResponse;
|
||||
|
||||
/*
|
||||
Constructors
|
||||
*/
|
||||
AbstractResponse() {
|
||||
this.rawResponse = null;
|
||||
this.responseCode = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
AbstractResponse(JSONObject jsonObj) {
|
||||
final String JSON_RESPONSE_CODE = "cod";
|
||||
|
||||
this.rawResponse = (jsonObj != null) ? jsonObj.toString() : null;
|
||||
this.responseCode = (jsonObj != null) ? jsonObj.optInt(JSON_RESPONSE_CODE, Integer.MIN_VALUE) : Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if response is valid (downloaded and parsed correctly), otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return (this.responseCode == 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if response code is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasResponseCode() {
|
||||
return (this.responseCode != Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if raw response is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasRawResponse() {
|
||||
return (this.rawResponse != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Response code if available, otherwise <code>Integer.MIN_VALUE</code>.
|
||||
*/
|
||||
public int getResponseCode() {
|
||||
return this.responseCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Raw response if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public String getRawResponse() {
|
||||
return this.rawResponse;
|
||||
}
|
||||
}
|
527
src/main/java/net/aksingh/owmjapis/AbstractWeather.java
Normal file
527
src/main/java/net/aksingh/owmjapis/AbstractWeather.java
Normal file
|
@ -0,0 +1,527 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 Ashutosh Kumar Singh <me@aksingh.net>
|
||||
*
|
||||
* 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 net.aksingh.owmjapis;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides default behaviours and implementations for:
|
||||
* 1. {@link net.aksingh.owmjapis.CurrentWeather}
|
||||
* It defines common methods like <code>has</code>, <code>get</code> and some others.
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/21
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public abstract class AbstractWeather extends AbstractResponse {
|
||||
/*
|
||||
JSON Keys
|
||||
*/
|
||||
final String JSON_CLOUDS = "clouds";
|
||||
final String JSON_COORD = "coord";
|
||||
final String JSON_MAIN = "main";
|
||||
final String JSON_WIND = "wind";
|
||||
|
||||
/*
|
||||
Instance variables
|
||||
*/
|
||||
private final Date dateTime;
|
||||
|
||||
private final int weatherCount;
|
||||
private final List<Weather> weatherList;
|
||||
|
||||
/*
|
||||
Constructors
|
||||
*/
|
||||
AbstractWeather() {
|
||||
super();
|
||||
|
||||
this.weatherCount = 0;
|
||||
this.weatherList = null;
|
||||
this.dateTime = null;
|
||||
}
|
||||
|
||||
AbstractWeather(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
|
||||
final String JSON_WEATHER = "weather";
|
||||
final String JSON_DATE_TIME = "dt";
|
||||
|
||||
long sec = (jsonObj != null) ? jsonObj.optLong(JSON_DATE_TIME, Long.MIN_VALUE) : Long.MIN_VALUE;
|
||||
if (sec != Long.MIN_VALUE) { // converting seconds to Date object
|
||||
/*
|
||||
Bugfix: It always return "Sat Jan 17 04:10:42 CET 1970"
|
||||
Issue: #3 at http://code.aksingh.net/owm-japis/issue/3/problem-with-datetime
|
||||
Incorrect: this.dateTime = new Date(sec);
|
||||
Correct: this.dateTime = new Date(sec * 1000);
|
||||
Reason: Date requires milliseconds but previously, seconds were provided.
|
||||
*/
|
||||
this.dateTime = new Date(sec * 1000);
|
||||
} else {
|
||||
this.dateTime = null;
|
||||
}
|
||||
|
||||
JSONArray weatherArray = (jsonObj != null) ? jsonObj.optJSONArray(JSON_WEATHER) : new JSONArray();
|
||||
this.weatherList = (weatherArray != null) ? new ArrayList<Weather>(weatherArray.length()) : Collections.EMPTY_LIST;
|
||||
if (this.weatherList != Collections.EMPTY_LIST) {
|
||||
for (int i = 0; i < weatherArray.length(); i++) {
|
||||
JSONObject weatherObj = weatherArray.optJSONObject(i);
|
||||
if (weatherObj != null) {
|
||||
this.weatherList.add(new Weather(weatherObj));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.weatherCount = this.weatherList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if date/time is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasDateTime() {
|
||||
return (this.dateTime != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Weather instance(s) is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasWeatherInstance() {
|
||||
return (weatherCount != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Date and time if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Date getDateTime() {
|
||||
return this.dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Count of Weather instance(s) if available, otherwise 0.
|
||||
*/
|
||||
public int getWeatherCount() {
|
||||
return this.weatherCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index Index of Weather instance in the list.
|
||||
* @return Weather instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Weather getWeatherInstance(int index) {
|
||||
return this.weatherList.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides default behaviours for Cloud
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2013/12/23
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
abstract public static class Clouds {
|
||||
private final String JSON_CLOUDS_ALL = "all";
|
||||
|
||||
private final float percentOfClouds;
|
||||
|
||||
Clouds() {
|
||||
this.percentOfClouds = Float.NaN;
|
||||
}
|
||||
|
||||
Clouds(JSONObject jsonObj) {
|
||||
this.percentOfClouds = (float) jsonObj.optDouble(this.JSON_CLOUDS_ALL, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if percentage of clouds is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean hasPercentageOfClouds() {
|
||||
return (this.percentOfClouds != Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Percentage of all clouds if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getPercentageOfClouds() {
|
||||
return this.percentOfClouds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides default behaviours for Coord, i.e., coordinates.
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2013/12/23
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
abstract public static class Coord {
|
||||
private final String JSON_COORD_LATITUDE = "lat";
|
||||
private final String JSON_COORD_LONGITUDE = "lon";
|
||||
|
||||
private final float lat;
|
||||
private final float lon;
|
||||
|
||||
Coord() {
|
||||
this.lat = Float.NaN;
|
||||
this.lon = Float.NaN;
|
||||
}
|
||||
|
||||
Coord(JSONObject jsonObj) {
|
||||
this.lat = (float) jsonObj.optDouble(this.JSON_COORD_LATITUDE, Double.NaN);
|
||||
this.lon = (float) jsonObj.optDouble(this.JSON_COORD_LONGITUDE, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the latitude of the city is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean hasLatitude() {
|
||||
return (this.lat != Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the longitude of the city is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean hasLongitude() {
|
||||
return (this.lon != Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Latitude of the city if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getLatitude() {
|
||||
return this.lat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Longitude of the city if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getLongitude() {
|
||||
return this.lon;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides default behaviours for Main, i.e., main weather elements like temperature, humidity, etc.
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2013/12/23
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
abstract public static class Main {
|
||||
|
||||
private final String JSON_MAIN_TEMP = "temp";
|
||||
private final String JSON_MAIN_TEMP_MIN = "temp_min";
|
||||
private final String JSON_MAIN_TEMP_MAX = "temp_max";
|
||||
private final String JSON_MAIN_PRESSURE = "pressure";
|
||||
private final String JSON_MAIN_HUMIDITY = "humidity";
|
||||
|
||||
private final float temp;
|
||||
private final float minTemp;
|
||||
private final float maxTemp;
|
||||
private final float pressure;
|
||||
private final float humidity;
|
||||
|
||||
Main() {
|
||||
this.temp = Float.NaN;
|
||||
this.minTemp = Float.NaN;
|
||||
this.maxTemp = Float.NaN;
|
||||
this.pressure = Float.NaN;
|
||||
this.humidity = Float.NaN;
|
||||
}
|
||||
|
||||
Main(JSONObject jsonObj) {
|
||||
this.temp = (float) jsonObj.optDouble(this.JSON_MAIN_TEMP, Double.NaN);
|
||||
this.minTemp = (float) jsonObj.optDouble(this.JSON_MAIN_TEMP_MIN, Double.NaN);
|
||||
this.maxTemp = (float) jsonObj.optDouble(this.JSON_MAIN_TEMP_MAX, Double.NaN);
|
||||
this.pressure = (float) jsonObj.optDouble(this.JSON_MAIN_PRESSURE, Double.NaN);
|
||||
this.humidity = (float) jsonObj.optDouble(this.JSON_MAIN_HUMIDITY, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the temperature of the city is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean hasTemperature() {
|
||||
return (this.temp != Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the minimum temperature of the city is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean hasMinTemperature() {
|
||||
return (this.minTemp != Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the maximum temperature of the city is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean hasMaxTemperature() {
|
||||
return (this.maxTemp != Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if pressure of the city is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean hasPressure() {
|
||||
return (this.pressure != Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if humidity of the city is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>
|
||||
*/
|
||||
public boolean hasHumidity() {
|
||||
return (this.humidity != Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Temperature of the city if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getTemperature() {
|
||||
return this.temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Minimum temperature of the city if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getMinTemperature() {
|
||||
return this.minTemp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Maximum temperature of the city if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getMaxTemperature() {
|
||||
return this.maxTemp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pressure of the city if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getPressure() {
|
||||
return this.pressure;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Humidity of the city if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getHumidity() {
|
||||
return this.humidity;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses weather data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/27
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
public static class Weather {
|
||||
private final String JSON_WEATHER_ID = "id";
|
||||
private final String JSON_WEATHER_MAIN = "main";
|
||||
private final String JSON_WEATHER_DESCRIPTION = "description";
|
||||
private final String JSON_WEATHER_ICON = "icon";
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final String icon;
|
||||
|
||||
Weather() {
|
||||
this.id = Integer.MIN_VALUE;
|
||||
this.name = null;
|
||||
this.description = null;
|
||||
this.icon = null;
|
||||
}
|
||||
|
||||
Weather(JSONObject jsonObj) {
|
||||
this.id = jsonObj.optInt(this.JSON_WEATHER_ID, Integer.MIN_VALUE);
|
||||
this.name = jsonObj.optString(this.JSON_WEATHER_MAIN, null);
|
||||
this.description = jsonObj.optString(this.JSON_WEATHER_DESCRIPTION, null);
|
||||
this.icon = jsonObj.optString(this.JSON_WEATHER_ICON, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if weather's code is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasWeatherCode() {
|
||||
return (this.id != Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if weather's name is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasWeatherName() {
|
||||
return (this.name != null && (!this.name.equals("")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if weather's description is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasWeatherDescription() {
|
||||
return (this.description != null && (!this.description.equals("")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if name of weather's icon is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasWeatherIconName() {
|
||||
return (this.icon != null && (!this.icon.equals("")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Code for weather of the city if available, otherwise <code>Integer.MIN_VALUE</code>.
|
||||
*/
|
||||
public int getWeatherCode() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name for weather of the city if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public String getWeatherName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Description for weather of the city if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public String getWeatherDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name of icon for weather of the city if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public String getWeatherIconName() {
|
||||
return this.icon;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides default behaviours for Wind.
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2013/12/23
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
abstract public static class Wind {
|
||||
private final String JSON_WIND_SPEED = "speed";
|
||||
private final String JSON_WIND_DEGREE = "deg";
|
||||
|
||||
private final float speed;
|
||||
private final float degree;
|
||||
|
||||
Wind() {
|
||||
this.speed = Float.NaN;
|
||||
this.degree = Float.NaN;
|
||||
}
|
||||
|
||||
Wind(JSONObject jsonObj) {
|
||||
this.speed = (float) jsonObj.optDouble(this.JSON_WIND_SPEED, Double.NaN);
|
||||
this.degree = (float) jsonObj.optDouble(this.JSON_WIND_DEGREE, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if speed of wind in the city is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasWindSpeed() {
|
||||
return (this.speed != Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if degree (degree gives direction) of wind in the city is available or not.
|
||||
*
|
||||
* @return <code>true</code> if data available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasWindDegree() {
|
||||
return (this.hasWindSpeed() && (this.degree != Float.NaN));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Speed of wind in the city if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getWindSpeed() {
|
||||
return this.speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Degree of wind in the city if available, otherwise <code>Float.NaN</code>.
|
||||
*/
|
||||
public float getWindDegree() {
|
||||
return this.degree;
|
||||
}
|
||||
}
|
||||
}
|
537
src/main/java/net/aksingh/owmjapis/CurrentWeather.java
Normal file
537
src/main/java/net/aksingh/owmjapis/CurrentWeather.java
Normal file
|
@ -0,0 +1,537 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 Ashutosh Kumar Singh <me@aksingh.net>
|
||||
*
|
||||
* 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 net.aksingh.owmjapis;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses current weather data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @see <a href="http://openweathermap.org/current">OWM's Current Weather API</a>
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public class CurrentWeather extends AbstractWeather {
|
||||
/*
|
||||
Instance variables
|
||||
*/
|
||||
private final String base;
|
||||
private final long cityId;
|
||||
private final String cityName;
|
||||
|
||||
private final Clouds clouds;
|
||||
private final Coord coord;
|
||||
private final Main main;
|
||||
private final Rain rain;
|
||||
private final Sys sys;
|
||||
private final Wind wind;
|
||||
|
||||
/*
|
||||
Constructor
|
||||
*/
|
||||
CurrentWeather(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
|
||||
final String JSON_RAIN = "rain";
|
||||
final String JSON_SYS = "sys";
|
||||
final String JSON_BASE = "base";
|
||||
final String JSON_CITY_ID = "id";
|
||||
final String JSON_CITY_NAME = "name";
|
||||
|
||||
this.base = (jsonObj != null) ? jsonObj.optString(JSON_BASE, null) : null;
|
||||
this.cityId = (jsonObj != null) ? jsonObj.optLong(JSON_CITY_ID, Long.MIN_VALUE) : Long.MIN_VALUE;
|
||||
this.cityName = (jsonObj != null) ? jsonObj.optString(JSON_CITY_NAME, null) : null;
|
||||
|
||||
JSONObject cloudsObj = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_CLOUDS) : null;
|
||||
this.clouds = (cloudsObj != null) ? new Clouds(cloudsObj) : null;
|
||||
|
||||
JSONObject coordObj = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_COORD) : null;
|
||||
this.coord = (coordObj != null) ? new Coord(coordObj) : null;
|
||||
|
||||
JSONObject mainObj = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_MAIN) : null;
|
||||
this.main = (mainObj != null) ? new Main(mainObj) : null;
|
||||
|
||||
JSONObject rainObj = (jsonObj != null) ? jsonObj.optJSONObject(JSON_RAIN) : null;
|
||||
this.rain = (rainObj != null) ? new Rain(rainObj) : null;
|
||||
|
||||
JSONObject sysObj = (jsonObj != null) ? jsonObj.optJSONObject(JSON_SYS) : null;
|
||||
this.sys = (sysObj != null) ? new Sys(sysObj) : null;
|
||||
|
||||
JSONObject windObj = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_WIND) : null;
|
||||
this.wind = (windObj != null) ? new Wind(windObj) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if base station is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasBaseStation() {
|
||||
return (this.base != null && (!this.base.equals("")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if city code is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasCityCode() {
|
||||
return (this.cityId != Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if city name is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasCityName() {
|
||||
return (this.cityName != null && (!this.cityName.equals("")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Clouds instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasCloudsInstance() {
|
||||
return (clouds != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Coord instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasCoordInstance() {
|
||||
return (coord != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Main instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasMainInstance() {
|
||||
return (main != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Rain instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasRainInstance() {
|
||||
return (rain != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Sys instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasSysInstance() {
|
||||
return (sys != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Wind instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasWindInstance() {
|
||||
return (wind != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Base station if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public String getBaseStation() {
|
||||
return this.base;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return City code if available, otherwise <code>Long.MIN_VALUE</code>.
|
||||
*/
|
||||
public long getCityCode() {
|
||||
return this.cityId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return City name if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public String getCityName() {
|
||||
return this.cityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Clouds instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Clouds getCloudsInstance() {
|
||||
return this.clouds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Coord instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Coord getCoordInstance() {
|
||||
return this.coord;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Main instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Main getMainInstance() {
|
||||
return this.main;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Rain instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Rain getRainInstance() {
|
||||
return this.rain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Sys instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Sys getSysInstance() {
|
||||
return this.sys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Wind instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Wind getWindInstance() {
|
||||
return this.wind;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses clouds data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Clouds extends AbstractWeather.Clouds {
|
||||
|
||||
Clouds() {
|
||||
super();
|
||||
}
|
||||
|
||||
Clouds(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses coordination data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Coord extends AbstractWeather.Coord {
|
||||
|
||||
Coord() {
|
||||
super();
|
||||
}
|
||||
|
||||
Coord(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses main data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Main extends AbstractWeather.Main {
|
||||
|
||||
Main() {
|
||||
super();
|
||||
}
|
||||
|
||||
Main(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses rain data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Rain {
|
||||
|
||||
private final String JSON_RAIN_1HOUR = "1h";
|
||||
|
||||
private final float rain1h;
|
||||
|
||||
Rain() {
|
||||
this.rain1h = Float.NaN;
|
||||
}
|
||||
|
||||
Rain(JSONObject jsonObj) {
|
||||
this.rain1h = (float) jsonObj.optDouble(this.JSON_RAIN_1HOUR, Double.NaN);
|
||||
}
|
||||
|
||||
public boolean hasRain() {
|
||||
return (this.rain1h != Float.NaN);
|
||||
}
|
||||
|
||||
public float getRain() {
|
||||
return this.rain1h;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses sys data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Sys {
|
||||
|
||||
private final String JSON_SYS_TYPE = "type";
|
||||
private final String JSON_SYS_ID = "id";
|
||||
private final String JSON_SYS_MESSAGE = "message";
|
||||
private final String JSON_SYS_COUNTRY_CODE = "country";
|
||||
private final String JSON_SYS_SUNRISE = "sunrise";
|
||||
private final String JSON_SYS_SUNSET = "sunset";
|
||||
|
||||
private final int type;
|
||||
private final int id;
|
||||
private final double message;
|
||||
private final String countryCode;
|
||||
private final Date sunrise;
|
||||
private final Date sunset;
|
||||
|
||||
Sys() {
|
||||
this.type = Integer.MIN_VALUE;
|
||||
this.id = Integer.MIN_VALUE;
|
||||
this.message = Double.NaN;
|
||||
this.countryCode = null;
|
||||
this.sunrise = null;
|
||||
this.sunset = null;
|
||||
}
|
||||
|
||||
Sys(JSONObject jsonObj) {
|
||||
this.type = jsonObj.optInt(this.JSON_SYS_TYPE, Integer.MIN_VALUE);
|
||||
this.id = jsonObj.optInt(this.JSON_SYS_ID, Integer.MIN_VALUE);
|
||||
this.message = jsonObj.optDouble(this.JSON_SYS_MESSAGE, Double.NaN);
|
||||
this.countryCode = jsonObj.optString(this.JSON_SYS_COUNTRY_CODE, null);
|
||||
|
||||
long sr_secs = jsonObj.optLong(this.JSON_SYS_SUNRISE, Long.MIN_VALUE);
|
||||
if (sr_secs != Long.MIN_VALUE) {
|
||||
/*
|
||||
Bugfix: Incorrect date and time
|
||||
Issue: #3 given at http://code.aksingh.net/owm-japis/issue/3/problem-with-datetime
|
||||
Incorrect: this.sunrise = new Date(sr_secs);
|
||||
Correct: this.sunrise = new Date(sr_secs * 1000);
|
||||
Reason: Date requires milliseconds but previously, seconds were provided.
|
||||
*/
|
||||
this.sunrise = new Date(sr_secs * 1000);
|
||||
} else {
|
||||
this.sunrise = null;
|
||||
}
|
||||
|
||||
long ss_secs = jsonObj.optLong(this.JSON_SYS_SUNSET, Long.MIN_VALUE);
|
||||
if (ss_secs != Long.MIN_VALUE) {
|
||||
/*
|
||||
Bugfix: Incorrect date and time
|
||||
Issue: #3 given at http://code.aksingh.net/owm-japis/issue/3/problem-with-datetime
|
||||
Incorrect: this.sunrise = new Date(ss_secs);
|
||||
Correct: this.sunrise = new Date(ss_secs * 1000);
|
||||
Reason: Date requires milliseconds but previously, seconds were provided.
|
||||
*/
|
||||
this.sunset = new Date(ss_secs * 1000);
|
||||
} else {
|
||||
this.sunset = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasType() {
|
||||
return (this.type != Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public boolean hasId() {
|
||||
return (this.id != Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public boolean hasMessage() {
|
||||
return (this.message != Double.NaN);
|
||||
}
|
||||
|
||||
public boolean hasCountryCode() {
|
||||
return (this.countryCode != null);
|
||||
}
|
||||
|
||||
public boolean hasSunriseTime() {
|
||||
return (this.sunrise != null);
|
||||
}
|
||||
|
||||
public boolean hasSunsetTime() {
|
||||
return (this.sunset != null);
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public double getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
public String getCountryCode() {
|
||||
return this.countryCode;
|
||||
}
|
||||
|
||||
public Date getSunriseTime() {
|
||||
return this.sunrise;
|
||||
}
|
||||
|
||||
public Date getSunsetTime() {
|
||||
return this.sunset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses wind data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Wind extends AbstractWeather.Wind {
|
||||
|
||||
private final String JSON_WIND_GUST = "gust";
|
||||
|
||||
private final float gust;
|
||||
|
||||
Wind() {
|
||||
super();
|
||||
|
||||
this.gust = Float.NaN;
|
||||
}
|
||||
|
||||
Wind(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
|
||||
this.gust = (float) jsonObj.optDouble(this.JSON_WIND_GUST, Double.NaN);
|
||||
}
|
||||
|
||||
public boolean hasWindGust() {
|
||||
return (this.gust != Float.NaN);
|
||||
}
|
||||
|
||||
public float getWindGust() {
|
||||
return this.gust;
|
||||
}
|
||||
}
|
||||
}
|
318
src/main/java/net/aksingh/owmjapis/DailyForecast.java
Normal file
318
src/main/java/net/aksingh/owmjapis/DailyForecast.java
Normal file
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 Ashutosh Kumar Singh <me@aksingh.net>
|
||||
*
|
||||
* 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 net.aksingh.owmjapis;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses daily forecast data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/27
|
||||
* @see <a href="http://openweathermap.org/forecast">OWM's Weather Forecast API</a>
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
public class DailyForecast extends AbstractForecast {
|
||||
/*
|
||||
Instance variables
|
||||
*/
|
||||
private final List<Forecast> forecastList;
|
||||
|
||||
/*
|
||||
Constructors
|
||||
*/
|
||||
DailyForecast(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
|
||||
JSONArray dataArray = (jsonObj != null) ? jsonObj.optJSONArray(this.JSON_FORECAST_LIST) : new JSONArray();
|
||||
this.forecastList = (dataArray != null) ? new ArrayList<Forecast>(dataArray.length()) : Collections.EMPTY_LIST;
|
||||
if (this.forecastList != Collections.EMPTY_LIST) {
|
||||
for (int i = 0; i < dataArray.length(); i++) {
|
||||
JSONObject forecastObj = dataArray.optJSONObject(i);
|
||||
if (forecastObj != null) {
|
||||
this.forecastList.add(new Forecast(forecastObj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index Index of Forecast instance in the list.
|
||||
* @return Forecast instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Forecast getForecastInstance(int index) {
|
||||
return this.forecastList.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses forecast data (one element in the forecastList) and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*/
|
||||
public static class Forecast extends AbstractForecast.Forecast {
|
||||
/*
|
||||
JSON Keys
|
||||
*/
|
||||
public final String JSON_TEMP = "temp";
|
||||
|
||||
private final String JSON_FORECAST_PRESSURE = "pressure";
|
||||
private final String JSON_FORECAST_HUMIDITY = "humidity";
|
||||
private final String JSON_FORECAST_WIND_SPEED = "speed";
|
||||
private final String JSON_FORECAST_WIND_DEGREE = "deg";
|
||||
private final String JSON_FORECAST_CLOUDS = "clouds";
|
||||
private final String JSON_FORECAST_RAIN = "rain";
|
||||
private final String JSON_FORECAST_SNOW = "snow";
|
||||
|
||||
/*
|
||||
Instance Variables
|
||||
*/
|
||||
private final float pressure;
|
||||
private final float humidity;
|
||||
private final float windSpeed;
|
||||
private final float windDegree;
|
||||
private final float cloudsPercent;
|
||||
private final float rain;
|
||||
private final float snow;
|
||||
|
||||
private final Temperature temp;
|
||||
|
||||
/*
|
||||
Constructors
|
||||
*/
|
||||
Forecast() {
|
||||
super();
|
||||
|
||||
this.pressure = Float.NaN;
|
||||
this.humidity = Float.NaN;
|
||||
this.windSpeed = Float.NaN;
|
||||
this.windDegree = Float.NaN;
|
||||
this.cloudsPercent = Float.NaN;
|
||||
this.rain = Float.NaN;
|
||||
this.snow = Float.NaN;
|
||||
|
||||
this.temp = new Temperature();
|
||||
}
|
||||
|
||||
Forecast(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
|
||||
JSONObject jsonObjTemp = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_TEMP) : null;
|
||||
this.temp = (jsonObjTemp != null) ? new Temperature(jsonObjTemp) : new Temperature();
|
||||
|
||||
this.humidity = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_FORECAST_HUMIDITY, Double.NaN) : Float.NaN;
|
||||
this.pressure = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_FORECAST_PRESSURE, Double.NaN) : Float.NaN;
|
||||
this.windSpeed = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_FORECAST_WIND_SPEED, Double.NaN) : Float.NaN;
|
||||
this.windDegree = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_FORECAST_WIND_DEGREE, Double.NaN) : Float.NaN;
|
||||
this.cloudsPercent = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_FORECAST_CLOUDS, Double.NaN) : Float.NaN;
|
||||
this.rain = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_FORECAST_RAIN, Double.NaN) : Float.NaN;
|
||||
this.snow = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_FORECAST_SNOW, Double.NaN) : Float.NaN;
|
||||
}
|
||||
|
||||
public boolean hasHumidity() {
|
||||
return (this.humidity != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasPressure() {
|
||||
return (this.pressure != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasWindSpeed() {
|
||||
return (this.windSpeed != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasWindDegree() {
|
||||
return (this.windDegree != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasPercentageOfClouds() {
|
||||
return (this.cloudsPercent != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasRain() {
|
||||
return (this.rain != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasSnow() {
|
||||
return (this.snow != Float.NaN);
|
||||
}
|
||||
|
||||
public float getHumidity() {
|
||||
return this.humidity;
|
||||
}
|
||||
|
||||
public float getPressure() {
|
||||
return this.pressure;
|
||||
}
|
||||
|
||||
public float getWindSpeed() {
|
||||
return this.windSpeed;
|
||||
}
|
||||
|
||||
public float getWindDegree() {
|
||||
return this.windDegree;
|
||||
}
|
||||
|
||||
public float getPercentageOfClouds() {
|
||||
return this.cloudsPercent;
|
||||
}
|
||||
|
||||
public float getRain() {
|
||||
return this.rain;
|
||||
}
|
||||
|
||||
public float getSnow() {
|
||||
return this.snow;
|
||||
}
|
||||
|
||||
public Temperature getTemperatureInstance() {
|
||||
return this.temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses temperature data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*/
|
||||
public static class Temperature {
|
||||
public final String JSON_TEMP_DAY = "day";
|
||||
public final String JSON_TEMP_MIN = "min";
|
||||
public final String JSON_TEMP_MAX = "max";
|
||||
public final String JSON_TEMP_NIGHT = "night";
|
||||
public final String JSON_TEMP_EVENING = "eve";
|
||||
public final String JSON_TEMP_MORNING = "morn";
|
||||
|
||||
private final float dayTemp;
|
||||
private final float minTemp;
|
||||
private final float maxTemp;
|
||||
private final float nightTemp;
|
||||
private final float eveTemp;
|
||||
private final float mornTemp;
|
||||
|
||||
Temperature() {
|
||||
this.dayTemp = Float.NaN;
|
||||
this.minTemp = Float.NaN;
|
||||
this.maxTemp = Float.NaN;
|
||||
this.nightTemp = Float.NaN;
|
||||
this.eveTemp = Float.NaN;
|
||||
this.mornTemp = Float.NaN;
|
||||
}
|
||||
|
||||
Temperature(JSONObject jsonObj) {
|
||||
this.dayTemp = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_TEMP_DAY, Double.NaN) : Float.NaN;
|
||||
this.minTemp = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_TEMP_MIN, Double.NaN) : Float.NaN;
|
||||
this.maxTemp = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_TEMP_MAX, Double.NaN) : Float.NaN;
|
||||
this.nightTemp = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_TEMP_NIGHT, Double.NaN) : Float.NaN;
|
||||
this.eveTemp = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_TEMP_EVENING, Double.NaN) : Float.NaN;
|
||||
this.mornTemp = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_TEMP_MORNING, Double.NaN) : Float.NaN;
|
||||
}
|
||||
|
||||
public boolean hasDayTemperature() {
|
||||
return (this.dayTemp != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasMinimumTemperature() {
|
||||
return (this.minTemp != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasMaximumTemperature() {
|
||||
return (this.maxTemp != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasNightTemperature() {
|
||||
return (this.nightTemp != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasEveningTemperature() {
|
||||
return (this.eveTemp != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasMorningTemperature() {
|
||||
return (this.mornTemp != Float.NaN);
|
||||
}
|
||||
|
||||
public float getDayTemperature() {
|
||||
return this.dayTemp;
|
||||
}
|
||||
|
||||
public float getMinimumTemperature() {
|
||||
return this.minTemp;
|
||||
}
|
||||
|
||||
public float getMaximumTemperature() {
|
||||
return this.maxTemp;
|
||||
}
|
||||
|
||||
public float getNightTemperature() {
|
||||
return this.nightTemp;
|
||||
}
|
||||
|
||||
public float getEveningTemperature() {
|
||||
return this.eveTemp;
|
||||
}
|
||||
|
||||
public float getMorningTemperature() {
|
||||
return this.mornTemp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
376
src/main/java/net/aksingh/owmjapis/HourlyForecast.java
Normal file
376
src/main/java/net/aksingh/owmjapis/HourlyForecast.java
Normal file
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 Ashutosh Kumar Singh <me@aksingh.net>
|
||||
*
|
||||
* 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 net.aksingh.owmjapis;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses hourly forecast data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/27
|
||||
* @see <a href="http://openweathermap.org/forecast">OWM's Weather Forecast API</a>
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
public class HourlyForecast extends AbstractForecast {
|
||||
/*
|
||||
Instance variables
|
||||
*/
|
||||
private final List<Forecast> forecastList;
|
||||
|
||||
/*
|
||||
Constructor
|
||||
*/
|
||||
HourlyForecast(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
|
||||
JSONArray forecastArr = (jsonObj != null) ? jsonObj.optJSONArray(this.JSON_FORECAST_LIST) : new JSONArray();
|
||||
this.forecastList = (forecastArr != null) ? new ArrayList<Forecast>(forecastArr.length()) : Collections.EMPTY_LIST;
|
||||
if (this.forecastList != Collections.EMPTY_LIST) {
|
||||
for (int i = 0; i < forecastArr.length(); i++) {
|
||||
JSONObject forecastObj = forecastArr.optJSONObject(i);
|
||||
if (forecastObj != null) {
|
||||
this.forecastList.add(new Forecast(forecastObj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index Index of Forecast instance in the list.
|
||||
* @return Forecast instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Forecast getForecastInstance(int index) {
|
||||
return this.forecastList.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses forecast data (one element in the forecastList) and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*/
|
||||
public static class Forecast extends AbstractForecast.Forecast {
|
||||
/*
|
||||
JSON Keys
|
||||
*/
|
||||
private final String JSON_SYS = "sys";
|
||||
private final String JSON_DT_TEXT = "dt_txt";
|
||||
|
||||
/*
|
||||
Instance Variables
|
||||
*/
|
||||
private final String dateTimeText;
|
||||
|
||||
private final Clouds clouds;
|
||||
private final Main main;
|
||||
private final Sys sys;
|
||||
private final Wind wind;
|
||||
|
||||
/*
|
||||
Constructor
|
||||
*/
|
||||
Forecast(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
|
||||
this.dateTimeText = (jsonObj != null) ? jsonObj.optString(this.JSON_DT_TEXT, null) : null;
|
||||
|
||||
JSONObject jsonObjClouds = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_CLOUDS) : null;
|
||||
this.clouds = (jsonObjClouds != null) ? new Clouds(jsonObjClouds) : null;
|
||||
|
||||
JSONObject jsonObjMain = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_MAIN) : null;
|
||||
this.main = (jsonObjMain != null) ? new Main(jsonObjMain) : null;
|
||||
|
||||
JSONObject jsonObjSys = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_SYS) : null;
|
||||
this.sys = (jsonObjSys != null) ? new Sys(jsonObjSys) : null;
|
||||
|
||||
JSONObject jsonObjWind = (jsonObj != null) ? jsonObj.optJSONObject(this.JSON_WIND) : null;
|
||||
this.wind = (jsonObjWind != null) ? new Wind(jsonObjWind) : null;
|
||||
}
|
||||
|
||||
public boolean hasDateTimeText() {
|
||||
return (this.dateTimeText != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Clouds instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasCloudsInstance() {
|
||||
return (clouds != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Main instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasMainInstance() {
|
||||
return (main != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Sys instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasSysInstance() {
|
||||
return (sys != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if Wind instance is available, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean hasWindInstance() {
|
||||
return (wind != null);
|
||||
}
|
||||
|
||||
public String getDateTimeText() {
|
||||
return this.dateTimeText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Clouds instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Clouds getCloudsInstance() {
|
||||
return this.clouds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Main instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Main getMainInstance() {
|
||||
return this.main;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Sys instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Sys getSysInstance() {
|
||||
return this.sys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Wind instance if available, otherwise <code>null</code>.
|
||||
*/
|
||||
public Wind getWindInstance() {
|
||||
return this.wind;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses clouds data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Clouds extends AbstractForecast.Forecast.Clouds {
|
||||
|
||||
Clouds() {
|
||||
super();
|
||||
}
|
||||
|
||||
Clouds(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses main data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Main extends AbstractForecast.Forecast.Main {
|
||||
private final String JSON_MAIN_SEA_LEVEL = "sea_level";
|
||||
private final String JSON_MAIN_GRND_LEVEL = "grnd_level";
|
||||
private final String JSON_MAIN_TMP_KF = "temp_kf";
|
||||
|
||||
private final float seaLevel;
|
||||
private final float groundLevel;
|
||||
private final float tempKF;
|
||||
|
||||
Main() {
|
||||
super();
|
||||
|
||||
this.seaLevel = Float.NaN;
|
||||
this.groundLevel = Float.NaN;
|
||||
this.tempKF = Float.NaN;
|
||||
}
|
||||
|
||||
Main(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
|
||||
this.seaLevel = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_MAIN_SEA_LEVEL, Float.NaN) : Float.NaN;
|
||||
this.groundLevel = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_MAIN_GRND_LEVEL, Float.NaN) : Float.NaN;
|
||||
this.tempKF = (jsonObj != null) ? (float) jsonObj.optDouble(this.JSON_MAIN_TMP_KF, Float.NaN) : Float.NaN;
|
||||
}
|
||||
|
||||
public boolean hasSeaLevel() {
|
||||
return (this.seaLevel != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasGroundLevel() {
|
||||
return (this.groundLevel != Float.NaN);
|
||||
}
|
||||
|
||||
public boolean hasTempKF() {
|
||||
return (this.tempKF != Float.NaN);
|
||||
}
|
||||
|
||||
public float getSeaLevel() {
|
||||
return this.seaLevel;
|
||||
}
|
||||
|
||||
public float getGroundLevel() {
|
||||
return this.groundLevel;
|
||||
}
|
||||
|
||||
public float getTempKF() {
|
||||
return this.tempKF;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses sys data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Sys {
|
||||
private final String JSON_SYS_POD = "pod";
|
||||
private final String pod;
|
||||
|
||||
Sys() {
|
||||
this.pod = null;
|
||||
}
|
||||
|
||||
Sys(JSONObject jsonObj) {
|
||||
this.pod = (jsonObj != null) ? jsonObj.optString(this.JSON_SYS_POD, null) : null;
|
||||
}
|
||||
|
||||
public boolean hasPod() {
|
||||
return (this.pod != null && (!this.pod.equals("")));
|
||||
}
|
||||
|
||||
public String getPod() {
|
||||
return this.pod;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parses wind data and provides methods to get/access the same information.
|
||||
* This class provides <code>has</code> and <code>get</code> methods to access the information.
|
||||
* </p>
|
||||
* <p>
|
||||
* <code>has</code> methods can be used to check if the data exists, i.e., if the data was available
|
||||
* (successfully downloaded) and was parsed correctly.
|
||||
* <code>get</code> methods can be used to access the data, if the data exists, otherwise <code>get</code>
|
||||
* methods will give value as per following basis:
|
||||
* Boolean: <code>false</code>
|
||||
* Integral: Minimum value (MIN_VALUE)
|
||||
* Floating point: Not a number (NaN)
|
||||
* Others: <code>null</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014/12/26
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public static class Wind extends AbstractWeather.Wind {
|
||||
|
||||
Wind() {
|
||||
super();
|
||||
}
|
||||
|
||||
Wind(JSONObject jsonObj) {
|
||||
super(jsonObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
677
src/main/java/net/aksingh/owmjapis/OpenWeatherMap.java
Normal file
677
src/main/java/net/aksingh/owmjapis/OpenWeatherMap.java
Normal file
|
@ -0,0 +1,677 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 Ashutosh Kumar Singh <me@aksingh.net>
|
||||
*
|
||||
* 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 net.aksingh.owmjapis;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Lets you access data from OpenWeatherMap.org using its Web APIs.
|
||||
* Henceforth, it's shortened as OWM.org to ease commenting.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Sample code:</b><br>
|
||||
* <code>OpenWeatherMap.org owm = new OpenWeatherMap("your-api-key");</code><br>
|
||||
* <code>OpenWeatherMap.org owm = new OpenWeatherMap(your-units, "your-api-key");</code><br>
|
||||
* <code>OpenWeatherMap.org owm = new OpenWeatherMap(your-units, your-language, "your-api-key");</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh <me@aksingh.net>
|
||||
* @version 12/19/2014
|
||||
* @see <a href="http://openweathermap.org/">OpenWeatherMap.org</a>
|
||||
* @see <a href="http://openweathermap.org/api">OpenWeatherMap.org API</a>
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public class OpenWeatherMap {
|
||||
/*
|
||||
URLs and parameters for OWM.org
|
||||
*/
|
||||
private static final String URL_API = "http://api.openweathermap.org/data/2.5/";
|
||||
private static final String URL_CURRENT = "weather?";
|
||||
private static final String URL_HOURLY_FORECAST = "forecast?";
|
||||
private static final String URL_DAILY_FORECAST = "forecast/daily?";
|
||||
|
||||
private static final String PARAM_COUNT = "cnt=";
|
||||
private static final String PARAM_CITY_NAME = "q=";
|
||||
private static final String PARAM_CITY_ID = "id=";
|
||||
private static final String PARAM_LATITUDE = "lat=";
|
||||
private static final String PARAM_LONGITUDE = "lon=";
|
||||
private static final String PARAM_MODE = "mode=";
|
||||
private static final String PARAM_UNITS = "units=";
|
||||
private static final String PARAM_APPID = "appId=";
|
||||
private static final String PARAM_LANG = "unit=";
|
||||
|
||||
/*
|
||||
Instance Variables
|
||||
*/
|
||||
private final OWMAddress owmAddress;
|
||||
private final OWMResponse owmResponse;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param apiKey API key from OWM.org
|
||||
* @see <a href="http://openweathermap.org/appid">OWM.org API Key</a>
|
||||
*/
|
||||
public OpenWeatherMap(String apiKey) {
|
||||
this(Units.IMPERIAL, Language.ENGLISH, apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param units Any constant from Units
|
||||
* @param apiKey API key from OWM.org
|
||||
* @see net.aksingh.owmjapis.OpenWeatherMap.Units
|
||||
* @see <a href="http://openweathermap.org/appid">OWM.org API Key</a>
|
||||
*/
|
||||
public OpenWeatherMap(Units units, String apiKey) {
|
||||
this(units, Language.ENGLISH, apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param units Any constant from Units
|
||||
* @param lang Any constant from Language
|
||||
* @param apiKey API key from OWM.org
|
||||
* @see net.aksingh.owmjapis.OpenWeatherMap.Units
|
||||
* @see net.aksingh.owmjapis.OpenWeatherMap.Language
|
||||
* @see <a href="http://openweathermap.org/current#multi">OWM.org's Multilingual support</a>
|
||||
* @see <a href="http://openweathermap.org/appid">OWM.org's API Key</a>
|
||||
*/
|
||||
public OpenWeatherMap(Units units, Language lang, String apiKey) {
|
||||
this.owmAddress = new OWMAddress(units, lang, apiKey);
|
||||
this.owmResponse = new OWMResponse(owmAddress);
|
||||
}
|
||||
|
||||
/*
|
||||
Getters
|
||||
*/
|
||||
public OWMAddress getOwmAddressInstance() {
|
||||
return owmAddress;
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
return owmAddress.getAppId();
|
||||
}
|
||||
|
||||
public Units getUnits() {
|
||||
return owmAddress.getUnits();
|
||||
}
|
||||
|
||||
public String getMode() {
|
||||
return owmAddress.getMode();
|
||||
}
|
||||
|
||||
public Language getLang() {
|
||||
return owmAddress.getLang();
|
||||
}
|
||||
|
||||
/*
|
||||
Setters
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set units for getting data from OWM.org
|
||||
*
|
||||
* @param units Any constant from Units
|
||||
* @see net.aksingh.owmjapis.OpenWeatherMap.Units
|
||||
*/
|
||||
public void setUnits(Units units) {
|
||||
owmAddress.setUnits(units);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set API key for getting data from OWM.org
|
||||
*
|
||||
* @param appId API key from OWM.org
|
||||
* @see <a href="http://openweathermap.org/appid">OWM.org's API Key</a>
|
||||
*/
|
||||
public void setApiKey(String appId) {
|
||||
owmAddress.setAppId(appId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set language for getting data from OWM.org
|
||||
*
|
||||
* @param lang Any constant from Language
|
||||
* @see net.aksingh.owmjapis.OpenWeatherMap.Language
|
||||
* @see <a href="http://openweathermap.org/current#multi">OWM.org's Multilingual support</a>
|
||||
*/
|
||||
public void setLang(Language lang) {
|
||||
owmAddress.setLang(lang);
|
||||
}
|
||||
|
||||
public CurrentWeather currentWeatherByCityName(String cityName)
|
||||
throws IOException, JSONException {
|
||||
String response = owmResponse.currentWeatherByCityName(cityName);
|
||||
return this.currentWeatherFromRawResponse(response);
|
||||
}
|
||||
|
||||
public CurrentWeather currentWeatherByCityName(String cityName, String countryCode)
|
||||
throws IOException, JSONException {
|
||||
String response = owmResponse.currentWeatherByCityName(cityName, countryCode);
|
||||
return this.currentWeatherFromRawResponse(response);
|
||||
}
|
||||
|
||||
public CurrentWeather currentWeatherByCityCode(long cityCode)
|
||||
throws JSONException {
|
||||
String response = owmResponse.currentWeatherByCityCode(cityCode);
|
||||
return this.currentWeatherFromRawResponse(response);
|
||||
}
|
||||
|
||||
public CurrentWeather currentWeatherByCoordinates(float latitude, float longitude)
|
||||
throws JSONException {
|
||||
String response = owmResponse.currentWeatherByCoordinates(latitude, longitude);
|
||||
return this.currentWeatherFromRawResponse(response);
|
||||
}
|
||||
|
||||
public CurrentWeather currentWeatherFromRawResponse(String response)
|
||||
throws JSONException {
|
||||
JSONObject jsonObj = (response != null) ? new JSONObject(response) : null;
|
||||
return new CurrentWeather(jsonObj);
|
||||
}
|
||||
|
||||
public HourlyForecast hourlyForecastByCityName(String cityName)
|
||||
throws IOException, JSONException {
|
||||
String response = owmResponse.hourlyForecastByCityName(cityName);
|
||||
return this.hourlyForecastFromRawResponse(response);
|
||||
}
|
||||
|
||||
public HourlyForecast hourlyForecastByCityName(String cityName, String countryCode)
|
||||
throws IOException, JSONException {
|
||||
String response = owmResponse.hourlyForecastByCityName(cityName, countryCode);
|
||||
return this.hourlyForecastFromRawResponse(response);
|
||||
}
|
||||
|
||||
public HourlyForecast hourlyForecastByCityCode(long cityCode)
|
||||
throws JSONException {
|
||||
String response = owmResponse.hourlyForecastByCityCode(cityCode);
|
||||
return this.hourlyForecastFromRawResponse(response);
|
||||
}
|
||||
|
||||
public HourlyForecast hourlyForecastByCoordinates(float latitude, float longitude)
|
||||
throws JSONException {
|
||||
String response = owmResponse.hourlyForecastByCoordinates(latitude, longitude);
|
||||
return this.hourlyForecastFromRawResponse(response);
|
||||
}
|
||||
|
||||
public HourlyForecast hourlyForecastFromRawResponse(String response)
|
||||
throws JSONException {
|
||||
JSONObject jsonObj = (response != null) ? new JSONObject(response) : null;
|
||||
return new HourlyForecast(jsonObj);
|
||||
}
|
||||
|
||||
public DailyForecast dailyForecastByCityName(String cityName, byte count)
|
||||
throws IOException, JSONException {
|
||||
String response = owmResponse.dailyForecastByCityName(cityName, count);
|
||||
return this.dailyForecastFromRawResponse(response);
|
||||
}
|
||||
|
||||
public DailyForecast dailyForecastByCityName(String cityName, String countryCode, byte count)
|
||||
throws IOException, JSONException {
|
||||
String response = owmResponse.dailyForecastByCityName(cityName, countryCode, count);
|
||||
return this.dailyForecastFromRawResponse(response);
|
||||
}
|
||||
|
||||
public DailyForecast dailyForecastByCityCode(long cityCode, byte count)
|
||||
throws JSONException {
|
||||
String response = owmResponse.dailyForecastByCityCode(cityCode, count);
|
||||
return this.dailyForecastFromRawResponse(response);
|
||||
}
|
||||
|
||||
public DailyForecast dailyForecastByCoordinates(float latitude, float longitude, byte count)
|
||||
throws JSONException {
|
||||
String response = owmResponse.dailyForecastByCoordinates(latitude, longitude, count);
|
||||
return this.dailyForecastFromRawResponse(response);
|
||||
}
|
||||
|
||||
public DailyForecast dailyForecastFromRawResponse(String response)
|
||||
throws JSONException {
|
||||
JSONObject jsonObj = (response != null) ? new JSONObject(response) : null;
|
||||
return new DailyForecast(jsonObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Units that can be set for getting data from OWM.org
|
||||
*
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
public static enum Units {
|
||||
METRIC("metric"),
|
||||
IMPERIAL("imperial");
|
||||
|
||||
private final String unit;
|
||||
|
||||
Units(String unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Languages that can be set for getting data from OWM.org
|
||||
*
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
public static enum Language {
|
||||
ENGLISH("en"),
|
||||
RUSSIAN("ru"),
|
||||
ITALIAN("it"),
|
||||
SPANISH("es"),
|
||||
UKRAINIAN("uk"),
|
||||
GERMAN("de"),
|
||||
PORTUGUESE("pt"),
|
||||
ROMANIAN("ro"),
|
||||
POLISH("pl"),
|
||||
FINNISH("fi"),
|
||||
DUTCH("nl"),
|
||||
FRENCH("FR"),
|
||||
BULGARIAN("bg"),
|
||||
SWEDISH("sv"),
|
||||
CHINESE_TRADITIONAL("zh_tw"),
|
||||
CHINESE_SIMPLIFIED("zh"),
|
||||
TURKISH("tr"),
|
||||
CROATIAN("hr"),
|
||||
CATALAN("ca");
|
||||
|
||||
private final String lang;
|
||||
|
||||
Language(String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates addresses for accessing the information from OWM.org
|
||||
*
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
public static class OWMAddress {
|
||||
private final String MODE = "json";
|
||||
private final String ENCODING = "UTF-8";
|
||||
|
||||
private String mode;
|
||||
private Units units;
|
||||
private String appId;
|
||||
private Language lang;
|
||||
|
||||
/*
|
||||
Constructors
|
||||
*/
|
||||
private OWMAddress(String appId) {
|
||||
this(Units.IMPERIAL, Language.ENGLISH, appId);
|
||||
}
|
||||
|
||||
private OWMAddress(Units units, String appId) {
|
||||
this(units, Language.ENGLISH, appId);
|
||||
}
|
||||
|
||||
private OWMAddress(Units units, Language lang, String appId) {
|
||||
this.mode = MODE;
|
||||
this.units = units;
|
||||
this.lang = lang;
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
/*
|
||||
Getters
|
||||
*/
|
||||
private String getAppId() {
|
||||
return this.appId;
|
||||
}
|
||||
|
||||
private Units getUnits() {
|
||||
return this.units;
|
||||
}
|
||||
|
||||
private String getMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
private Language getLang() {
|
||||
return this.lang;
|
||||
}
|
||||
|
||||
/*
|
||||
Setters
|
||||
*/
|
||||
private void setUnits(Units units) {
|
||||
this.units = units;
|
||||
}
|
||||
|
||||
private void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
private void setLang(Language lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
/*
|
||||
Addresses for current weather
|
||||
*/
|
||||
public String currentWeatherByCityName(String cityName) throws UnsupportedEncodingException {
|
||||
return new StringBuilder()
|
||||
.append(URL_API).append(URL_CURRENT)
|
||||
.append(PARAM_CITY_NAME).append(URLEncoder.encode(cityName, ENCODING)).append("&")
|
||||
.append(PARAM_MODE).append(this.mode).append("&")
|
||||
.append(PARAM_UNITS).append(this.units).append("&")
|
||||
.append(PARAM_LANG).append(this.lang).append("&")
|
||||
.append(PARAM_APPID).append(this.appId)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String currentWeatherByCityName(String cityName, String countryCode) throws UnsupportedEncodingException {
|
||||
return currentWeatherByCityName(new StringBuilder()
|
||||
.append(cityName).append(",").append(countryCode)
|
||||
.toString());
|
||||
}
|
||||
|
||||
public String currentWeatherByCityCode(long cityCode) {
|
||||
return new StringBuilder()
|
||||
.append(URL_API).append(URL_CURRENT)
|
||||
.append(PARAM_CITY_ID).append(Long.toString(cityCode)).append("&")
|
||||
.append(PARAM_MODE).append(this.mode).append("&")
|
||||
.append(PARAM_UNITS).append(this.units).append("&")
|
||||
.append(PARAM_LANG).append(this.lang).append("&")
|
||||
.append(PARAM_APPID).append(this.appId)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String currentWeatherByCoordinates(float latitude, float longitude) {
|
||||
return new StringBuilder()
|
||||
.append(URL_API).append(URL_CURRENT)
|
||||
.append(PARAM_LATITUDE).append(Float.toString(latitude)).append("&")
|
||||
.append(PARAM_LONGITUDE).append(Float.toString(longitude)).append("&")
|
||||
.append(PARAM_MODE).append(this.mode).append("&")
|
||||
.append(PARAM_UNITS).append(this.units).append("&")
|
||||
.append(PARAM_APPID).append(this.appId)
|
||||
.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
Addresses for hourly forecasts
|
||||
*/
|
||||
public String hourlyForecastByCityName(String cityName) throws UnsupportedEncodingException {
|
||||
return new StringBuilder()
|
||||
.append(URL_API).append(URL_HOURLY_FORECAST)
|
||||
.append(PARAM_CITY_NAME).append(URLEncoder.encode(cityName, ENCODING)).append("&")
|
||||
.append(PARAM_MODE).append(this.mode).append("&")
|
||||
.append(PARAM_UNITS).append(this.units).append("&")
|
||||
.append(PARAM_LANG).append(this.lang).append("&")
|
||||
.append(PARAM_APPID).append(this.appId)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String hourlyForecastByCityName(String cityName, String countryCode) throws UnsupportedEncodingException {
|
||||
return hourlyForecastByCityName(new StringBuilder()
|
||||
.append(cityName).append(",").append(countryCode)
|
||||
.toString());
|
||||
}
|
||||
|
||||
public String hourlyForecastByCityCode(long cityCode) {
|
||||
return new StringBuilder()
|
||||
.append(URL_API).append(URL_HOURLY_FORECAST)
|
||||
.append(PARAM_CITY_ID).append(Long.toString(cityCode)).append("&")
|
||||
.append(PARAM_MODE).append(this.mode).append("&")
|
||||
.append(PARAM_UNITS).append(this.units).append("&")
|
||||
.append(PARAM_LANG).append(this.lang).append("&")
|
||||
.append(PARAM_APPID).append(this.appId)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String hourlyForecastByCoordinates(float latitude, float longitude) {
|
||||
return new StringBuilder()
|
||||
.append(URL_API).append(URL_HOURLY_FORECAST)
|
||||
.append(PARAM_LATITUDE).append(Float.toString(latitude)).append("&")
|
||||
.append(PARAM_LONGITUDE).append(Float.toString(longitude)).append("&")
|
||||
.append(PARAM_MODE).append(this.mode).append("&")
|
||||
.append(PARAM_UNITS).append(this.units).append("&")
|
||||
.append(PARAM_LANG).append(this.lang).append("&")
|
||||
.append(PARAM_APPID).append(this.appId)
|
||||
.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
Addresses for daily forecasts
|
||||
*/
|
||||
public String dailyForecastByCityName(String cityName, byte count) throws UnsupportedEncodingException {
|
||||
return new StringBuilder()
|
||||
.append(URL_API).append(URL_DAILY_FORECAST)
|
||||
.append(PARAM_CITY_NAME).append(URLEncoder.encode(cityName, ENCODING)).append("&")
|
||||
.append(PARAM_COUNT).append(Byte.toString(count)).append("&")
|
||||
.append(PARAM_MODE).append(this.mode).append("&")
|
||||
.append(PARAM_UNITS).append(this.units).append("&")
|
||||
.append(PARAM_LANG).append(this.lang).append("&")
|
||||
.append(PARAM_APPID).append(this.appId)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String dailyForecastByCityName(String cityName, String countryCode, byte count) throws UnsupportedEncodingException {
|
||||
return dailyForecastByCityName(new StringBuilder()
|
||||
.append(cityName).append(",").append(countryCode)
|
||||
.toString(), count);
|
||||
}
|
||||
|
||||
public String dailyForecastByCityCode(long cityCode, byte count) {
|
||||
return new StringBuilder()
|
||||
.append(URL_API).append(URL_DAILY_FORECAST)
|
||||
.append(PARAM_CITY_ID).append(Long.toString(cityCode)).append("&")
|
||||
.append(PARAM_COUNT).append(Byte.toString(count)).append("&")
|
||||
.append(PARAM_MODE).append(this.mode).append("&")
|
||||
.append(PARAM_UNITS).append(this.units).append("&")
|
||||
.append(PARAM_LANG).append(this.lang).append("&")
|
||||
.append(PARAM_APPID).append(this.appId)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String dailyForecastByCoordinates(float latitude, float longitude, byte count) {
|
||||
return new StringBuilder()
|
||||
.append(URL_API).append(URL_DAILY_FORECAST)
|
||||
.append(PARAM_LATITUDE).append(Float.toString(latitude)).append("&")
|
||||
.append(PARAM_LONGITUDE).append(Float.toString(longitude)).append("&")
|
||||
.append(PARAM_COUNT).append(Byte.toString(count)).append("&")
|
||||
.append(PARAM_MODE).append(this.mode).append("&")
|
||||
.append(PARAM_UNITS).append(this.units).append("&")
|
||||
.append(PARAM_LANG).append(this.lang).append("&")
|
||||
.append(PARAM_APPID).append(this.appId)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests OWM.org for data and provides back the incoming response.
|
||||
*
|
||||
* @since 2.5.0.3
|
||||
*/
|
||||
private static class OWMResponse {
|
||||
private final OWMAddress owmAddress;
|
||||
|
||||
private OWMResponse(OWMAddress owmAddress) {
|
||||
this.owmAddress = owmAddress;
|
||||
}
|
||||
|
||||
/*
|
||||
Responses for current weather
|
||||
*/
|
||||
public String currentWeatherByCityName(String cityName) throws UnsupportedEncodingException {
|
||||
String address = owmAddress.currentWeatherByCityName(cityName);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
public String currentWeatherByCityName(String cityName, String countryCode) throws UnsupportedEncodingException {
|
||||
String address = owmAddress.currentWeatherByCityName(cityName, countryCode);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
public String currentWeatherByCityCode(long cityCode) {
|
||||
String address = owmAddress.currentWeatherByCityCode(cityCode);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
public String currentWeatherByCoordinates(float latitude, float longitude) {
|
||||
String address = owmAddress.currentWeatherByCoordinates(latitude, longitude);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
/*
|
||||
Responses for daily forecasts
|
||||
*/
|
||||
public String hourlyForecastByCityName(String cityName) throws UnsupportedEncodingException {
|
||||
String address = owmAddress.hourlyForecastByCityName(cityName);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
public String hourlyForecastByCityName(String cityName, String countryCode) throws UnsupportedEncodingException {
|
||||
String address = owmAddress.hourlyForecastByCityName(cityName, countryCode);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
public String hourlyForecastByCityCode(long cityCode) {
|
||||
String address = owmAddress.hourlyForecastByCityCode(cityCode);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
public String hourlyForecastByCoordinates(float latitude, float longitude) {
|
||||
String address = owmAddress.hourlyForecastByCoordinates(latitude, longitude);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
/*
|
||||
Responses for daily forecasts
|
||||
*/
|
||||
public String dailyForecastByCityName(String cityName, byte count) throws UnsupportedEncodingException {
|
||||
String address = owmAddress.dailyForecastByCityName(cityName, count);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
public String dailyForecastByCityName(String cityName, String countryCode, byte count) throws UnsupportedEncodingException {
|
||||
String address = owmAddress.dailyForecastByCityName(cityName, countryCode, count);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
public String dailyForecastByCityCode(long cityCode, byte count) {
|
||||
String address = owmAddress.dailyForecastByCityCode(cityCode, count);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
public String dailyForecastByCoordinates(float latitude, float longitude, byte count) {
|
||||
String address = owmAddress.dailyForecastByCoordinates(latitude, longitude, count);
|
||||
return httpGET(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements HTTP's GET method
|
||||
*
|
||||
* @param requestAddress Address to be loaded
|
||||
* @return Response if successful, else <code>null</code>
|
||||
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">HTTP - (9.3) GET</a>
|
||||
*/
|
||||
private String httpGET(String requestAddress) {
|
||||
URL request;
|
||||
HttpURLConnection connection = null;
|
||||
BufferedReader reader = null;
|
||||
|
||||
String s;
|
||||
String response = null;
|
||||
|
||||
try {
|
||||
request = new URL(requestAddress);
|
||||
connection = (HttpURLConnection) request.openConnection();
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setUseCaches(false);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(false);
|
||||
connection.setRequestProperty("Accept-Encoding", "gzip");
|
||||
connection.connect();
|
||||
|
||||
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
try {
|
||||
if (connection.getRequestProperty("Accept-Encoding") != null) {
|
||||
reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(connection.getInputStream())));
|
||||
while ((s = reader.readLine()) != null) {
|
||||
response = s;
|
||||
}
|
||||
} else {
|
||||
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
while ((s = reader.readLine()) != null) {
|
||||
response = s;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // if HttpURLConnection is not okay
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
|
||||
while ((s = reader.readLine()) != null)
|
||||
response = s;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if response is bad
|
||||
System.err.println("Bad Response: " + response + "\n");
|
||||
return null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
response = null;
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
91
src/main/java/net/aksingh/owmjapis/Tools.java
Normal file
91
src/main/java/net/aksingh/owmjapis/Tools.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 Ashutosh Kumar Singh <me@aksingh.net>
|
||||
*
|
||||
* 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 net.aksingh.owmjapis;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Provides methods for conversions, etc.
|
||||
* </p>
|
||||
*
|
||||
* @author Ashutosh Kumar Singh
|
||||
* @version 2014-12-27
|
||||
* @since 2.5.0.1
|
||||
*/
|
||||
public class Tools {
|
||||
/**
|
||||
* <p>
|
||||
* Converts degree to direction.
|
||||
* </p>
|
||||
*
|
||||
* @param degree Degree of wind as received from OWM.org
|
||||
* @return Direction
|
||||
* @throws IllegalArgumentException Degree should be between 0 and 360.
|
||||
*/
|
||||
public String convertDegree2Direction(float degree)
|
||||
throws IllegalArgumentException {
|
||||
String direction;
|
||||
|
||||
// degree should be between 0 and 360
|
||||
if ((degree < 0.0f) || (degree > 360.0f)) {
|
||||
throw new IllegalArgumentException("Degree cannot be less than 0 or more than 360.");
|
||||
}
|
||||
|
||||
if (degree <= 11.25f) {
|
||||
direction = "N";
|
||||
} else if (degree <= 33.75f) {
|
||||
direction = "NNE";
|
||||
} else if (degree <= 56.25f) {
|
||||
direction = "NE";
|
||||
} else if (degree <= 78.75f) {
|
||||
direction = "ENE";
|
||||
} else if (degree <= 101.25f) {
|
||||
direction = "E";
|
||||
} else if (degree <= 123.75f) {
|
||||
direction = "ESE";
|
||||
} else if (degree <= 146.25f) {
|
||||
direction = "SE";
|
||||
} else if (degree <= 168.75f) {
|
||||
direction = "SSE";
|
||||
} else if (degree <= 191.25f) {
|
||||
direction = "S";
|
||||
} else if (degree <= 213.75f) {
|
||||
direction = "SSW";
|
||||
} else if (degree <= 236.25f) {
|
||||
direction = "SW";
|
||||
} else if (degree <= 258.75f) {
|
||||
direction = "WSW";
|
||||
} else if (degree <= 281.25f) {
|
||||
direction = "W";
|
||||
} else if (degree <= 303.75f) {
|
||||
direction = "WNW";
|
||||
} else if (degree <= 326.25f) {
|
||||
direction = "NW";
|
||||
} else if (degree <= 348.75f) {
|
||||
direction = "NNW";
|
||||
} else {
|
||||
direction = "N";
|
||||
}
|
||||
|
||||
return direction;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue