Folder.java revision 00b8b479e63bcff5270dad63156acd83c8451f18
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.content.CursorLoader;
22import android.database.Cursor;
23import android.graphics.drawable.PaintDrawable;
24import android.net.Uri;
25import android.net.Uri.Builder;
26import android.os.Parcel;
27import android.os.Parcelable;
28import android.text.TextUtils;
29import android.view.View;
30import android.widget.ImageView;
31
32import com.android.mail.utils.Utils;
33
34import com.google.common.base.Objects;
35import com.google.common.collect.ImmutableList;
36import com.google.common.collect.Maps;
37
38import java.util.ArrayList;
39import java.util.Collection;
40import java.util.Collections;
41import java.util.HashMap;
42import java.util.Map;
43import java.util.regex.Pattern;
44
45/**
46 * A folder is a collection of conversations, and perhaps other folders.
47 */
48public class Folder implements Parcelable, Comparable<Folder> {
49    /**
50     *
51     */
52    private static final String FOLDER_UNINITIALIZED = "Uninitialized!";
53
54    // TODO: remove this once we figure out which folder is returning a "null" string as the
55    // conversation list uri
56    private static final String NULL_STRING_URI = "null";
57
58    // Try to match the order of members with the order of constants in UIProvider.
59
60    /**
61     * Unique id of this folder.
62     */
63    public int id;
64
65    /**
66     * The content provider URI that returns this folder for this account.
67     */
68    public Uri uri;
69
70    /**
71     * The human visible name for this folder.
72     */
73    public String name;
74
75    /**
76     * The possible capabilities that this folder supports.
77     */
78    public int capabilities;
79
80    /**
81     * Whether or not this folder has children folders.
82     */
83    public boolean hasChildren;
84
85    /**
86     * How large the synchronization window is: how many days worth of data is retained on the
87     * device.
88     */
89    public int syncWindow;
90
91    /**
92     * The content provider URI to return the list of conversations in this
93     * folder.
94     */
95    public Uri conversationListUri;
96
97    /**
98     * The content provider URI to return the list of child folders of this folder.
99     */
100    public Uri childFoldersListUri;
101
102    /**
103     * The number of messages that are unread in this folder.
104     */
105    public int unreadCount;
106
107    /**
108     * The total number of messages in this folder.
109     */
110    public int totalCount;
111
112    /**
113     * The content provider URI to force a refresh of this folder.
114     */
115    public Uri refreshUri;
116
117    /**
118     * The current sync status of the folder
119     */
120    public int syncStatus;
121
122    /**
123     * A packed integer containing the last synced result, and the request code. The
124     * value is (requestCode << 4) | syncResult
125     * syncResult is a value from {@link UIProvider.LastSyncResult}
126     * requestCode is a value from: {@link UIProvider.SyncStatus},
127     */
128    public int lastSyncResult;
129
130    /**
131     * Folder type. 0 is default.
132     */
133    public int type;
134
135    /**
136     * Icon for this folder; 0 implies no icon.
137     */
138    public long iconResId;
139
140    public String bgColor;
141    public String fgColor;
142
143    /**
144     * The content provider URI to request additional conversations
145     */
146    public Uri loadMoreUri;
147
148    /**
149     * The possibly empty name of this folder with full hierarchy.
150     * The expected format is: parent/folder1/folder2/folder3/folder4
151     */
152    public String hierarchicalDesc;
153
154    /**
155     * Parent folder of this folder, or null if there is none. This is set as
156     * part of the execution of the application and not obtained or stored via
157     * the provider.
158     */
159    public Folder parent;
160
161    /** An immutable, empty conversation list */
162    public static final Collection<Folder> EMPTY = Collections.emptyList();
163
164    public static final String SPLITTER = "^*^";
165    private static final Pattern SPLITTER_REGEX = Pattern.compile("\\^\\*\\^");
166    public static final String FOLDERS_SPLIT = "^**^";
167    private static final Pattern FOLDERS_SPLIT_REGEX = Pattern.compile("\\^\\*\\*\\^");
168
169    public Folder(Parcel in) {
170        id = in.readInt();
171        uri = in.readParcelable(null);
172        name = in.readString();
173        capabilities = in.readInt();
174        // 1 for true, 0 for false.
175        hasChildren = in.readInt() == 1;
176        syncWindow = in.readInt();
177        conversationListUri = in.readParcelable(null);
178        childFoldersListUri = in.readParcelable(null);
179        unreadCount = in.readInt();
180        totalCount = in.readInt();
181        refreshUri = in.readParcelable(null);
182        syncStatus = in.readInt();
183        lastSyncResult = in.readInt();
184        type = in.readInt();
185        iconResId = in.readLong();
186        bgColor = in.readString();
187        fgColor = in.readString();
188        loadMoreUri = in.readParcelable(null);
189        hierarchicalDesc = in.readString();
190        parent = in.readParcelable(null);
191     }
192
193    public Folder(Cursor cursor) {
194        id = cursor.getInt(UIProvider.FOLDER_ID_COLUMN);
195        uri = Uri.parse(cursor.getString(UIProvider.FOLDER_URI_COLUMN));
196        name = cursor.getString(UIProvider.FOLDER_NAME_COLUMN);
197        capabilities = cursor.getInt(UIProvider.FOLDER_CAPABILITIES_COLUMN);
198        // 1 for true, 0 for false.
199        hasChildren = cursor.getInt(UIProvider.FOLDER_HAS_CHILDREN_COLUMN) == 1;
200        syncWindow = cursor.getInt(UIProvider.FOLDER_SYNC_WINDOW_COLUMN);
201        String convList = cursor.getString(UIProvider.FOLDER_CONVERSATION_LIST_URI_COLUMN);
202        conversationListUri = !TextUtils.isEmpty(convList) ? Uri.parse(convList) : null;
203        String childList = cursor.getString(UIProvider.FOLDER_CHILD_FOLDERS_LIST_COLUMN);
204        childFoldersListUri = (hasChildren && !TextUtils.isEmpty(childList)) ? Uri.parse(childList)
205                : null;
206        unreadCount = cursor.getInt(UIProvider.FOLDER_UNREAD_COUNT_COLUMN);
207        totalCount = cursor.getInt(UIProvider.FOLDER_TOTAL_COUNT_COLUMN);
208        String refresh = cursor.getString(UIProvider.FOLDER_REFRESH_URI_COLUMN);
209        refreshUri = !TextUtils.isEmpty(refresh) ? Uri.parse(refresh) : null;
210        syncStatus = cursor.getInt(UIProvider.FOLDER_SYNC_STATUS_COLUMN);
211        lastSyncResult = cursor.getInt(UIProvider.FOLDER_LAST_SYNC_RESULT_COLUMN);
212        type = cursor.getInt(UIProvider.FOLDER_TYPE_COLUMN);
213        iconResId = cursor.getLong(UIProvider.FOLDER_ICON_RES_ID_COLUMN);
214        bgColor = cursor.getString(UIProvider.FOLDER_BG_COLOR_COLUMN);
215        fgColor = cursor.getString(UIProvider.FOLDER_FG_COLOR_COLUMN);
216        String loadMore = cursor.getString(UIProvider.FOLDER_LOAD_MORE_URI_COLUMN);
217        loadMoreUri = !TextUtils.isEmpty(loadMore) ? Uri.parse(loadMore) : null;
218        hierarchicalDesc = cursor.getString(UIProvider.FOLDER_HIERARCHICAL_DESC_COLUMN);
219        parent = null;
220    }
221
222    @Override
223    public void writeToParcel(Parcel dest, int flags) {
224        dest.writeInt(id);
225        dest.writeParcelable(uri, 0);
226        dest.writeString(name);
227        dest.writeInt(capabilities);
228        // 1 for true, 0 for false.
229        dest.writeInt(hasChildren ? 1 : 0);
230        dest.writeInt(syncWindow);
231        dest.writeParcelable(conversationListUri, 0);
232        dest.writeParcelable(childFoldersListUri, 0);
233        dest.writeInt(unreadCount);
234        dest.writeInt(totalCount);
235        dest.writeParcelable(refreshUri, 0);
236        dest.writeInt(syncStatus);
237        dest.writeInt(lastSyncResult);
238        dest.writeInt(type);
239        dest.writeLong(iconResId);
240        dest.writeString(bgColor);
241        dest.writeString(fgColor);
242        dest.writeParcelable(loadMoreUri, 0);
243        dest.writeString(hierarchicalDesc);
244        dest.writeParcelable(parent, 0);
245    }
246
247    /**
248     * Construct a folder that queries for search results. Do not call on the UI
249     * thread.
250     */
251    public static CursorLoader forSearchResults(Account account, String query, Context context) {
252        if (account.searchUri != null) {
253            Builder searchBuilder = account.searchUri.buildUpon();
254            searchBuilder.appendQueryParameter(UIProvider.SearchQueryParameters.QUERY, query);
255            Uri searchUri = searchBuilder.build();
256            return new CursorLoader(context, searchUri, UIProvider.FOLDERS_PROJECTION, null, null,
257                    null);
258        }
259        return null;
260    }
261
262    public static HashMap<Uri, Folder> hashMapForFolders(ArrayList<Folder> rawFolders) {
263        final HashMap<Uri, Folder> folders = new HashMap<Uri, Folder>();
264        for (Folder f : rawFolders) {
265            folders.put(f.uri, f);
266        }
267        return folders;
268    }
269
270    private static Uri getValidUri(String uri) {
271        if (TextUtils.isEmpty(uri)) {
272            return null;
273        }
274        return Uri.parse(uri);
275    }
276
277    /**
278     * Constructor that leaves everything uninitialized.
279     */
280    private Folder() {
281        name = FOLDER_UNINITIALIZED;
282    }
283
284    /**
285     * Creates a new instance of a folder object that is <b>not</b> initialized.  The caller is
286     * expected to fill in the details. This resulting instance is not guaranteed to work
287     * correctly, and might break functionality.  Use at your own risk!!
288     * @return a new instance of an unsafe folder.
289     */
290    public static Folder newUnsafeInstance() {
291        return new Folder();
292    }
293
294    @SuppressWarnings("hiding")
295    public static final Creator<Folder> CREATOR = new Creator<Folder>() {
296        @Override
297        public Folder createFromParcel(Parcel source) {
298            return new Folder(source);
299        }
300
301        @Override
302        public Folder[] newArray(int size) {
303            return new Folder[size];
304        }
305    };
306
307    @Override
308    public int describeContents() {
309        // Return a sort of version number for this parcelable folder. Starting with zero.
310        return 0;
311    }
312
313    @Override
314    public boolean equals(Object o) {
315        if (o == null || !(o instanceof Folder)) {
316            return false;
317        }
318        return Objects.equal(uri, ((Folder) o).uri);
319    }
320
321    @Override
322    public int hashCode() {
323        return uri == null ? 0 : uri.hashCode();
324    }
325
326    @Override
327    public int compareTo(Folder other) {
328        return name.compareToIgnoreCase(other.name);
329    }
330
331    /**
332     * Create a Folder map from a string of serialized folders. This can only be done on the output
333     * of {@link #serialize(Map)}.
334     * @param serializedFolder A string obtained from {@link #serialize(Map)}
335     * @return a Map of folder name to folder.
336     */
337    public static Map<String, Folder> parseFoldersFromString(String serializedFoldersString) {
338        if (TextUtils.isEmpty(serializedFoldersString)) {
339            return null;
340        }
341        Map<String, Folder> folderMap = Maps.newHashMap();
342        ArrayList<Folder> folders = Folder.getFoldersArray(serializedFoldersString);
343        for (Folder folder : folders) {
344            if (folder.name != FOLDER_UNINITIALIZED) {
345                folderMap.put(folder.name, folder);
346            }
347        }
348        return folderMap;
349    }
350
351    /**
352     * Returns a boolean indicating whether network activity (sync) is occuring for this folder.
353     */
354    public boolean isSyncInProgress() {
355        return UIProvider.SyncStatus.isSyncInProgress(syncStatus);
356    }
357
358    /**
359     * Serialize the given list of folders
360     * @param folderMap A valid map of folder names to Folders
361     * @return a string containing a serialized output of folder maps.
362     */
363    public static String serialize(Map<String, Folder> folderMap) {
364        return getSerializedFolderString(folderMap.values());
365    }
366
367    public boolean supportsCapability(int capability) {
368        return (capabilities & capability) != 0;
369    }
370
371    // Show black text on a transparent swatch for system folders, effectively hiding the
372    // swatch (see bug 2431925).
373    public static void setFolderBlockColor(Folder folder, View colorBlock) {
374        if (colorBlock == null) {
375            return;
376        }
377        boolean showBg = !TextUtils.isEmpty(folder.bgColor);
378        final int backgroundColor = showBg ? Integer.parseInt(folder.bgColor) : 0;
379        if (backgroundColor == Utils.getDefaultFolderBackgroundColor(colorBlock.getContext())) {
380            showBg = false;
381        }
382        if (!showBg) {
383            colorBlock.setBackgroundDrawable(null);
384            colorBlock.setVisibility(View.GONE);
385        } else {
386            PaintDrawable paintDrawable = new PaintDrawable();
387            paintDrawable.getPaint().setColor(backgroundColor);
388            colorBlock.setBackgroundDrawable(paintDrawable);
389            colorBlock.setVisibility(View.VISIBLE);
390        }
391    }
392
393    public static void setIcon(Folder folder, ImageView iconView) {
394        if (iconView == null) {
395            return;
396        }
397        final long icon = folder.iconResId;
398        if (icon > 0) {
399            iconView.setImageResource((int)icon);
400            iconView.setVisibility(View.VISIBLE);
401        } else {
402            iconView.setVisibility(View.INVISIBLE);
403        }
404    }
405
406    /**
407     * Return if the type of the folder matches a provider defined folder.
408     */
409    public boolean isProviderFolder() {
410        return type != UIProvider.FolderType.DEFAULT;
411    }
412
413    public int getBackgroundColor(int defaultColor) {
414        return TextUtils.isEmpty(bgColor) ? defaultColor : Integer.parseInt(bgColor);
415    }
416
417    public int getForegroundColor(int defaultColor) {
418        return TextUtils.isEmpty(fgColor) ? defaultColor : Integer.parseInt(fgColor);
419    }
420
421    public static String getSerializedFolderString(Collection<Folder> folders) {
422        final StringBuilder folderList = new StringBuilder();
423        int i = 0;
424        for (Folder folderEntry : folders) {
425            folderList.append(Folder.toString(folderEntry));
426            if (i < folders.size()) {
427                folderList.append(FOLDERS_SPLIT);
428            }
429            i++;
430        }
431        return folderList.toString();
432    }
433
434
435    public static Folder fromString(String inString) {
436        if (TextUtils.isEmpty(inString)) {
437            return null;
438        }
439        final Folder f = new Folder();
440        final String[] split = TextUtils.split(inString, SPLITTER_REGEX);
441        if (split.length < 20) {
442            return null;
443        }
444        f.id = Integer.parseInt(split[0]);
445        f.uri = Folder.getValidUri(split[1]);
446        f.name = split[2];
447        f.hasChildren = Integer.parseInt(split[3]) != 0;
448        f.capabilities = Integer.parseInt(split[4]);
449        f.syncWindow = Integer.parseInt(split[5]);
450        f.conversationListUri = getValidUri(split[6]);
451        f.childFoldersListUri = getValidUri(split[7]);
452        f.unreadCount = Integer.parseInt(split[8]);
453        f.totalCount = Integer.parseInt(split[9]);
454        f.refreshUri = getValidUri(split[10]);
455        f.syncStatus = Integer.parseInt(split[11]);
456        f.lastSyncResult = Integer.parseInt(split[12]);
457        f.type = Integer.parseInt(split[13]);
458        f.iconResId = Integer.parseInt(split[14]);
459        f.bgColor = split[15];
460        f.fgColor = split[16];
461        f.loadMoreUri = getValidUri(split[17]);
462        f.hierarchicalDesc = split[18];
463        f.parent = Folder.fromString(split[19]);
464        return f;
465    }
466
467    /**
468     * Create a string representation of a folder.
469     */
470    public static String createAsString(int id, Uri uri, String name, boolean hasChildren,
471            int capabilities, int syncWindow, Uri convListUri, Uri childFoldersListUri,
472            int unreadCount, int totalCount, Uri refreshUri, int syncStatus, int lastSyncResult,
473            int type, long iconResId, String bgColor, String fgColor, Uri loadMore,
474            String hierarchicalDesc, Folder parent) {
475        StringBuilder builder = new StringBuilder();
476        builder.append(id);
477        builder.append(SPLITTER);
478        builder.append(uri);
479        builder.append(SPLITTER);
480        builder.append(name);
481        builder.append(SPLITTER);
482        builder.append(hasChildren ? 1 : 0);
483        builder.append(SPLITTER);
484        builder.append(capabilities);
485        builder.append(SPLITTER);
486        builder.append(syncWindow);
487        builder.append(SPLITTER);
488        builder.append(convListUri);
489        builder.append(SPLITTER);
490        builder.append(childFoldersListUri);
491        builder.append(SPLITTER);
492        builder.append(unreadCount);
493        builder.append(SPLITTER);
494        builder.append(totalCount);
495        builder.append(SPLITTER);
496        builder.append(refreshUri);
497        builder.append(SPLITTER);
498        builder.append(syncStatus);
499        builder.append(SPLITTER);
500        builder.append(lastSyncResult);
501        builder.append(SPLITTER);
502        builder.append(type);
503        builder.append(SPLITTER);
504        builder.append(iconResId);
505        builder.append(SPLITTER);
506        builder.append(bgColor);
507        builder.append(SPLITTER);
508        builder.append(fgColor);
509        builder.append(SPLITTER);
510        builder.append(loadMore);
511        builder.append(SPLITTER);
512        builder.append(hierarchicalDesc);
513        builder.append(SPLITTER);
514        if (parent != null) {
515            builder.append(Folder.toString(parent));
516        } else {
517            builder.append("");
518        }
519        return builder.toString();
520    }
521
522    public static String toString(Folder folder) {
523        return createAsString(folder.id, folder.uri, folder.name, folder.hasChildren,
524                folder.capabilities, folder.syncWindow, folder.conversationListUri,
525                folder.childFoldersListUri, folder.unreadCount, folder.totalCount,
526                folder.refreshUri, folder.syncStatus, folder.lastSyncResult, folder.type,
527                folder.iconResId, folder.bgColor, folder.fgColor, folder.loadMoreUri,
528                folder.hierarchicalDesc, folder.parent);
529    }
530
531    /**
532     * Returns a comma separated list of folder URIs for all the folders in the collection.
533     * @param folders
534     * @return
535     */
536    public final static String getUriString(Collection<Folder> folders) {
537        final StringBuilder uris = new StringBuilder();
538        boolean first = true;
539        for (Folder f : folders) {
540            if (first) {
541                first = false;
542            } else {
543                uris.append(',');
544            }
545            uris.append(f.uri.toString());
546        }
547        return uris.toString();
548    }
549
550
551    /**
552     * Get an array of folders from a rawFolders string.
553     */
554    public static ArrayList<Folder> getFoldersArray(String rawFolders) {
555        if (TextUtils.isEmpty(rawFolders)) {
556            return null;
557        }
558        ArrayList<Folder> folders = new ArrayList<Folder>();
559        String[] split = TextUtils.split(rawFolders, FOLDERS_SPLIT_REGEX);
560        Folder f;
561        for (String folder : split) {
562            f = Folder.fromString(folder);
563            if (f != null) {
564                folders.add(f);
565            }
566        }
567        return folders;
568    }
569
570    /**
571     * Get just the uri's from an arraylist of folders.
572     */
573    public final static String[] getUriArray(ArrayList<Folder> folders) {
574        if (folders == null || folders.size() == 0) {
575            return new String[0];
576        }
577        String[] folderUris = new String[folders.size()];
578        int i = 0;
579        for (Folder folder : folders) {
580            folderUris[i] = folder.uri.toString();
581            i++;
582        }
583        return folderUris;
584    }
585
586    /**
587     * Returns true if a conversation assigned to the needle will be assigned to the collection of
588     * folders in the haystack. False otherwise. This method is safe to call with null
589     * arguments.
590     * This method returns true under two circumstances
591     * <ul><li> If the URI of the needle was found in the collection of URIs that comprise the
592     * haystack.
593     * </li><li> If the needle is of the type Inbox, and at least one of the folders in the haystack
594     * are of type Inbox. <em>Rationale</em>: there are special folders that are marked as inbox,
595     * and the user might not have the control to assign conversations to them. This happens for
596     * the Priority Inbox in Gmail. When you assign a conversation to an Inbox folder, it will
597     * continue to appear in the Priority Inbox. However, the URI of Priority Inbox and Inbox will
598     * be different. So a direct equality check is insufficient.
599     * </li></ul>
600     * @param haystack a collection of folders, possibly overlapping
601     * @param needle a folder
602     * @return true if a conversation inside the needle will be in the folders in the haystack.
603     */
604    public final static boolean containerIncludes(Collection<Folder> haystack, Folder needle) {
605        // If the haystack is empty, it cannot contain anything.
606        if (haystack == null || haystack.size() <= 0) {
607            return false;
608        }
609        // The null folder exists everywhere.
610        if (needle == null) {
611            return true;
612        }
613        boolean hasInbox = false;
614        // Get currently active folder info and compare it to the list
615        // these conversations have been given; if they no longer contain
616        // the selected folder, delete them from the list.
617        final Uri toFind = needle.uri;
618        for (Folder f : haystack) {
619            if (toFind.equals(f.uri)) {
620                return true;
621            }
622            hasInbox |= (f.type == UIProvider.FolderType.INBOX);
623        }
624        // Did not find the URI of needle directly. If the needle is an Inbox and one of the folders
625        // was an inbox, then the needle is contained (check Javadoc for explanation).
626        final boolean needleIsInbox = (needle.type == UIProvider.FolderType.INBOX);
627        return needleIsInbox ? hasInbox : false;
628    }
629
630    /**
631     * Returns a boolean indicating whether this Folder object has been initialized
632     */
633    public boolean isInitialized() {
634        return name != FOLDER_UNINITIALIZED && conversationListUri != null &&
635                !NULL_STRING_URI.equals(conversationListUri.toString());
636    }
637
638    /**
639     * Returns a collection of a single folder. This method always returns a valid collection
640     * even if the input folder is null.
641     * @param in a folder, possibly null.
642     * @return a collection of the folder.
643     */
644    public static Collection<Folder> listOf(Folder in) {
645        final Collection<Folder> target = (in == null) ? EMPTY : ImmutableList.of(in);
646        return target;
647    }
648
649    /**
650     * Return if this is the trash folder.
651     */
652    public boolean isTrash() {
653        return type == UIProvider.FolderType.TRASH;
654    }
655
656    /**
657     * Return if this is a draft folder.
658     */
659    public boolean isDraft() {
660        return type == UIProvider.FolderType.DRAFT;
661    }
662
663    /**
664     * Whether this folder supports only showing important messages.
665     */
666    public boolean isImportantOnly() {
667        return supportsCapability(
668                UIProvider.FolderCapabilities.ONLY_IMPORTANT);
669    }
670
671    /**
672     * Whether this is the special folder just used to display all mail for an account.
673     */
674    public boolean isViewAll() {
675        return type == UIProvider.FolderType.ALL_MAIL;
676    }
677
678    /**
679     * True if the previous sync was successful, false otherwise.
680     * @return
681     */
682    public final boolean wasSyncSuccessful() {
683        return ((lastSyncResult & 0x0f) == UIProvider.LastSyncResult.SUCCESS);
684    }
685
686    /**
687     * Don't use this for ANYTHING but the FolderListAdapter. It does not have
688     * all the fields.
689     */
690    public static Folder getDeficientDisplayOnlyFolder(Cursor cursor) {
691        Folder f = Folder.newUnsafeInstance();
692        f.id = cursor.getInt(UIProvider.FOLDER_ID_COLUMN);
693        f.uri = Utils.getValidUri(cursor.getString(UIProvider.FOLDER_URI_COLUMN));
694        f.unreadCount = cursor.getInt(UIProvider.FOLDER_UNREAD_COUNT_COLUMN);
695        f.conversationListUri = Utils.getValidUri(cursor
696                .getString(UIProvider.FOLDER_CONVERSATION_LIST_URI_COLUMN));
697        f.type = cursor.getInt(UIProvider.FOLDER_TYPE_COLUMN);
698        f.capabilities = cursor.getInt(UIProvider.FOLDER_CAPABILITIES_COLUMN);
699        f.bgColor = cursor.getString(UIProvider.FOLDER_BG_COLOR_COLUMN);
700        f.name = cursor.getString(UIProvider.FOLDER_NAME_COLUMN);
701        return f;
702    }
703}
704