Settings.java revision 57899081749fac79c25362cc591705f8bd1c1f58
1/** 2 * Copyright (c) 2012, Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.mail.providers; 18 19import com.google.common.base.Objects; 20 21import com.android.mail.providers.UIProvider.AccountColumns; 22import com.android.mail.providers.UIProvider.AutoAdvance; 23import com.android.mail.providers.UIProvider.DefaultReplyBehavior; 24import com.android.mail.providers.UIProvider.MessageTextSize; 25import com.android.mail.providers.UIProvider.SnapHeaderValue; 26import com.android.mail.providers.UIProvider.Swipe; 27import com.android.mail.utils.LogTag; 28import com.android.mail.utils.LogUtils; 29import com.android.mail.utils.Utils; 30 31import android.database.Cursor; 32import android.net.Uri; 33import android.os.Parcel; 34import android.os.Parcelable; 35import android.text.TextUtils; 36 37import org.json.JSONException; 38import org.json.JSONObject; 39 40/** 41 * Model to hold Settings for an account. 42 */ 43public class Settings implements Parcelable { 44 private static final String LOG_TAG = LogTag.getLogTag(); 45 46 static final Settings EMPTY_SETTINGS = new Settings(); 47 48 // Max size for attachments (5 megs). Will be overridden by an account 49 // setting, if found. 50 private static final int DEFAULT_MAX_ATTACHMENT_SIZE = 5 * 1024 * 1024; 51 52 public static final int SWIPE_SETTING_ARCHIVE = 0; 53 public static final int SWIPE_SETTING_DELETE = 1; 54 public static final int SWIPE_SETTING_DISABLED = 2; 55 56 private static final int DEFAULT = SWIPE_SETTING_ARCHIVE; 57 58 public final String signature; 59 /** 60 * Auto advance setting for this account. 61 * Integer, one of {@link AutoAdvance#LIST}, {@link AutoAdvance#NEWER}, 62 * {@link AutoAdvance#OLDER} or {@link AutoAdvance#UNSET} 63 */ 64 public final int autoAdvance; 65 public final int messageTextSize; 66 public final int snapHeaders; 67 public final int replyBehavior; 68 public final boolean hideCheckboxes; 69 public final boolean confirmDelete; 70 public final boolean confirmArchive; 71 public final boolean confirmSend; 72 public final Uri defaultInbox; 73 /** 74 * The name of the default inbox: "Inbox" or "Priority Inbox", internationalized... 75 */ 76 public final String defaultInboxName; 77 // If you find the need for more default Inbox information: ID or capabilities, then 78 // ask viki to replace the above two members with a single JSON object representing the default 79 // folder. That should make all the information about the folder available without an 80 // explosion in the number of members. 81 82 public final boolean forceReplyFromDefault; 83 public final int maxAttachmentSize; 84 public final int swipe; 85 /** True if arrows on the priority inbox are enabled. */ 86 public final boolean priorityArrowsEnabled; 87 public final Uri setupIntentUri; 88 89 /** Cached value of hashCode */ 90 private int mHashCode; 91 92 /** Safe defaults to be used if some values are unspecified. */ 93 private static final Settings sDefault = EMPTY_SETTINGS; 94 95 private Settings() { 96 signature = ""; 97 autoAdvance = AutoAdvance.LIST; 98 messageTextSize = MessageTextSize.NORMAL; 99 snapHeaders = SnapHeaderValue.ALWAYS; 100 replyBehavior = DefaultReplyBehavior.REPLY; 101 hideCheckboxes = false; 102 confirmDelete = false; 103 confirmArchive = false; 104 confirmSend = false; 105 defaultInbox = Uri.EMPTY; 106 defaultInboxName = ""; 107 forceReplyFromDefault = false; 108 maxAttachmentSize = 0; 109 swipe = DEFAULT; 110 priorityArrowsEnabled = false; 111 setupIntentUri = Uri.EMPTY; 112 } 113 114 public Settings(Parcel inParcel) { 115 signature = inParcel.readString(); 116 autoAdvance = inParcel.readInt(); 117 messageTextSize = inParcel.readInt(); 118 snapHeaders = inParcel.readInt(); 119 replyBehavior = inParcel.readInt(); 120 hideCheckboxes = inParcel.readInt() != 0; 121 confirmDelete = inParcel.readInt() != 0; 122 confirmArchive = inParcel.readInt() != 0; 123 confirmSend = inParcel.readInt() != 0; 124 defaultInbox = Utils.getValidUri(inParcel.readString()); 125 defaultInboxName = inParcel.readString(); 126 forceReplyFromDefault = inParcel.readInt() != 0; 127 maxAttachmentSize = inParcel.readInt(); 128 swipe = inParcel.readInt(); 129 priorityArrowsEnabled = inParcel.readInt() != 0; 130 setupIntentUri = Utils.getValidUri(inParcel.readString()); 131 } 132 133 public Settings(Cursor cursor) { 134 signature = cursor.getString(UIProvider.ACCOUNT_SETTINGS_SIGNATURE_COLUMN); 135 autoAdvance = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_AUTO_ADVANCE_COLUMN); 136 messageTextSize = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_MESSAGE_TEXT_SIZE_COLUMN); 137 snapHeaders = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_SNAP_HEADERS_COLUMN); 138 replyBehavior = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_REPLY_BEHAVIOR_COLUMN); 139 hideCheckboxes = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_HIDE_CHECKBOXES_COLUMN) != 0; 140 confirmDelete = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_CONFIRM_DELETE_COLUMN) != 0; 141 confirmArchive = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_CONFIRM_ARCHIVE_COLUMN) != 0; 142 confirmSend = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_CONFIRM_SEND_COLUMN) != 0; 143 defaultInbox = Utils.getValidUri( 144 cursor.getString(UIProvider.ACCOUNT_SETTINGS_DEFAULT_INBOX_COLUMN)); 145 defaultInboxName = cursor.getString(UIProvider.ACCOUNT_SETTINGS_DEFAULT_INBOX_NAME_COLUMN); 146 forceReplyFromDefault = cursor.getInt( 147 UIProvider.ACCOUNT_SETTINGS_FORCE_REPLY_FROM_DEFAULT_COLUMN) != 0; 148 maxAttachmentSize = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_MAX_ATTACHMENT_SIZE_COLUMN); 149 swipe = cursor.getInt(UIProvider.ACCOUNT_SETTINGS_SWIPE_COLUMN); 150 priorityArrowsEnabled = 151 cursor.getInt(UIProvider.ACCOUNT_SETTINGS_PRIORITY_ARROWS_ENABLED_COLUMN) != 0; 152 setupIntentUri = Utils.getValidUri( 153 cursor.getString(UIProvider.ACCOUNT_SETTINGS_SETUP_INTENT_URI)); 154 } 155 156 private Settings(JSONObject json) { 157 signature = json.optString(AccountColumns.SettingsColumns.SIGNATURE, sDefault.signature); 158 autoAdvance = json.optInt(AccountColumns.SettingsColumns.AUTO_ADVANCE, 159 sDefault.autoAdvance); 160 messageTextSize = json.optInt(AccountColumns.SettingsColumns.MESSAGE_TEXT_SIZE, 161 sDefault.messageTextSize); 162 snapHeaders = json.optInt(AccountColumns.SettingsColumns.SNAP_HEADERS, 163 sDefault.snapHeaders); 164 replyBehavior = json.optInt(AccountColumns.SettingsColumns.REPLY_BEHAVIOR, 165 sDefault.replyBehavior); 166 hideCheckboxes = json.optBoolean(AccountColumns.SettingsColumns.HIDE_CHECKBOXES, 167 sDefault.hideCheckboxes); 168 confirmDelete = json.optBoolean(AccountColumns.SettingsColumns.CONFIRM_DELETE, 169 sDefault.confirmDelete); 170 confirmArchive = json.optBoolean(AccountColumns.SettingsColumns.CONFIRM_ARCHIVE, 171 sDefault.confirmArchive); 172 confirmSend = json.optBoolean(AccountColumns.SettingsColumns.CONFIRM_SEND, 173 sDefault.confirmSend); 174 defaultInbox = Utils.getValidUri( 175 json.optString(AccountColumns.SettingsColumns.DEFAULT_INBOX)); 176 defaultInboxName = json.optString(AccountColumns.SettingsColumns.DEFAULT_INBOX_NAME, 177 sDefault.defaultInboxName); 178 forceReplyFromDefault = 179 json.optBoolean(AccountColumns.SettingsColumns.FORCE_REPLY_FROM_DEFAULT, 180 sDefault.forceReplyFromDefault); 181 maxAttachmentSize = json.optInt(AccountColumns.SettingsColumns.MAX_ATTACHMENT_SIZE, 182 sDefault.maxAttachmentSize); 183 swipe = json.optInt(AccountColumns.SettingsColumns.SWIPE, sDefault.swipe); 184 priorityArrowsEnabled = 185 json.optBoolean(AccountColumns.SettingsColumns.PRIORITY_ARROWS_ENABLED, 186 sDefault.priorityArrowsEnabled); 187 setupIntentUri = Utils.getValidUri( 188 json.optString(AccountColumns.SettingsColumns.SETUP_INTENT_URI)); 189 } 190 191 /** 192 * Return a serialized String for these settings. 193 */ 194 public synchronized String serialize() { 195 final JSONObject json = toJSON(); 196 return json.toString(); 197 } 198 199 private static final Object getNonNull(Object candidate, Object fallback){ 200 if (candidate == null) 201 return fallback; 202 return candidate; 203 } 204 205 /** 206 * Return a JSONObject for these settings. 207 */ 208 public synchronized JSONObject toJSON() { 209 final JSONObject json = new JSONObject(); 210 try { 211 json.put(AccountColumns.SettingsColumns.SIGNATURE, 212 getNonNull(signature, sDefault.signature)); 213 json.put(AccountColumns.SettingsColumns.AUTO_ADVANCE, autoAdvance); 214 json.put(AccountColumns.SettingsColumns.MESSAGE_TEXT_SIZE, messageTextSize); 215 json.put(AccountColumns.SettingsColumns.SNAP_HEADERS, snapHeaders); 216 json.put(AccountColumns.SettingsColumns.REPLY_BEHAVIOR, replyBehavior); 217 json.put(AccountColumns.SettingsColumns.HIDE_CHECKBOXES, hideCheckboxes); 218 json.put(AccountColumns.SettingsColumns.CONFIRM_DELETE, confirmDelete); 219 json.put(AccountColumns.SettingsColumns.CONFIRM_ARCHIVE, confirmArchive); 220 json.put(AccountColumns.SettingsColumns.CONFIRM_SEND, confirmSend); 221 json.put(AccountColumns.SettingsColumns.DEFAULT_INBOX, 222 getNonNull(defaultInbox, sDefault.defaultInbox)); 223 json.put(AccountColumns.SettingsColumns.DEFAULT_INBOX_NAME, 224 getNonNull(defaultInboxName, sDefault.defaultInboxName)); 225 json.put(AccountColumns.SettingsColumns.FORCE_REPLY_FROM_DEFAULT, 226 forceReplyFromDefault); 227 json.put(AccountColumns.SettingsColumns.MAX_ATTACHMENT_SIZE, 228 maxAttachmentSize); 229 json.put(AccountColumns.SettingsColumns.SWIPE, swipe); 230 json.put(AccountColumns.SettingsColumns.PRIORITY_ARROWS_ENABLED, priorityArrowsEnabled); 231 json.put(AccountColumns.SettingsColumns.SETUP_INTENT_URI, setupIntentUri); 232 } catch (JSONException e) { 233 LogUtils.wtf(LOG_TAG, e, "Could not serialize settings"); 234 } 235 return json; 236 } 237 238 /** 239 * Create a new instance of an Settings object using a serialized instance created previously 240 * using {@link #serialize()}. This returns null if the serialized instance was invalid or does 241 * not represent a valid account object. 242 * 243 * @param serializedAccount 244 * @return 245 */ 246 public static Settings newInstance(String serializedSettings) { 247 JSONObject json = null; 248 try { 249 json = new JSONObject(serializedSettings); 250 return new Settings(json); 251 } catch (JSONException e) { 252 LogUtils.e(LOG_TAG, e, "Could not create an settings from this input: \"%s\"", 253 serializedSettings); 254 return null; 255 } 256 } 257 258 /** 259 * Create a new instance of an Settings object using a JSONObject instance created previously 260 * using {@link #toJSON()}. This returns null if the serialized instance was invalid or does 261 * not represent a valid account object. 262 * 263 * @param json 264 * @return 265 */ 266 public static Settings newInstance(JSONObject json) { 267 if (json == null) { 268 return null; 269 } 270 return new Settings(json); 271 } 272 273 @Override 274 public int describeContents() { 275 return 0; 276 } 277 278 @Override 279 public void writeToParcel(Parcel dest, int flags) { 280 dest.writeString((String) getNonNull(signature, sDefault.signature)); 281 dest.writeInt(autoAdvance); 282 dest.writeInt(messageTextSize); 283 dest.writeInt(snapHeaders); 284 dest.writeInt(replyBehavior); 285 dest.writeInt(hideCheckboxes ? 1 : 0); 286 dest.writeInt(confirmDelete ? 1 : 0); 287 dest.writeInt(confirmArchive? 1 : 0); 288 dest.writeInt(confirmSend? 1 : 0); 289 dest.writeString(((Uri) getNonNull(defaultInbox, sDefault.defaultInbox)).toString()); 290 dest.writeString((String) getNonNull(defaultInboxName, sDefault.defaultInboxName)); 291 dest.writeInt(forceReplyFromDefault ? 1 : 0); 292 dest.writeInt(maxAttachmentSize); 293 dest.writeInt(swipe); 294 dest.writeInt(priorityArrowsEnabled ? 1 : 0); 295 dest.writeString(((Uri) getNonNull(setupIntentUri, sDefault.setupIntentUri)).toString()); 296 } 297 298 /** 299 * Returns the URI of the current account's default inbox if available, otherwise 300 * returns the empty URI {@link Uri#EMPTY} 301 * @param settings a settings object, possibly null. 302 * @return a valid default Inbox URI, or {@link Uri#EMPTY} if settings are null or no default 303 * is specified. 304 */ 305 public static Uri getDefaultInboxUri(Settings settings) { 306 if (settings == null) { 307 return sDefault.defaultInbox; 308 } 309 return (Uri) getNonNull(settings.defaultInbox, sDefault.defaultInbox); 310 } 311 312 /** 313 * Return the auto advance setting for the settings provided. It is safe to pass this method 314 * a null object. It always returns a valid {@link AutoAdvance} setting. 315 * @return the auto advance setting, a constant from {@link AutoAdvance} 316 */ 317 public static int getAutoAdvanceSetting(Settings settings) { 318 // TODO(mindyp): if this isn't set, then show the dialog telling the user to set it. 319 // Remove defaulting to AutoAdvance.LIST. 320 final int autoAdvance = (settings != null) ? 321 (settings.autoAdvance == AutoAdvance.UNSET ? 322 AutoAdvance.LIST : settings.autoAdvance) 323 : AutoAdvance.LIST; 324 return autoAdvance; 325 } 326 327 /** 328 * Return the swipe setting for the settings provided. It is safe to pass this method 329 * a null object. It always returns a valid {@link Swipe} setting. 330 * @return the auto advance setting, a constant from {@link Swipe} 331 */ 332 public static int getSwipeSetting(Settings settings) { 333 return settings != null ? settings.swipe : sDefault.swipe; 334 } 335 336 @SuppressWarnings("hiding") 337 public static final Creator<Settings> CREATOR = new Creator<Settings>() { 338 @Override 339 public Settings createFromParcel(Parcel source) { 340 return new Settings(source); 341 } 342 343 @Override 344 public Settings[] newArray(int size) { 345 return new Settings[size]; 346 } 347 }; 348 349 /** 350 * Get the maximum size in bytes for attachments. 351 */ 352 public int getMaxAttachmentSize() { 353 return maxAttachmentSize <= 0 ? DEFAULT_MAX_ATTACHMENT_SIZE : maxAttachmentSize; 354 } 355 356 @Override 357 public boolean equals(final Object aThat) { 358 LogUtils.d(LOG_TAG, "Settings.equals(%s)", aThat); 359 if (this == aThat) { 360 return true; 361 } 362 if ((aThat == null) || (aThat.getClass() != this.getClass())) { 363 return false; 364 } 365 final Settings that = (Settings) aThat; 366 return (TextUtils.equals(signature, that.signature) 367 && autoAdvance == that.autoAdvance 368 && messageTextSize == that.messageTextSize 369 && replyBehavior == that.replyBehavior 370 && hideCheckboxes == that.hideCheckboxes 371 && confirmDelete == that.confirmDelete 372 && confirmArchive == that.confirmArchive 373 && confirmSend == that.confirmSend 374 && Objects.equal(defaultInbox, that.defaultInbox) 375 // Not checking default Inbox name, since is is identical to the URI check above. 376 && forceReplyFromDefault == that.forceReplyFromDefault 377 && maxAttachmentSize == that.maxAttachmentSize 378 && swipe == that.swipe 379 && priorityArrowsEnabled == that.priorityArrowsEnabled 380 && setupIntentUri == that.setupIntentUri); 381 } 382 383 @Override 384 public int hashCode() { 385 if (mHashCode == 0) { 386 mHashCode = calculateHashCode(); 387 } 388 return mHashCode; 389 } 390 391 /** 392 * Returns the hash code for this object. 393 * @return 394 */ 395 private final int calculateHashCode() { 396 return super.hashCode() 397 ^ Objects.hashCode(signature, autoAdvance, messageTextSize, replyBehavior, 398 hideCheckboxes, confirmDelete, confirmArchive, confirmSend, 399 defaultInbox, forceReplyFromDefault, maxAttachmentSize, swipe, 400 priorityArrowsEnabled, setupIntentUri); 401 } 402} 403