Folder.java revision a44b0eda75782a95cbf16e8d14e8080325028657
1/******************************************************************************* 2 * Copyright (C) 2012 Google Inc. 3 * Licensed to The Android Open Source Project. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 *******************************************************************************/ 17 18package com.android.mail.providers; 19 20import android.content.Context; 21import android.database.Cursor; 22import android.graphics.drawable.PaintDrawable; 23import android.net.Uri; 24import android.os.Parcel; 25import android.os.Parcelable; 26import android.text.TextUtils; 27import android.view.View; 28import android.widget.ImageView; 29 30import com.android.mail.content.CursorCreator; 31import com.android.mail.content.ObjectCursorLoader; 32import com.android.mail.providers.UIProvider.FolderType; 33import com.android.mail.utils.FolderUri; 34import com.android.mail.utils.LogTag; 35import com.android.mail.utils.LogUtils; 36import com.android.mail.utils.Utils; 37import com.google.common.annotations.VisibleForTesting; 38import com.google.common.base.Objects; 39 40import java.util.Collection; 41import java.util.Collections; 42import java.util.HashMap; 43import java.util.List; 44import java.util.regex.Pattern; 45 46/** 47 * A folder is a collection of conversations, and perhaps other folders. 48 */ 49// TODO: make most of these fields final 50public class Folder implements Parcelable, Comparable<Folder> { 51 52 @Deprecated 53 public static final String SPLITTER = "^*^"; 54 @Deprecated 55 private static final Pattern SPLITTER_REGEX = Pattern.compile("\\^\\*\\^"); 56 57 private static final String FOLDER_UNINITIALIZED = "Uninitialized!"; 58 59 // TODO: remove this once we figure out which folder is returning a "null" string as the 60 // conversation list uri 61 private static final String NULL_STRING_URI = "null"; 62 private static final String LOG_TAG = LogTag.getLogTag(); 63 64 // Try to match the order of members with the order of constants in UIProvider. 65 66 /** 67 * Unique id of this folder. 68 */ 69 public int id; 70 71 /** 72 * Persistent (across installations) id of this folder. 73 */ 74 public String persistentId; 75 76 /** 77 * The content provider URI that returns this folder for this account. 78 */ 79 public FolderUri folderUri; 80 81 /** 82 * The human visible name for this folder. 83 */ 84 public String name; 85 86 /** 87 * The possible capabilities that this folder supports. 88 */ 89 public int capabilities; 90 91 /** 92 * Whether or not this folder has children folders. 93 */ 94 public boolean hasChildren; 95 96 /** 97 * How large the synchronization window is: how many days worth of data is retained on the 98 * device. 99 */ 100 public int syncWindow; 101 102 /** 103 * The content provider URI to return the list of conversations in this 104 * folder. 105 */ 106 public Uri conversationListUri; 107 108 /** 109 * The content provider URI to return the list of child folders of this folder. 110 */ 111 public Uri childFoldersListUri; 112 113 /** 114 * The number of messages that are unseen in this folder. 115 */ 116 public int unseenCount; 117 118 /** 119 * The number of messages that are unread in this folder. 120 */ 121 public int unreadCount; 122 123 /** 124 * The total number of messages in this folder. 125 */ 126 public int totalCount; 127 128 /** 129 * The content provider URI to force a refresh of this folder. 130 */ 131 public Uri refreshUri; 132 133 /** 134 * The current sync status of the folder 135 */ 136 public int syncStatus; 137 138 /** 139 * A packed integer containing the last synced result, and the request code. The 140 * value is (requestCode << 4) | syncResult 141 * syncResult is a value from {@link UIProvider.LastSyncResult} 142 * requestCode is a value from: {@link UIProvider.SyncStatus}, 143 */ 144 public int lastSyncResult; 145 146 /** 147 * Folder type bit mask. 0 is default. 148 * @see FolderType 149 */ 150 public int type; 151 152 /** 153 * Icon for this folder; 0 implies no icon. 154 */ 155 public int iconResId; 156 157 /** 158 * Notification icon for this folder; 0 implies no icon. 159 */ 160 public int notificationIconResId; 161 162 public String bgColor; 163 public String fgColor; 164 165 public int bgColorInt; 166 public int fgColorInt; 167 168 /** 169 * The content provider URI to request additional conversations 170 */ 171 public Uri loadMoreUri; 172 173 /** 174 * The possibly empty name of this folder with full hierarchy. 175 * The expected format is: parent/folder1/folder2/folder3/folder4 176 */ 177 public String hierarchicalDesc; 178 179 /** 180 * Parent folder of this folder, or null if there is none. 181 */ 182 public Uri parent; 183 184 /** 185 * The time at which the last message was received. 186 */ 187 public long lastMessageTimestamp; 188 189 /** 190 * A string of unread senders sorted by date, so we don't have to fetch this in multiple queries 191 */ 192 public String unreadSenders; 193 194 /** An immutable, empty conversation list */ 195 public static final Collection<Folder> EMPTY = Collections.emptyList(); 196 197 public static final class Builder { 198 private int mId; 199 private String mPersistentId; 200 private Uri mUri; 201 private String mName; 202 private int mCapabilities; 203 private boolean mHasChildren; 204 private int mSyncWindow; 205 private Uri mConversationListUri; 206 private Uri mChildFoldersListUri; 207 private int mUnseenCount; 208 private int mUnreadCount; 209 private int mTotalCount; 210 private Uri mRefreshUri; 211 private int mSyncStatus; 212 private int mLastSyncResult; 213 private int mType; 214 private int mIconResId; 215 private int mNotificationIconResId; 216 private String mBgColor; 217 private String mFgColor; 218 private Uri mLoadMoreUri; 219 private String mHierarchicalDesc; 220 private Uri mParent; 221 private long mLastMessageTimestamp; 222 private String mUnreadSenders; 223 224 public Folder build() { 225 return new Folder(mId, mPersistentId, mUri, mName, mCapabilities, 226 mHasChildren, mSyncWindow, mConversationListUri, mChildFoldersListUri, 227 mUnseenCount, mUnreadCount, mTotalCount, mRefreshUri, mSyncStatus, 228 mLastSyncResult, mType, mIconResId, mNotificationIconResId, mBgColor, 229 mFgColor, mLoadMoreUri, mHierarchicalDesc, mParent, 230 mLastMessageTimestamp, mUnreadSenders); 231 } 232 233 public Builder setId(final int id) { 234 mId = id; 235 return this; 236 } 237 public Builder setPersistentId(final String persistentId) { 238 mPersistentId = persistentId; 239 return this; 240 } 241 public Builder setUri(final Uri uri) { 242 mUri = uri; 243 return this; 244 } 245 public Builder setName(final String name) { 246 mName = name; 247 return this; 248 } 249 public Builder setCapabilities(final int capabilities) { 250 mCapabilities = capabilities; 251 return this; 252 } 253 public Builder setHasChildren(final boolean hasChildren) { 254 mHasChildren = hasChildren; 255 return this; 256 } 257 public Builder setSyncWindow(final int syncWindow) { 258 mSyncWindow = syncWindow; 259 return this; 260 } 261 public Builder setConversationListUri(final Uri conversationListUri) { 262 mConversationListUri = conversationListUri; 263 return this; 264 } 265 public Builder setChildFoldersListUri(final Uri childFoldersListUri) { 266 mChildFoldersListUri = childFoldersListUri; 267 return this; 268 } 269 public Builder setUnseenCount(final int unseenCount) { 270 mUnseenCount = unseenCount; 271 return this; 272 } 273 public Builder setUnreadCount(final int unreadCount) { 274 mUnreadCount = unreadCount; 275 return this; 276 } 277 public Builder setTotalCount(final int totalCount) { 278 mTotalCount = totalCount; 279 return this; 280 } 281 public Builder setRefreshUri(final Uri refreshUri) { 282 mRefreshUri = refreshUri; 283 return this; 284 } 285 public Builder setSyncStatus(final int syncStatus) { 286 mSyncStatus = syncStatus; 287 return this; 288 } 289 public Builder setLastSyncResult(final int lastSyncResult) { 290 mLastSyncResult = lastSyncResult; 291 return this; 292 } 293 public Builder setType(final int type) { 294 mType = type; 295 return this; 296 } 297 public Builder setIconResId(final int iconResId) { 298 mIconResId = iconResId; 299 return this; 300 } 301 public Builder setNotificationIconResId(final int notificationIconResId) { 302 mNotificationIconResId = notificationIconResId; 303 return this; 304 } 305 public Builder setBgColor(final String bgColor) { 306 mBgColor = bgColor; 307 return this; 308 } 309 public Builder setFgColor(final String fgColor) { 310 mFgColor = fgColor; 311 return this; 312 } 313 public Builder setLoadMoreUri(final Uri loadMoreUri) { 314 mLoadMoreUri = loadMoreUri; 315 return this; 316 } 317 public Builder setHierarchicalDesc(final String hierarchicalDesc) { 318 mHierarchicalDesc = hierarchicalDesc; 319 return this; 320 } 321 public Builder setParent(final Uri parent) { 322 mParent = parent; 323 return this; 324 } 325 public Builder setLastMessageTimestamp(final long lastMessageTimestamp) { 326 mLastMessageTimestamp = lastMessageTimestamp; 327 return this; 328 } 329 public Builder setUnreadSenders(final String unreadSenders) { 330 mUnreadSenders = unreadSenders; 331 return this; 332 } 333 } 334 335 public Folder(int id, String persistentId, Uri uri, String name, int capabilities, 336 boolean hasChildren, int syncWindow, Uri conversationListUri, Uri childFoldersListUri, 337 int unseenCount, int unreadCount, int totalCount, Uri refreshUri, int syncStatus, 338 int lastSyncResult, int type, int iconResId, int notificationIconResId, String bgColor, 339 String fgColor, Uri loadMoreUri, String hierarchicalDesc, Uri parent, 340 final long lastMessageTimestamp, final String unreadSenders) { 341 this.id = id; 342 this.persistentId = persistentId; 343 this.folderUri = new FolderUri(uri); 344 this.name = name; 345 this.capabilities = capabilities; 346 this.hasChildren = hasChildren; 347 this.syncWindow = syncWindow; 348 this.conversationListUri = conversationListUri; 349 this.childFoldersListUri = childFoldersListUri; 350 this.unseenCount = unseenCount; 351 this.unreadCount = unreadCount; 352 this.totalCount = totalCount; 353 this.refreshUri = refreshUri; 354 this.syncStatus = syncStatus; 355 this.lastSyncResult = lastSyncResult; 356 this.type = type; 357 this.iconResId = iconResId; 358 this.notificationIconResId = notificationIconResId; 359 this.bgColor = bgColor; 360 this.fgColor = fgColor; 361 if (bgColor != null) { 362 this.bgColorInt = Integer.parseInt(bgColor); 363 } 364 if (fgColor != null) { 365 this.fgColorInt = Integer.parseInt(fgColor); 366 } 367 this.loadMoreUri = loadMoreUri; 368 this.hierarchicalDesc = hierarchicalDesc; 369 this.lastMessageTimestamp = lastMessageTimestamp; 370 this.parent = parent; 371 this.unreadSenders = unreadSenders; 372 } 373 374 public Folder(Cursor cursor) { 375 id = cursor.getInt(UIProvider.FOLDER_ID_COLUMN); 376 persistentId = cursor.getString(UIProvider.FOLDER_PERSISTENT_ID_COLUMN); 377 folderUri = 378 new FolderUri(Uri.parse(cursor.getString(UIProvider.FOLDER_URI_COLUMN))); 379 name = cursor.getString(UIProvider.FOLDER_NAME_COLUMN); 380 capabilities = cursor.getInt(UIProvider.FOLDER_CAPABILITIES_COLUMN); 381 // 1 for true, 0 for false. 382 hasChildren = cursor.getInt(UIProvider.FOLDER_HAS_CHILDREN_COLUMN) == 1; 383 syncWindow = cursor.getInt(UIProvider.FOLDER_SYNC_WINDOW_COLUMN); 384 String convList = cursor.getString(UIProvider.FOLDER_CONVERSATION_LIST_URI_COLUMN); 385 conversationListUri = !TextUtils.isEmpty(convList) ? Uri.parse(convList) : null; 386 String childList = cursor.getString(UIProvider.FOLDER_CHILD_FOLDERS_LIST_COLUMN); 387 childFoldersListUri = (hasChildren && !TextUtils.isEmpty(childList)) ? Uri.parse(childList) 388 : null; 389 unseenCount = cursor.getInt(UIProvider.FOLDER_UNSEEN_COUNT_COLUMN); 390 unreadCount = cursor.getInt(UIProvider.FOLDER_UNREAD_COUNT_COLUMN); 391 totalCount = cursor.getInt(UIProvider.FOLDER_TOTAL_COUNT_COLUMN); 392 String refresh = cursor.getString(UIProvider.FOLDER_REFRESH_URI_COLUMN); 393 refreshUri = !TextUtils.isEmpty(refresh) ? Uri.parse(refresh) : null; 394 syncStatus = cursor.getInt(UIProvider.FOLDER_SYNC_STATUS_COLUMN); 395 lastSyncResult = cursor.getInt(UIProvider.FOLDER_LAST_SYNC_RESULT_COLUMN); 396 type = cursor.getInt(UIProvider.FOLDER_TYPE_COLUMN); 397 iconResId = cursor.getInt(UIProvider.FOLDER_ICON_RES_ID_COLUMN); 398 notificationIconResId = cursor.getInt(UIProvider.FOLDER_NOTIFICATION_ICON_RES_ID_COLUMN); 399 bgColor = cursor.getString(UIProvider.FOLDER_BG_COLOR_COLUMN); 400 fgColor = cursor.getString(UIProvider.FOLDER_FG_COLOR_COLUMN); 401 if (bgColor != null) { 402 bgColorInt = Integer.parseInt(bgColor); 403 } 404 if (fgColor != null) { 405 fgColorInt = Integer.parseInt(fgColor); 406 } 407 String loadMore = cursor.getString(UIProvider.FOLDER_LOAD_MORE_URI_COLUMN); 408 loadMoreUri = !TextUtils.isEmpty(loadMore) ? Uri.parse(loadMore) : null; 409 hierarchicalDesc = cursor.getString(UIProvider.FOLDER_HIERARCHICAL_DESC_COLUMN); 410 lastMessageTimestamp = cursor.getLong(UIProvider.FOLDER_LAST_MESSAGE_TIMESTAMP_COLUMN); 411 // A null parent URI means that this is a top-level folder. 412 final String parentString = cursor.getString(UIProvider.FOLDER_PARENT_URI_COLUMN); 413 parent = parentString == null ? Uri.EMPTY : Uri.parse(parentString); 414 final int unreadSendersColumn = 415 cursor.getColumnIndex(UIProvider.FolderColumns.UNREAD_SENDERS); 416 if (unreadSendersColumn != -1) { 417 unreadSenders = cursor.getString(unreadSendersColumn); 418 } else { 419 unreadSenders = null; 420 } 421 } 422 423 /** 424 * Public object that knows how to construct Folders given Cursors. 425 */ 426 public static final CursorCreator<Folder> FACTORY = new CursorCreator<Folder>() { 427 @Override 428 public Folder createFromCursor(Cursor c) { 429 return new Folder(c); 430 } 431 432 @Override 433 public String toString() { 434 return "Folder CursorCreator"; 435 } 436 }; 437 438 public Folder(Parcel in, ClassLoader loader) { 439 id = in.readInt(); 440 persistentId = in.readString(); 441 folderUri = new FolderUri((Uri) in.readParcelable(loader)); 442 name = in.readString(); 443 capabilities = in.readInt(); 444 // 1 for true, 0 for false. 445 hasChildren = in.readInt() == 1; 446 syncWindow = in.readInt(); 447 conversationListUri = in.readParcelable(loader); 448 childFoldersListUri = in.readParcelable(loader); 449 unseenCount = in.readInt(); 450 unreadCount = in.readInt(); 451 totalCount = in.readInt(); 452 refreshUri = in.readParcelable(loader); 453 syncStatus = in.readInt(); 454 lastSyncResult = in.readInt(); 455 type = in.readInt(); 456 iconResId = in.readInt(); 457 notificationIconResId = in.readInt(); 458 bgColor = in.readString(); 459 fgColor = in.readString(); 460 if (bgColor != null) { 461 bgColorInt = Integer.parseInt(bgColor); 462 } 463 if (fgColor != null) { 464 fgColorInt = Integer.parseInt(fgColor); 465 } 466 loadMoreUri = in.readParcelable(loader); 467 hierarchicalDesc = in.readString(); 468 parent = in.readParcelable(loader); 469 lastMessageTimestamp = in.readLong(); 470 parent = in.readParcelable(loader); 471 unreadSenders = in.readString(); 472 } 473 474 @Override 475 public void writeToParcel(Parcel dest, int flags) { 476 dest.writeInt(id); 477 dest.writeString(persistentId); 478 dest.writeParcelable(folderUri != null ? folderUri.fullUri : null, 0); 479 dest.writeString(name); 480 dest.writeInt(capabilities); 481 // 1 for true, 0 for false. 482 dest.writeInt(hasChildren ? 1 : 0); 483 dest.writeInt(syncWindow); 484 dest.writeParcelable(conversationListUri, 0); 485 dest.writeParcelable(childFoldersListUri, 0); 486 dest.writeInt(unseenCount); 487 dest.writeInt(unreadCount); 488 dest.writeInt(totalCount); 489 dest.writeParcelable(refreshUri, 0); 490 dest.writeInt(syncStatus); 491 dest.writeInt(lastSyncResult); 492 dest.writeInt(type); 493 dest.writeInt(iconResId); 494 dest.writeInt(notificationIconResId); 495 dest.writeString(bgColor); 496 dest.writeString(fgColor); 497 dest.writeParcelable(loadMoreUri, 0); 498 dest.writeString(hierarchicalDesc); 499 dest.writeParcelable(parent, 0); 500 dest.writeLong(lastMessageTimestamp); 501 dest.writeParcelable(parent, 0); 502 dest.writeString(unreadSenders); 503 } 504 505 /** 506 * Construct a folder that queries for search results. Do not call on the UI 507 * thread. 508 */ 509 public static ObjectCursorLoader<Folder> forSearchResults(Account account, String query, 510 Context context) { 511 if (account.searchUri != null) { 512 final Uri.Builder searchBuilder = account.searchUri.buildUpon(); 513 searchBuilder.appendQueryParameter(UIProvider.SearchQueryParameters.QUERY, query); 514 final Uri searchUri = searchBuilder.build(); 515 return new ObjectCursorLoader<Folder>(context, searchUri, UIProvider.FOLDERS_PROJECTION, 516 FACTORY); 517 } 518 return null; 519 } 520 521 public static HashMap<Uri, Folder> hashMapForFolders(List<Folder> rawFolders) { 522 final HashMap<Uri, Folder> folders = new HashMap<Uri, Folder>(); 523 for (Folder f : rawFolders) { 524 folders.put(f.folderUri.getComparisonUri(), f); 525 } 526 return folders; 527 } 528 529 /** 530 * Constructor that leaves everything uninitialized. 531 */ 532 private Folder() { 533 name = FOLDER_UNINITIALIZED; 534 } 535 536 /** 537 * Creates a new instance of a folder object that is <b>not</b> initialized. The caller is 538 * expected to fill in the details. Used only for testing. 539 * @return a new instance of an unsafe folder. 540 */ 541 @VisibleForTesting 542 public static Folder newUnsafeInstance() { 543 return new Folder(); 544 } 545 546 public static final ClassLoaderCreator<Folder> CREATOR = new ClassLoaderCreator<Folder>() { 547 @Override 548 public Folder createFromParcel(Parcel source) { 549 return new Folder(source, null); 550 } 551 552 @Override 553 public Folder createFromParcel(Parcel source, ClassLoader loader) { 554 return new Folder(source, loader); 555 } 556 557 @Override 558 public Folder[] newArray(int size) { 559 return new Folder[size]; 560 } 561 }; 562 563 @Override 564 public int describeContents() { 565 // Return a sort of version number for this parcelable folder. Starting with zero. 566 return 0; 567 } 568 569 @Override 570 public boolean equals(Object o) { 571 if (o == null || !(o instanceof Folder)) { 572 return false; 573 } 574 return Objects.equal(folderUri, ((Folder) o).folderUri); 575 } 576 577 @Override 578 public int hashCode() { 579 return folderUri == null ? 0 : folderUri.hashCode(); 580 } 581 582 @Override 583 public String toString() { 584 // log extra info at DEBUG level or finer 585 final StringBuilder sb = new StringBuilder(super.toString()); 586 sb.append("{id="); 587 sb.append(id); 588 if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) { 589 sb.append(", uri="); 590 sb.append(folderUri); 591 sb.append(", name="); 592 sb.append(name); 593 sb.append(", count="); 594 sb.append(totalCount); 595 } 596 sb.append("}"); 597 return sb.toString(); 598 } 599 600 @Override 601 public int compareTo(Folder other) { 602 return name.compareToIgnoreCase(other.name); 603 } 604 605 /** 606 * Returns a boolean indicating whether network activity (sync) is occuring for this folder. 607 */ 608 public boolean isSyncInProgress() { 609 return UIProvider.SyncStatus.isSyncInProgress(syncStatus); 610 } 611 612 public boolean supportsCapability(int capability) { 613 return (capabilities & capability) != 0; 614 } 615 616 // Show black text on a transparent swatch for system folders, effectively hiding the 617 // swatch (see bug 2431925). 618 public static void setFolderBlockColor(Folder folder, View colorBlock) { 619 if (colorBlock == null) { 620 return; 621 } 622 boolean showBg = 623 !TextUtils.isEmpty(folder.bgColor) && (folder.type & FolderType.INBOX_SECTION) == 0; 624 final int backgroundColor = showBg ? Integer.parseInt(folder.bgColor) : 0; 625 if (backgroundColor == Utils.getDefaultFolderBackgroundColor(colorBlock.getContext())) { 626 showBg = false; 627 } 628 if (!showBg) { 629 colorBlock.setBackgroundDrawable(null); 630 colorBlock.setVisibility(View.GONE); 631 } else { 632 PaintDrawable paintDrawable = new PaintDrawable(); 633 paintDrawable.getPaint().setColor(backgroundColor); 634 colorBlock.setBackgroundDrawable(paintDrawable); 635 colorBlock.setVisibility(View.VISIBLE); 636 } 637 } 638 639 public static void setIcon(Folder folder, ImageView iconView) { 640 if (iconView == null) { 641 return; 642 } 643 final int icon = folder.iconResId; 644 if (icon > 0) { 645 iconView.setImageResource(icon); 646 iconView.setVisibility(View.VISIBLE); 647 } else { 648 iconView.setVisibility(View.GONE); 649 } 650 } 651 652 /** 653 * Return if the type of the folder matches a provider defined folder. 654 */ 655 public boolean isProviderFolder() { 656 return !isType(UIProvider.FolderType.DEFAULT); 657 } 658 659 public int getBackgroundColor(int defaultColor) { 660 return bgColor != null ? bgColorInt : defaultColor; 661 } 662 663 public int getForegroundColor(int defaultColor) { 664 return fgColor != null ? fgColorInt : defaultColor; 665 } 666 667 /** 668 * Get just the uri's from an arraylist of folders. 669 */ 670 public static String[] getUriArray(List<Folder> folders) { 671 if (folders == null || folders.size() == 0) { 672 return new String[0]; 673 } 674 final String[] folderUris = new String[folders.size()]; 675 int i = 0; 676 for (Folder folder : folders) { 677 folderUris[i] = folder.folderUri.toString(); 678 i++; 679 } 680 return folderUris; 681 } 682 683 /** 684 * Returns a boolean indicating whether this Folder object has been initialized 685 */ 686 public boolean isInitialized() { 687 return !name.equals(FOLDER_UNINITIALIZED) && conversationListUri != null && 688 !NULL_STRING_URI.equals(conversationListUri.toString()); 689 } 690 691 public boolean isType(final int folderType) { 692 return isType(type, folderType); 693 } 694 695 /** 696 * Checks if <code>typeMask</code> is of the specified {@link FolderType} 697 * 698 * @return <code>true</code> if the mask contains the specified 699 * {@link FolderType}, <code>false</code> otherwise 700 */ 701 public static boolean isType(final int typeMask, final int folderType) { 702 return (typeMask & folderType) != 0; 703 } 704 705 /** 706 * Returns {@code true} if this folder is an inbox folder. 707 */ 708 public boolean isInbox() { 709 return isType(FolderType.INBOX); 710 } 711 712 /** 713 * Returns {@code true} if this folder is a search folder. 714 */ 715 public boolean isSearch() { 716 return isType(FolderType.SEARCH); 717 } 718 719 /** 720 * Returns {@code true} if this folder is the spam folder. 721 */ 722 public boolean isSpam() { 723 return isType(FolderType.SPAM); 724 } 725 726 /** 727 * Return if this is the trash folder. 728 */ 729 public boolean isTrash() { 730 return isType(FolderType.TRASH); 731 } 732 733 /** 734 * Return if this is a draft folder. 735 */ 736 public boolean isDraft() { 737 return isType(FolderType.DRAFT); 738 } 739 740 /** 741 * Whether this folder supports only showing important messages. 742 */ 743 public boolean isImportantOnly() { 744 return supportsCapability( 745 UIProvider.FolderCapabilities.ONLY_IMPORTANT); 746 } 747 748 /** 749 * Whether this is the special folder just used to display all mail for an account. 750 */ 751 public boolean isViewAll() { 752 return isType(FolderType.ALL_MAIL); 753 } 754 755 /** 756 * @return a non-user facing English string describing this folder's type 757 */ 758 public String getTypeDescription() { 759 final String desc; 760 if (isType(FolderType.INBOX_SECTION)) { 761 desc = "inbox_section:" + persistentId; 762 } else if (isInbox()) { 763 desc = "inbox:" + persistentId; 764 } else if (isDraft()) { 765 desc = "draft"; 766 } else if (isImportantOnly()) { 767 desc = "important"; 768 } else if (isType(FolderType.OUTBOX)) { 769 desc = "outbox"; 770 } else if (isType(FolderType.SENT)) { 771 desc = "sent"; 772 } else if (isType(FolderType.SPAM)) { 773 desc = "spam"; 774 } else if (isType(FolderType.STARRED)) { 775 desc = "starred"; 776 } else if (isTrash()) { 777 desc = "trash"; 778 } else if (isType(FolderType.UNREAD)) { 779 desc = "unread"; 780 } else if (isType(FolderType.SEARCH)) { 781 desc = "search"; 782 } else if (isViewAll()) { 783 desc = "all_mail"; 784 } else if (isProviderFolder()) { 785 desc = "other:" + persistentId; 786 } else { 787 desc = "user_folder"; 788 } 789 return desc; 790 } 791 792 /** 793 * True if the previous sync was successful, false otherwise. 794 * @return 795 */ 796 public final boolean wasSyncSuccessful() { 797 return ((lastSyncResult & 0x0f) == UIProvider.LastSyncResult.SUCCESS); 798 } 799 800 /** 801 * Returns true if unread count should be suppressed for this folder. This is done for folders 802 * where the unread count is meaningless: trash or drafts, for instance. 803 * @return true if unread count should be suppressed for this object. 804 */ 805 public final boolean isUnreadCountHidden() { 806 return (isDraft() || isTrash() || isType(FolderType.OUTBOX)); 807 } 808 809 /** 810 * This method is only used for parsing folders out of legacy intent extras, and only the 811 * folderUri and conversationListUri fields are actually read before the object is discarded. 812 * TODO: replace this with a parsing function that just directly returns those values 813 * @param inString UR8 or earlier EXTRA_FOLDER intent extra string 814 * @return Constructed folder object 815 */ 816 @Deprecated 817 public static Folder fromString(String inString) { 818 if (TextUtils.isEmpty(inString)) { 819 return null; 820 } 821 final Folder f = new Folder(); 822 int indexOf = inString.indexOf(SPLITTER); 823 int id = -1; 824 if (indexOf != -1) { 825 id = Integer.valueOf(inString.substring(0, indexOf)); 826 } else { 827 // If no separator was found, we can't parse this folder and the 828 // TextUtils.split call would also fail. Return null. 829 return null; 830 } 831 final String[] split = TextUtils.split(inString, SPLITTER_REGEX); 832 if (split.length < 20) { 833 LogUtils.e(LOG_TAG, "split.length %d", split.length); 834 return null; 835 } 836 f.id = id; 837 int index = 1; 838 f.folderUri = new FolderUri(Folder.getValidUri(split[index++])); 839 f.name = split[index++]; 840 f.hasChildren = Integer.parseInt(split[index++]) != 0; 841 f.capabilities = Integer.parseInt(split[index++]); 842 f.syncWindow = Integer.parseInt(split[index++]); 843 f.conversationListUri = getValidUri(split[index++]); 844 f.childFoldersListUri = getValidUri(split[index++]); 845 f.unreadCount = Integer.parseInt(split[index++]); 846 f.totalCount = Integer.parseInt(split[index++]); 847 f.refreshUri = getValidUri(split[index++]); 848 f.syncStatus = Integer.parseInt(split[index++]); 849 f.lastSyncResult = Integer.parseInt(split[index++]); 850 f.type = Integer.parseInt(split[index++]); 851 f.iconResId = Integer.parseInt(split[index++]); 852 f.bgColor = split[index++]; 853 f.fgColor = split[index++]; 854 if (f.bgColor != null) { 855 f.bgColorInt = Integer.parseInt(f.bgColor); 856 } 857 if (f.fgColor != null) { 858 f.fgColorInt = Integer.parseInt(f.fgColor); 859 } 860 f.loadMoreUri = getValidUri(split[index++]); 861 f.hierarchicalDesc = split[index++]; 862 f.parent = Folder.getValidUri(split[index++]); 863 f.unreadSenders = null; 864 865 return f; 866 } 867 868 private static Uri getValidUri(String uri) { 869 if (TextUtils.isEmpty(uri)) { 870 return null; 871 } 872 return Uri.parse(uri); 873 } 874} 875