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