replicant-vendor_cmsdk/sdk/src/java/cyanogenmod/weather/WeatherInfo.java

524 lines
17 KiB
Java
Executable File

/*
* Copyright (C) 2016 The CyanongenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cyanogenmod.weather;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import cyanogenmod.os.Build;
import cyanogenmod.os.Concierge;
import cyanogenmod.os.Concierge.ParcelInfo;
import cyanogenmod.providers.WeatherContract;
import cyanogenmod.weatherservice.ServiceRequest;
import cyanogenmod.weatherservice.ServiceRequestResult;
import java.util.ArrayList;
/**
* This class represents the weather information that a
* {@link cyanogenmod.weatherservice.WeatherProviderService} will use to update the weather content
* provider. A weather provider service will be called by the system to process an update
* request at any time. If the service successfully processes the request, then the weather provider
* service is responsible of calling
* {@link ServiceRequest#complete(ServiceRequestResult)} to notify the
* system that the request was completed and that the weather content provider should be updated
* with the supplied weather information.
*/
public final class WeatherInfo implements Parcelable {
private String mCityId;
private String mCity;
private int mConditionCode;
private float mTemperature;
private int mTempUnit;
private float mHumidity;
private float mWindSpeed;
private float mWindDirection;
private int mWindSpeedUnit;
private long mTimestamp;
private ArrayList<DayForecast> mForecastList;
int mKey;
private WeatherInfo() {}
public static class Builder {
private String mCityId;
private String mCity;
private int mConditionCode;
private float mTemperature;
private int mTempUnit;
private float mHumidity;
private float mWindSpeed;
private float mWindDirection;
private int mWindSpeedUnit;
private long mTimestamp;
private ArrayList<DayForecast> mForecastList;
public Builder(long timestamp) {
mTimestamp = timestamp;
}
public Builder setCity(String cityId, @NonNull String cityName) {
if (cityName == null || cityId == null) {
throw new IllegalArgumentException("City name and id can't be null");
}
mCityId = cityId;
mCity = cityName;
return this;
}
public Builder setTemperature(float temperature, int tempUnit) {
if (!isValidTempUnit(tempUnit)) {
throw new IllegalArgumentException("Invalid temperature unit");
}
if (Float.isNaN(temperature)) {
throw new IllegalArgumentException("Invalid temperature value");
}
mTemperature = temperature;
mTempUnit = tempUnit;
return this;
}
public Builder setHumidity(float humidity) {
if (Float.isNaN(humidity)) {
throw new IllegalArgumentException("Invalid humidity value");
}
mHumidity = humidity;
return this;
}
public Builder setWind(float windSpeed, float windDirection, int windSpeedUnit) {
if (Float.isNaN(windSpeed)) {
throw new IllegalArgumentException("Invalid wind speed value");
}
if (Float.isNaN(windDirection)) {
throw new IllegalArgumentException("Invalid wind direction value");
}
if (!isValidWindSpeedUnit(windSpeedUnit)) {
throw new IllegalArgumentException("Invalid speed unit");
}
mWindSpeed = windSpeed;
mWindSpeedUnit = windSpeedUnit;
mWindDirection = windDirection;
return this;
}
public Builder setWeatherCondition(int conditionCode) {
if (!isValidWeatherCode(conditionCode)) {
throw new IllegalArgumentException("Invalid weather condition code");
}
mConditionCode = conditionCode;
return this;
}
public Builder setForecast(@NonNull ArrayList<DayForecast> forecasts) {
if (forecasts == null) {
throw new IllegalArgumentException("Forecast list can't be null");
}
mForecastList = forecasts;
return this;
}
public WeatherInfo build() {
WeatherInfo info = new WeatherInfo();
info.mCityId = this.mCityId;
info.mCity = this.mCity;
info.mConditionCode = this.mConditionCode;
info.mTemperature = this.mTemperature;
info.mTempUnit = this.mTempUnit;
info.mHumidity = this.mHumidity;
info.mWindSpeed = this.mWindSpeed;
info.mWindDirection = this.mWindDirection;
info.mWindSpeedUnit = this.mWindSpeedUnit;
info.mTimestamp = this.mTimestamp;
info.mForecastList = this.mForecastList;
info.mKey = this.hashCode();
return info;
}
private boolean isValidTempUnit(int unit) {
switch (unit) {
case WeatherContract.WeatherColumns.TempUnit.CELSIUS:
case WeatherContract.WeatherColumns.TempUnit.FAHRENHEIT:
return true;
default:
return false;
}
}
private boolean isValidWindSpeedUnit(int unit) {
switch (unit) {
case WeatherContract.WeatherColumns.WindSpeedUnit.KPH:
case WeatherContract.WeatherColumns.WindSpeedUnit.MPH:
return true;
default:
return false;
}
}
}
private static boolean isValidWeatherCode(int code) {
if (code < WeatherContract.WeatherColumns.WeatherCode.WEATHER_CODE_MIN
|| code > WeatherContract.WeatherColumns.WeatherCode.WEATHER_CODE_MAX) {
if (code != WeatherContract.WeatherColumns.WeatherCode.NOT_AVAILABLE) {
return false;
}
}
return true;
}
/**
* @return city id
*/
public String getCityId() {
return mCityId;
}
/**
* @return city name
*/
public String getCity() {
return mCity;
}
/**
* @return An implementation specific weather condition code
*/
public int getConditionCode() {
return mConditionCode;
}
/**
* @return humidity
*/
public float getHumidity() {
return mHumidity;
}
/**
* @return time stamp when the request was processed
*/
public long getTimestamp() {
return mTimestamp;
}
/**
* @return wind direction (degrees)
*/
public float getWindDirection() {
return mWindDirection;
}
/**
* @return wind speed
*/
public float getWindSpeed() {
return mWindSpeed;
}
/**
* @return wind speed unit
*/
public int getWindSpeedUnit() {
return mWindSpeedUnit;
}
/**
* @return current temperature
*/
public float getTemperature() {
return mTemperature;
}
/**
* @return temperature unit
*/
public int getTemperatureUnit() {
return mTempUnit;
}
/**
* @return List of {@link cyanogenmod.weather.WeatherInfo.DayForecast}
*/
public ArrayList<DayForecast> getForecasts() {
return mForecastList;
}
private WeatherInfo(Parcel parcel) {
// Read parcelable version via the Concierge
ParcelInfo parcelInfo = Concierge.receiveParcel(parcel);
int parcelableVersion = parcelInfo.getParcelVersion();
if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) {
mKey = parcel.readInt();
mCityId = parcel.readString();
mCity = parcel.readString();
mConditionCode = parcel.readInt();
mTemperature = parcel.readFloat();
mTempUnit = parcel.readInt();
mHumidity = parcel.readFloat();
mWindSpeed = parcel.readFloat();
mWindDirection = parcel.readFloat();
mWindSpeedUnit = parcel.readInt();
mTimestamp = parcel.readLong();
int forecastListSize = parcel.readInt();
mForecastList = new ArrayList<>();
while (forecastListSize > 0) {
mForecastList.add(DayForecast.CREATOR.createFromParcel(parcel));
forecastListSize--;
}
}
// Complete parcel info for the concierge
parcelInfo.complete();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// Tell the concierge to prepare the parcel
ParcelInfo parcelInfo = Concierge.prepareParcel(dest);
// ==== ELDERBERRY =====
dest.writeInt(mKey);
dest.writeString(mCityId);
dest.writeString(mCity);
dest.writeInt(mConditionCode);
dest.writeFloat(mTemperature);
dest.writeInt(mTempUnit);
dest.writeFloat(mHumidity);
dest.writeFloat(mWindSpeed);
dest.writeFloat(mWindDirection);
dest.writeInt(mWindSpeedUnit);
dest.writeLong(mTimestamp);
dest.writeInt(mForecastList.size());
for (DayForecast dayForecast : mForecastList) {
dayForecast.writeToParcel(dest, 0);
}
// Complete parcel info for the concierge
parcelInfo.complete();
}
public static final Parcelable.Creator<WeatherInfo> CREATOR =
new Parcelable.Creator<WeatherInfo>() {
@Override
public WeatherInfo createFromParcel(Parcel source) {
return new WeatherInfo(source);
}
@Override
public WeatherInfo[] newArray(int size) {
return new WeatherInfo[size];
}
};
/**
* This class represents the weather forecast for a given day
*/
public static class DayForecast implements Parcelable{
float mLow;
float mHigh;
int mConditionCode;
int mKey;
private DayForecast() {}
public static class Builder {
float mLow;
float mHigh;
int mConditionCode;
public Builder() {}
public Builder setHigh(float high) {
if (Float.isNaN(high)) {
throw new IllegalArgumentException("Invalid high forecast temperature");
}
mHigh = high;
return this;
}
public Builder setLow(float low) {
if (Float.isNaN(low)) {
throw new IllegalArgumentException("Invalid low forecast temperature");
}
mLow = low;
return this;
}
public Builder setWeatherCondition(int code) {
if (!isValidWeatherCode(code)) {
throw new IllegalArgumentException("Invalid weather condition code");
}
mConditionCode = code;
return this;
}
public DayForecast build() {
DayForecast forecast = new DayForecast();
forecast.mLow = this.mLow;
forecast.mHigh = this.mHigh;
forecast.mConditionCode = this.mConditionCode;
forecast.mKey = this.hashCode();
return forecast;
}
}
/**
* @return forecasted low temperature
*/
public float getLow() {
return mLow;
}
/**
* @return not what you think. Returns the forecasted high temperature
*/
public float getHigh() {
return mHigh;
}
/**
* @return forecasted weather condition code. Implementation specific
*/
public int getConditionCode() {
return mConditionCode;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// Tell the concierge to prepare the parcel
ParcelInfo parcelInfo = Concierge.prepareParcel(dest);
// ==== ELDERBERRY =====
dest.writeInt(mKey);
dest.writeFloat(mLow);
dest.writeFloat(mHigh);
dest.writeInt(mConditionCode);
// Complete parcel info for the concierge
parcelInfo.complete();
}
public static final Parcelable.Creator<DayForecast> CREATOR =
new Parcelable.Creator<DayForecast>() {
@Override
public DayForecast createFromParcel(Parcel source) {
return new DayForecast(source);
}
@Override
public DayForecast[] newArray(int size) {
return new DayForecast[size];
}
};
private DayForecast(Parcel parcel) {
// Read parcelable version via the Concierge
ParcelInfo parcelInfo = Concierge.receiveParcel(parcel);
int parcelableVersion = parcelInfo.getParcelVersion();
if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) {
mKey = parcel.readInt();
mLow = parcel.readFloat();
mHigh = parcel.readFloat();
mConditionCode = parcel.readInt();
}
// Complete parcel info for the concierge
parcelInfo.complete();
}
@Override
public String toString() {
return new StringBuilder()
.append("{Low temp: ").append(mLow)
.append(" High temp: ").append(mHigh)
.append(" Condition code: ").append(mConditionCode)
.append("}").toString();
}
@Override
public int hashCode() {
//The hashcode of this object was stored when it was built. This is an
//immutable object but we need to preserve the hashcode since this object is parcelable
//and it's reconstructed over IPC, and clients of this object might want to store it in
//a collection that relies on this code to identify the object
return mKey;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof DayForecast) {
DayForecast forecast = (DayForecast) obj;
return (forecast.hashCode() == this.mKey);
}
return false;
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder()
.append("{CityId: ").append(mCityId)
.append(" City Name: ").append(mCity)
.append(" Condition Code: ").append(mConditionCode)
.append(" Temperature: ").append(mTemperature)
.append(" Temperature Unit: ").append(mTempUnit)
.append(" Humidity: ").append(mHumidity)
.append(" Wind speed: ").append(mWindSpeed)
.append(" Wind direction: ").append(mWindDirection)
.append(" Wind Speed Unit: ").append(mWindSpeedUnit)
.append(" Timestamp: ").append(mTimestamp).append(" Forecasts: [");
for (DayForecast dayForecast : mForecastList) {
builder.append(dayForecast.toString());
}
return builder.append("]}").toString();
}
@Override
public int hashCode() {
//The hashcode of this object was stored when it was built. This is an
//immutable object but we need to preserve the hashcode since this object is parcelable and
//it's reconstructed over IPC, and clients of this object might want to store it in a
//collection that relies on this code to identify the object
return mKey;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof WeatherInfo) {
WeatherInfo info = (WeatherInfo) obj;
return (info.hashCode() == this.mKey);
}
return false;
}
}