Account.java revision 9982fdb413d09b8e391dbc96a114987b1b87bb62
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 android.database.Cursor; 20import android.net.Uri; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.text.TextUtils; 24 25import com.android.mail.providers.UIProvider.AccountCapabilities; 26import com.android.mail.providers.UIProvider.SyncStatus; 27import com.android.mail.utils.LogTag; 28import com.android.mail.utils.LogUtils; 29import com.android.mail.utils.Utils; 30import com.google.common.base.Objects; 31import com.google.common.collect.Lists; 32 33import org.json.JSONArray; 34import org.json.JSONException; 35import org.json.JSONObject; 36 37import java.util.List; 38 39public class Account extends android.accounts.Account implements Parcelable { 40 private static final String SETTINGS_KEY = "settings"; 41 42 /** 43 * The version of the UI provider schema from which this account provider 44 * will return results. 45 */ 46 public final int providerVersion; 47 48 /** 49 * The uri to directly access the information for this account. 50 */ 51 public final Uri uri; 52 53 /** 54 * The possible capabilities that this account supports. 55 */ 56 public final int capabilities; 57 58 /** 59 * The content provider uri to return the list of top level folders for this 60 * account. 61 */ 62 public final Uri folderListUri; 63 /** 64 * The content provider uri to return the list of all folders for this 65 * account. 66 */ 67 public Uri fullFolderListUri; 68 /** 69 * The content provider uri that can be queried for search results. 70 */ 71 public final Uri searchUri; 72 73 /** 74 * The custom from addresses for this account or null if there are none. 75 */ 76 public String accountFromAddresses; 77 78 /** 79 * The content provider uri that can be used to save (insert) new draft 80 * messages for this account. NOTE: This might be better to be an update 81 * operation on the messageUri. 82 */ 83 public final Uri saveDraftUri; 84 85 /** 86 * The content provider uri that can be used to send a message for this 87 * account. 88 * NOTE: This might be better to be an update operation on the 89 * messageUri. 90 */ 91 public final Uri sendMessageUri; 92 93 /** 94 * The content provider uri that can be used to expunge message from this 95 * account. NOTE: This might be better to be an update operation on the 96 * messageUri. 97 */ 98 public final Uri expungeMessageUri; 99 100 /** 101 * The content provider uri that can be used to undo the last operation 102 * performed. 103 */ 104 public final Uri undoUri; 105 106 /** 107 * Uri for EDIT intent that will cause the settings screens for this account type to be 108 * shown. 109 */ 110 public final Uri settingsIntentUri; 111 112 /** 113 * Uri for VIEW intent that will cause the help screens for this account type to be 114 * shown. 115 */ 116 public final Uri helpIntentUri; 117 118 /** 119 * Uri for VIEW intent that will cause the send feedback screens for this account type to be 120 * shown. 121 */ 122 public final Uri sendFeedbackIntentUri; 123 124 /** 125 * Uri for VIEW intent that will cause the reauthentication screen for this account to be 126 * shown. 127 */ 128 public final Uri reauthenticationIntentUri; 129 130 /** 131 * The sync status of the account 132 */ 133 public final int syncStatus; 134 135 /** 136 * Uri for VIEW intent that will cause the compose screen for this account type to be 137 * shown. 138 */ 139 public final Uri composeIntentUri; 140 141 public final String mimeType; 142 /** 143 * URI for recent folders for this account. 144 */ 145 public final Uri recentFolderListUri; 146 /** 147 * The color used for this account in combined view (Email) 148 */ 149 public final int color; 150 /** 151 * URI for default recent folders for this account, if any. 152 */ 153 public final Uri defaultRecentFolderListUri; 154 /** 155 * Settings object for this account. 156 */ 157 public final Settings settings; 158 159 /** 160 * URI for forcing a manual sync of this account. 161 */ 162 public final Uri manualSyncUri; 163 164 /** 165 * URI for account type specific supplementary account info on outgoing links, if any. 166 */ 167 public final Uri viewIntentProxyUri; 168 169 /** 170 * Transient cache of parsed {@link #accountFromAddresses}, plus an entry for the main account 171 * address. 172 */ 173 private transient List<ReplyFromAccount> mReplyFroms; 174 175 private static final String LOG_TAG = LogTag.getLogTag(); 176 177 /** 178 * Return a serialized String for this account. 179 */ 180 public synchronized String serialize() { 181 JSONObject json = new JSONObject(); 182 try { 183 json.put(UIProvider.AccountColumns.NAME, name); 184 json.put(UIProvider.AccountColumns.TYPE, type); 185 json.put(UIProvider.AccountColumns.PROVIDER_VERSION, providerVersion); 186 json.put(UIProvider.AccountColumns.URI, uri); 187 json.put(UIProvider.AccountColumns.CAPABILITIES, capabilities); 188 json.put(UIProvider.AccountColumns.FOLDER_LIST_URI, folderListUri); 189 json.put(UIProvider.AccountColumns.FULL_FOLDER_LIST_URI, fullFolderListUri); 190 json.put(UIProvider.AccountColumns.SEARCH_URI, searchUri); 191 json.put(UIProvider.AccountColumns.ACCOUNT_FROM_ADDRESSES, accountFromAddresses); 192 json.put(UIProvider.AccountColumns.SAVE_DRAFT_URI, saveDraftUri); 193 json.put(UIProvider.AccountColumns.SEND_MAIL_URI, sendMessageUri); 194 json.put(UIProvider.AccountColumns.EXPUNGE_MESSAGE_URI, expungeMessageUri); 195 json.put(UIProvider.AccountColumns.UNDO_URI, undoUri); 196 json.put(UIProvider.AccountColumns.SETTINGS_INTENT_URI, settingsIntentUri); 197 json.put(UIProvider.AccountColumns.HELP_INTENT_URI, helpIntentUri); 198 json.put(UIProvider.AccountColumns.SEND_FEEDBACK_INTENT_URI, sendFeedbackIntentUri); 199 json.put(UIProvider.AccountColumns.REAUTHENTICATION_INTENT_URI, 200 reauthenticationIntentUri); 201 json.put(UIProvider.AccountColumns.SYNC_STATUS, syncStatus); 202 json.put(UIProvider.AccountColumns.COMPOSE_URI, composeIntentUri); 203 json.put(UIProvider.AccountColumns.MIME_TYPE, mimeType); 204 json.put(UIProvider.AccountColumns.RECENT_FOLDER_LIST_URI, recentFolderListUri); 205 json.put(UIProvider.AccountColumns.COLOR, color); 206 json.put(UIProvider.AccountColumns.DEFAULT_RECENT_FOLDER_LIST_URI, 207 defaultRecentFolderListUri); 208 json.put(UIProvider.AccountColumns.MANUAL_SYNC_URI, 209 manualSyncUri); 210 json.put(UIProvider.AccountColumns.VIEW_INTENT_PROXY_URI, 211 viewIntentProxyUri); 212 if (settings != null) { 213 json.put(SETTINGS_KEY, settings.toJSON()); 214 } 215 } catch (JSONException e) { 216 LogUtils.wtf(LOG_TAG, e, "Could not serialize account with name %s", name); 217 } 218 return json.toString(); 219 } 220 221 /** 222 * Create a new instance of an Account object using a serialized instance created previously 223 * using {@link #serialize()}. This returns null if the serialized instance was invalid or does 224 * not represent a valid account object. 225 * 226 * @param serializedAccount 227 * @return 228 */ 229 public static Account newinstance(String serializedAccount) { 230 // The heavy lifting is done by Account(name, type, serializedAccount). This method 231 // is a wrapper to check for errors and exceptions and return back a null in cases 232 // something breaks. 233 JSONObject json = null; 234 try { 235 json = new JSONObject(serializedAccount); 236 final String name = (String) json.get(UIProvider.AccountColumns.NAME); 237 final String type = (String) json.get(UIProvider.AccountColumns.TYPE); 238 return new Account(name, type, serializedAccount); 239 } catch (JSONException e) { 240 LogUtils.e(LOG_TAG, e, "Could not create an account from this input: \"%s\"", 241 serializedAccount); 242 return null; 243 } 244 } 245 246 /** 247 * Construct a new Account instance from a previously serialized string. This calls 248 * {@link android.accounts.Account#Account(String, String)} with name and type given as the 249 * first two arguments. 250 * 251 * <p> 252 * This is private. Public uses should go through the safe {@link #newinstance(String)} method. 253 * </p> 254 * @param name name of account in {@link android.accounts.Account} 255 * @param type type of account in {@link android.accounts.Account} 256 * @param jsonAccount string obtained from {@link #serialize()} on a valid account. 257 * @throws JSONException 258 */ 259 private Account(String name, String type, String jsonAccount) throws JSONException { 260 super(name, type); 261 final JSONObject json = new JSONObject(jsonAccount); 262 providerVersion = json.getInt(UIProvider.AccountColumns.PROVIDER_VERSION); 263 uri = Uri.parse(json.optString(UIProvider.AccountColumns.URI)); 264 capabilities = json.getInt(UIProvider.AccountColumns.CAPABILITIES); 265 folderListUri = Utils 266 .getValidUri(json.optString(UIProvider.AccountColumns.FOLDER_LIST_URI)); 267 fullFolderListUri = Utils.getValidUri(json 268 .optString(UIProvider.AccountColumns.FULL_FOLDER_LIST_URI)); 269 searchUri = Utils.getValidUri(json.optString(UIProvider.AccountColumns.SEARCH_URI)); 270 accountFromAddresses = UIProvider.AccountColumns.ACCOUNT_FROM_ADDRESSES; 271 saveDraftUri = Utils.getValidUri(json.optString(UIProvider.AccountColumns.SAVE_DRAFT_URI)); 272 sendMessageUri = Utils.getValidUri(json.optString(UIProvider.AccountColumns.SEND_MAIL_URI)); 273 expungeMessageUri = Utils.getValidUri(json 274 .optString(UIProvider.AccountColumns.EXPUNGE_MESSAGE_URI)); 275 undoUri = Utils.getValidUri(json.optString(UIProvider.AccountColumns.UNDO_URI)); 276 settingsIntentUri = Utils.getValidUri(json 277 .optString(UIProvider.AccountColumns.SETTINGS_INTENT_URI)); 278 helpIntentUri = Utils 279 .getValidUri(json.optString(UIProvider.AccountColumns.HELP_INTENT_URI)); 280 sendFeedbackIntentUri = Utils.getValidUri(json 281 .optString(UIProvider.AccountColumns.SEND_FEEDBACK_INTENT_URI)); 282 reauthenticationIntentUri = Utils.getValidUri( 283 json.optString(UIProvider.AccountColumns.REAUTHENTICATION_INTENT_URI)); 284 syncStatus = json.optInt(UIProvider.AccountColumns.SYNC_STATUS); 285 composeIntentUri = Utils.getValidUri(json.optString(UIProvider.AccountColumns.COMPOSE_URI)); 286 mimeType = json.optString(UIProvider.AccountColumns.MIME_TYPE); 287 recentFolderListUri = Utils.getValidUri(json 288 .optString(UIProvider.AccountColumns.RECENT_FOLDER_LIST_URI)); 289 color = json.optInt(UIProvider.AccountColumns.COLOR, 0); 290 defaultRecentFolderListUri = Utils.getValidUri(json 291 .optString(UIProvider.AccountColumns.DEFAULT_RECENT_FOLDER_LIST_URI)); 292 manualSyncUri = Utils 293 .getValidUri(json.optString(UIProvider.AccountColumns.MANUAL_SYNC_URI)); 294 viewIntentProxyUri = Utils 295 .getValidUri(json.optString(UIProvider.AccountColumns.VIEW_INTENT_PROXY_URI)); 296 297 final Settings jsonSettings = Settings.newInstance(json.optJSONObject(SETTINGS_KEY)); 298 if (jsonSettings != null) { 299 settings = jsonSettings; 300 } else { 301 LogUtils.e(LOG_TAG, new Throwable(), 302 "Unexpected null settings in Account(name, type, jsonAccount)"); 303 settings = Settings.EMPTY_SETTINGS; 304 } 305 } 306 307 public Account(Parcel in) { 308 super(in); 309 providerVersion = in.readInt(); 310 uri = in.readParcelable(null); 311 capabilities = in.readInt(); 312 folderListUri = in.readParcelable(null); 313 fullFolderListUri = in.readParcelable(null); 314 searchUri = in.readParcelable(null); 315 accountFromAddresses = in.readString(); 316 saveDraftUri = in.readParcelable(null); 317 sendMessageUri = in.readParcelable(null); 318 expungeMessageUri = in.readParcelable(null); 319 undoUri = in.readParcelable(null); 320 settingsIntentUri = in.readParcelable(null); 321 helpIntentUri = in.readParcelable(null); 322 sendFeedbackIntentUri = in.readParcelable(null); 323 reauthenticationIntentUri = in.readParcelable(null); 324 syncStatus = in.readInt(); 325 composeIntentUri = in.readParcelable(null); 326 mimeType = in.readString(); 327 recentFolderListUri = in.readParcelable(null); 328 color = in.readInt(); 329 defaultRecentFolderListUri = in.readParcelable(null); 330 manualSyncUri = in.readParcelable(null); 331 viewIntentProxyUri = in.readParcelable(null); 332 final String serializedSettings = in.readString(); 333 final Settings parcelSettings = Settings.newInstance(serializedSettings); 334 if (parcelSettings != null) { 335 settings = parcelSettings; 336 } else { 337 LogUtils.e(LOG_TAG, new Throwable(), "Unexpected null settings in Account(Parcel)"); 338 settings = Settings.EMPTY_SETTINGS; 339 } 340 } 341 342 public Account(Cursor cursor) { 343 super(cursor.getString(UIProvider.ACCOUNT_NAME_COLUMN), "unknown"); 344 accountFromAddresses = cursor.getString(UIProvider.ACCOUNT_FROM_ADDRESSES_COLUMN); 345 capabilities = cursor.getInt(UIProvider.ACCOUNT_CAPABILITIES_COLUMN); 346 providerVersion = cursor.getInt(UIProvider.ACCOUNT_PROVIDER_VERISON_COLUMN); 347 uri = Uri.parse(cursor.getString(UIProvider.ACCOUNT_URI_COLUMN)); 348 folderListUri = Uri.parse(cursor.getString(UIProvider.ACCOUNT_FOLDER_LIST_URI_COLUMN)); 349 fullFolderListUri = Utils.getValidUri(cursor 350 .getString(UIProvider.ACCOUNT_FULL_FOLDER_LIST_URI_COLUMN)); 351 searchUri = Utils.getValidUri(cursor.getString(UIProvider.ACCOUNT_SEARCH_URI_COLUMN)); 352 saveDraftUri = Utils 353 .getValidUri(cursor.getString(UIProvider.ACCOUNT_SAVE_DRAFT_URI_COLUMN)); 354 sendMessageUri = Utils.getValidUri(cursor 355 .getString(UIProvider.ACCOUNT_SEND_MESSAGE_URI_COLUMN)); 356 expungeMessageUri = Utils.getValidUri(cursor 357 .getString(UIProvider.ACCOUNT_EXPUNGE_MESSAGE_URI_COLUMN)); 358 undoUri = Utils.getValidUri(cursor.getString(UIProvider.ACCOUNT_UNDO_URI_COLUMN)); 359 settingsIntentUri = Utils.getValidUri(cursor 360 .getString(UIProvider.ACCOUNT_SETTINGS_INTENT_URI_COLUMN)); 361 helpIntentUri = Utils.getValidUri(cursor 362 .getString(UIProvider.ACCOUNT_HELP_INTENT_URI_COLUMN)); 363 sendFeedbackIntentUri = Utils.getValidUri(cursor 364 .getString(UIProvider.ACCOUNT_SEND_FEEDBACK_INTENT_URI_COLUMN)); 365 reauthenticationIntentUri = Utils.getValidUri( 366 cursor.getString(UIProvider.ACCOUNT_REAUTHENTICATION_INTENT_URI_COLUMN)); 367 syncStatus = cursor.getInt(UIProvider.ACCOUNT_SYNC_STATUS_COLUMN); 368 composeIntentUri = Utils.getValidUri(cursor 369 .getString(UIProvider.ACCOUNT_COMPOSE_INTENT_URI_COLUMN)); 370 mimeType = cursor.getString(UIProvider.ACCOUNT_MIME_TYPE_COLUMN); 371 recentFolderListUri = Utils.getValidUri(cursor 372 .getString(UIProvider.ACCOUNT_RECENT_FOLDER_LIST_URI_COLUMN)); 373 color = cursor.getInt(UIProvider.ACCOUNT_COLOR_COLUMN); 374 defaultRecentFolderListUri = Utils.getValidUri(cursor 375 .getString(UIProvider.ACCOUNT_DEFAULT_RECENT_FOLDER_LIST_URI_COLUMN)); 376 manualSyncUri = Utils.getValidUri(cursor 377 .getString(UIProvider.ACCOUNT_MANUAL_SYNC_URI_COLUMN)); 378 viewIntentProxyUri = Utils.getValidUri(cursor 379 .getString(UIProvider.ACCOUNT_VIEW_INTENT_PROXY_URI_COLUMN)); 380 settings = new Settings(cursor); 381 } 382 383 /** 384 * Returns an array of all Accounts located at this cursor. This method returns a zero length 385 * array if no account was found. This method does not close the cursor. 386 * @param cursor cursor pointing to the list of accounts 387 * @return the array of all accounts stored at this cursor. 388 */ 389 public static Account[] getAllAccounts(Cursor cursor) { 390 final int initialLength = cursor.getCount(); 391 if (initialLength <= 0 || !cursor.moveToFirst()) { 392 // Return zero length account array rather than null 393 return new Account[0]; 394 } 395 396 Account[] allAccounts = new Account[initialLength]; 397 int i = 0; 398 do { 399 allAccounts[i++] = new Account(cursor); 400 } while (cursor.moveToNext()); 401 // Ensure that the length of the array is accurate 402 assert (i == initialLength); 403 return allAccounts; 404 } 405 406 public boolean supportsCapability(int capability) { 407 return (capabilities & capability) != 0; 408 } 409 410 public boolean isAccountIntialized() { 411 return (syncStatus & SyncStatus.INITIAL_SYNC_NEEDED) != SyncStatus.INITIAL_SYNC_NEEDED; 412 } 413 414 @Override 415 public void writeToParcel(Parcel dest, int flags) { 416 super.writeToParcel(dest, flags); 417 dest.writeInt(providerVersion); 418 dest.writeParcelable(uri, 0); 419 dest.writeInt(capabilities); 420 dest.writeParcelable(folderListUri, 0); 421 dest.writeParcelable(fullFolderListUri, 0); 422 dest.writeParcelable(searchUri, 0); 423 dest.writeString(accountFromAddresses); 424 dest.writeParcelable(saveDraftUri, 0); 425 dest.writeParcelable(sendMessageUri, 0); 426 dest.writeParcelable(expungeMessageUri, 0); 427 dest.writeParcelable(undoUri, 0); 428 dest.writeParcelable(settingsIntentUri, 0); 429 dest.writeParcelable(helpIntentUri, 0); 430 dest.writeParcelable(sendFeedbackIntentUri, 0); 431 dest.writeParcelable(reauthenticationIntentUri, 0); 432 dest.writeInt(syncStatus); 433 dest.writeParcelable(composeIntentUri, 0); 434 dest.writeString(mimeType); 435 dest.writeParcelable(recentFolderListUri, 0); 436 dest.writeInt(color); 437 dest.writeParcelable(defaultRecentFolderListUri, 0); 438 dest.writeParcelable(manualSyncUri, 0); 439 dest.writeParcelable(viewIntentProxyUri, 0); 440 if (settings == null) { 441 LogUtils.e(LOG_TAG, "unexpected null settings object in writeToParcel"); 442 } 443 dest.writeString(settings != null ? settings.serialize() : ""); 444 } 445 446 @Override 447 public String toString() { 448 final StringBuilder sb = new StringBuilder(); 449 450 sb.append("name="); 451 sb.append(name); 452 sb.append(",type="); 453 sb.append(type); 454 sb.append(",accountFromAddressUri="); 455 sb.append(accountFromAddresses); 456 sb.append(",capabilities="); 457 sb.append(capabilities); 458 sb.append(",providerVersion="); 459 sb.append(providerVersion); 460 sb.append(",folderListUri="); 461 sb.append(folderListUri); 462 sb.append(",fullFolderListUri="); 463 sb.append(fullFolderListUri); 464 sb.append(",searchUri="); 465 sb.append(searchUri); 466 sb.append(",saveDraftUri="); 467 sb.append(saveDraftUri); 468 sb.append(",sendMessageUri="); 469 sb.append(sendMessageUri); 470 sb.append(",expungeMessageUri="); 471 sb.append(expungeMessageUri); 472 sb.append(",undoUri="); 473 sb.append(undoUri); 474 sb.append(",settingsIntentUri="); 475 sb.append(settingsIntentUri); 476 sb.append(",helpIntentUri="); 477 sb.append(helpIntentUri); 478 sb.append(",sendFeedbackIntentUri="); 479 sb.append(sendFeedbackIntentUri); 480 sb.append(",reauthenticationIntentUri="); 481 sb.append(reauthenticationIntentUri); 482 sb.append(",syncStatus="); 483 sb.append(syncStatus); 484 sb.append(",composeIntentUri="); 485 sb.append(composeIntentUri); 486 sb.append(",mimeType="); 487 sb.append(mimeType); 488 sb.append(",recentFoldersUri="); 489 sb.append(recentFolderListUri); 490 sb.append(",color="); 491 sb.append(Integer.toHexString(color)); 492 sb.append(",defaultRecentFoldersUri="); 493 sb.append(defaultRecentFolderListUri); 494 sb.append(",settings="); 495 sb.append(settings.serialize()); 496 497 return sb.toString(); 498 } 499 500 @Override 501 public boolean equals(Object o) { 502 if (o == this) { 503 return true; 504 } 505 506 if ((o == null) || (o.getClass() != this.getClass())) { 507 return false; 508 } 509 510 final Account other = (Account) o; 511 return TextUtils.equals(name, other.name) && TextUtils.equals(type, other.type) && 512 capabilities == other.capabilities && providerVersion == other.providerVersion && 513 Objects.equal(uri, other.uri) && 514 Objects.equal(folderListUri, other.folderListUri) && 515 Objects.equal(fullFolderListUri, other.fullFolderListUri) && 516 Objects.equal(searchUri, other.searchUri) && 517 Objects.equal(accountFromAddresses, other.accountFromAddresses) && 518 Objects.equal(saveDraftUri, other.saveDraftUri) && 519 Objects.equal(sendMessageUri, other.sendMessageUri) && 520 Objects.equal(expungeMessageUri, other.expungeMessageUri) && 521 Objects.equal(undoUri, other.undoUri) && 522 Objects.equal(settingsIntentUri, other.settingsIntentUri) && 523 Objects.equal(helpIntentUri, other.helpIntentUri) && 524 Objects.equal(sendFeedbackIntentUri, other.sendFeedbackIntentUri) && 525 Objects.equal(reauthenticationIntentUri, other.reauthenticationIntentUri) && 526 (syncStatus == other.syncStatus) && 527 Objects.equal(composeIntentUri, other.composeIntentUri) && 528 TextUtils.equals(mimeType, other.mimeType) && 529 Objects.equal(recentFolderListUri, other.recentFolderListUri) && 530 color == other.color && 531 Objects.equal(defaultRecentFolderListUri, other.defaultRecentFolderListUri) && 532 Objects.equal(viewIntentProxyUri, other.viewIntentProxyUri) && 533 Objects.equal(settings, other.settings); 534 } 535 536 @Override 537 public int hashCode() { 538 return super.hashCode() 539 ^ Objects.hashCode(name, type, capabilities, providerVersion, uri, folderListUri, 540 fullFolderListUri, searchUri, accountFromAddresses, saveDraftUri, 541 sendMessageUri, expungeMessageUri, undoUri, settingsIntentUri, 542 helpIntentUri, sendFeedbackIntentUri, reauthenticationIntentUri, syncStatus, 543 composeIntentUri, mimeType, recentFolderListUri, color, 544 defaultRecentFolderListUri, viewIntentProxyUri); 545 } 546 547 /** 548 * Returns whether two Accounts match, as determined by their base URIs. 549 * <p>For a deep object comparison, use {@link #equals(Object)}. 550 * 551 */ 552 public boolean matches(Account other) { 553 return other != null && Objects.equal(uri, other.uri); 554 } 555 556 public List<ReplyFromAccount> getReplyFroms() { 557 558 if (mReplyFroms == null) { 559 mReplyFroms = Lists.newArrayList(); 560 561 // skip if sending is unsupported 562 if (supportsCapability(AccountCapabilities.SENDING_UNAVAILABLE)) { 563 return mReplyFroms; 564 } 565 566 // add the main account address 567 mReplyFroms.add(new ReplyFromAccount(this, uri, name, name, name, 568 false /* isDefault */, false /* isCustom */)); 569 570 if (!TextUtils.isEmpty(accountFromAddresses)) { 571 try { 572 JSONArray accounts = new JSONArray(accountFromAddresses); 573 574 for (int i = 0, len = accounts.length(); i < len; i++) { 575 final ReplyFromAccount a = ReplyFromAccount.deserialize(this, 576 accounts.getJSONObject(i)); 577 if (a != null) { 578 mReplyFroms.add(a); 579 } 580 } 581 582 } catch (JSONException e) { 583 LogUtils.e(LOG_TAG, e, "Unable to parse accountFromAddresses. name=%s", name); 584 } 585 } 586 } 587 return mReplyFroms; 588 } 589 590 /** 591 * @param fromAddress a raw email address, e.g. "user@domain.com" 592 * @return if the address belongs to this Account (either as the main address or as a 593 * custom-from) 594 */ 595 public boolean ownsFromAddress(String fromAddress) { 596 for (ReplyFromAccount replyFrom : getReplyFroms()) { 597 if (TextUtils.equals(replyFrom.address, fromAddress)) { 598 return true; 599 } 600 } 601 602 return false; 603 } 604 605 @SuppressWarnings("hiding") 606 public static final Creator<Account> CREATOR = new Creator<Account>() { 607 @Override 608 public Account createFromParcel(Parcel source) { 609 return new Account(source); 610 } 611 612 @Override 613 public Account[] newArray(int size) { 614 return new Account[size]; 615 } 616 }; 617 618 /** 619 * Find the position of the given needle in the given array of accounts. 620 * @param haystack the array of accounts to search 621 * @param needle the URI of account to find 622 * @return a position between 0 and haystack.length-1 if an account is found, -1 if not found. 623 */ 624 public static int findPosition(Account[] haystack, Uri needle) { 625 if (haystack != null && haystack.length > 0 && needle != null) { 626 // Need to go through the list of current accounts, and fix the 627 // position. 628 for (int i = 0, size = haystack.length; i < size; ++i) { 629 if (haystack[i].uri.equals(needle)) { 630 LogUtils.d(LOG_TAG, "findPositionOfAccount: Found needle at position %d", i); 631 return i; 632 } 633 } 634 } 635 return -1; 636 } 637} 638