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