Folder.java revision d005ebdd6d0aef4aec2e631cfe37e014c99bfa3d
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 != null ? bgColor : ""); 507 builder.append(SPLITTER); 508 builder.append(fgColor != null ? 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