Conversation.java revision a6b671dd9f5ba358a05888b3ab3bf1c5cb5cf493
1/** 2 * Copyright (c) 2012, Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.mail.providers; 18 19import android.database.Cursor; 20import android.net.Uri; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.text.TextUtils; 24 25import com.google.common.collect.ImmutableList; 26 27import java.util.Collection; 28import java.util.Collections; 29 30public class Conversation implements Parcelable { 31 public static final int NO_POSITION = -1; 32 33 public long id; 34 public Uri uri; 35 public String subject; 36 public long dateMs; 37 public String snippet; 38 public boolean hasAttachments; 39 public Uri messageListUri; 40 public String senders; 41 public int numMessages; 42 public int numDrafts; 43 public int sendingState; 44 public int priority; 45 public boolean read; 46 public boolean starred; 47 public String folderList; 48 public String rawFolders; 49 public int convFlags; 50 public int personalLevel; 51 public boolean spam; 52 public boolean muted; 53 public int color; 54 public Uri accountUri; 55 56 // Used within the UI to indicate the adapter position of this conversation 57 public transient int position; 58 // Used within the UI to indicate that a Conversation should be removed from the 59 // ConversationCursor when executing an update, e.g. the the Conversation is no longer 60 // in the ConversationList for the current folder, that is it's now in some other folder(s) 61 public transient boolean localDeleteOnUpdate; 62 63 // Constituents of convFlags below 64 // Flag indicating that the item has been deleted, but will continue being shown in the list 65 // Delete/Archive of a mostly-dead item will NOT propagate the delete/archive, but WILL remove 66 // the item from the cursor 67 public static final int FLAG_MOSTLY_DEAD = 1 << 0; 68 69 /** An immutable, empty conversation list */ 70 public static final Collection<Conversation> EMPTY = Collections.emptyList(); 71 72 @Override 73 public int describeContents() { 74 return 0; 75 } 76 77 @Override 78 public void writeToParcel(Parcel dest, int flags) { 79 dest.writeLong(id); 80 dest.writeParcelable(uri, flags); 81 dest.writeString(subject); 82 dest.writeLong(dateMs); 83 dest.writeString(snippet); 84 dest.writeByte(hasAttachments ? (byte) 1 : 0); 85 dest.writeParcelable(messageListUri, 0); 86 dest.writeString(senders); 87 dest.writeInt(numMessages); 88 dest.writeInt(numDrafts); 89 dest.writeInt(sendingState); 90 dest.writeInt(priority); 91 dest.writeByte(read ? (byte) 1 : 0); 92 dest.writeByte(starred ? (byte) 1 : 0); 93 dest.writeString(folderList); 94 dest.writeString(rawFolders); 95 dest.writeInt(convFlags); 96 dest.writeInt(personalLevel); 97 dest.writeInt(spam ? 1 : 0); 98 dest.writeInt(muted ? 1 : 0); 99 dest.writeInt(color); 100 dest.writeParcelable(accountUri, 0); 101 } 102 103 private Conversation(Parcel in) { 104 id = in.readLong(); 105 uri = in.readParcelable(null); 106 subject = in.readString(); 107 dateMs = in.readLong(); 108 snippet = in.readString(); 109 hasAttachments = (in.readByte() != 0); 110 messageListUri = in.readParcelable(null); 111 senders = in.readString(); 112 numMessages = in.readInt(); 113 numDrafts = in.readInt(); 114 sendingState = in.readInt(); 115 priority = in.readInt(); 116 read = (in.readByte() != 0); 117 starred = (in.readByte() != 0); 118 folderList = in.readString(); 119 rawFolders = in.readString(); 120 convFlags = in.readInt(); 121 personalLevel = in.readInt(); 122 spam = in.readInt() != 0; 123 muted = in.readInt() != 0; 124 color = in.readInt(); 125 accountUri = in.readParcelable(null); 126 position = NO_POSITION; 127 localDeleteOnUpdate = false; 128 } 129 130 @Override 131 public String toString() { 132 return "[conversation id=" + id + ", subject =" + subject + "]"; 133 } 134 135 public static final Creator<Conversation> CREATOR = new Creator<Conversation>() { 136 137 @Override 138 public Conversation createFromParcel(Parcel source) { 139 return new Conversation(source); 140 } 141 142 @Override 143 public Conversation[] newArray(int size) { 144 return new Conversation[size]; 145 } 146 147 }; 148 149 public static final Uri MOVE_CONVERSATIONS_URI = Uri.parse("content://moveconversations"); 150 151 public Conversation(Cursor cursor) { 152 if (cursor != null) { 153 id = cursor.getLong(UIProvider.CONVERSATION_ID_COLUMN); 154 uri = Uri.parse(cursor.getString(UIProvider.CONVERSATION_URI_COLUMN)); 155 dateMs = cursor.getLong(UIProvider.CONVERSATION_DATE_RECEIVED_MS_COLUMN); 156 subject = cursor.getString(UIProvider.CONVERSATION_SUBJECT_COLUMN); 157 // Don't allow null subject 158 if (subject == null) { 159 subject = ""; 160 } 161 snippet = cursor.getString(UIProvider.CONVERSATION_SNIPPET_COLUMN); 162 hasAttachments = cursor.getInt(UIProvider.CONVERSATION_HAS_ATTACHMENTS_COLUMN) != 0; 163 String messageList = cursor 164 .getString(UIProvider.CONVERSATION_MESSAGE_LIST_URI_COLUMN); 165 messageListUri = !TextUtils.isEmpty(messageList) ? Uri.parse(messageList) : null; 166 senders = cursor.getString(UIProvider.CONVERSATION_SENDER_INFO_COLUMN); 167 numMessages = cursor.getInt(UIProvider.CONVERSATION_NUM_MESSAGES_COLUMN); 168 numDrafts = cursor.getInt(UIProvider.CONVERSATION_NUM_DRAFTS_COLUMN); 169 sendingState = cursor.getInt(UIProvider.CONVERSATION_SENDING_STATE_COLUMN); 170 priority = cursor.getInt(UIProvider.CONVERSATION_PRIORITY_COLUMN); 171 read = cursor.getInt(UIProvider.CONVERSATION_READ_COLUMN) != 0; 172 starred = cursor.getInt(UIProvider.CONVERSATION_STARRED_COLUMN) != 0; 173 folderList = cursor.getString(UIProvider.CONVERSATION_FOLDER_LIST_COLUMN); 174 rawFolders = cursor.getString(UIProvider.CONVERSATION_RAW_FOLDERS_COLUMN); 175 convFlags = cursor.getInt(UIProvider.CONVERSATION_FLAGS_COLUMN); 176 personalLevel = cursor.getInt(UIProvider.CONVERSATION_PERSONAL_LEVEL_COLUMN); 177 spam = cursor.getInt(UIProvider.CONVERSATION_IS_SPAM_COLUMN) != 0; 178 muted = cursor.getInt(UIProvider.CONVERSATION_MUTED_COLUMN) != 0; 179 color = cursor.getInt(UIProvider.CONVERSATION_COLOR_COLUMN); 180 String account = cursor.getString(UIProvider.CONVERSATION_ACCOUNT_URI_COLUMN); 181 accountUri = !TextUtils.isEmpty(account) ? Uri.parse(account) : null; 182 position = NO_POSITION; 183 localDeleteOnUpdate = false; 184 } 185 } 186 187 public Conversation() { 188 } 189 190 public static Conversation create(long id, Uri uri, String subject, long dateMs, 191 String snippet, boolean hasAttachment, Uri messageListUri, String senders, 192 int numMessages, int numDrafts, int sendingState, int priority, boolean read, 193 boolean starred, String folderList, String rawFolders, int convFlags, 194 int personalLevel, boolean spam, boolean muted, Uri accountUri) { 195 196 final Conversation conversation = new Conversation(); 197 198 conversation.id = id; 199 conversation.uri = uri; 200 conversation.subject = subject; 201 conversation.dateMs = dateMs; 202 conversation.snippet = snippet; 203 conversation.hasAttachments = hasAttachment; 204 conversation.messageListUri = messageListUri; 205 conversation.senders = senders; 206 conversation.numMessages = numMessages; 207 conversation.numDrafts = numDrafts; 208 conversation.sendingState = sendingState; 209 conversation.priority = priority; 210 conversation.read = read; 211 conversation.starred = starred; 212 conversation.folderList = folderList; 213 conversation.rawFolders = rawFolders; 214 conversation.convFlags = convFlags; 215 conversation.personalLevel = personalLevel; 216 conversation.spam = spam; 217 conversation.muted = muted; 218 conversation.color = 0; 219 conversation.accountUri = accountUri; 220 return conversation; 221 } 222 223 @Override 224 public boolean equals(Object o) { 225 if (o instanceof Conversation) { 226 Conversation conv = (Conversation)o; 227 return conv.uri.equals(uri); 228 } 229 return false; 230 } 231 232 @Override 233 public int hashCode() { 234 return uri.hashCode(); 235 } 236 237 /** 238 * Get if this conversation is marked as high priority. 239 */ 240 public boolean isImportant() { 241 return priority == UIProvider.ConversationPriority.IMPORTANT; 242 } 243 244 /** 245 * Get if this conversation is mostly dead 246 */ 247 public boolean isMostlyDead() { 248 return (convFlags & FLAG_MOSTLY_DEAD) != 0; 249 } 250 251 /** 252 * Returns true if the URI of the conversation specified as the needle was found in the 253 * collection of conversations specified as the haystack. False otherwise. This method is safe 254 * to call with nullarguments. 255 * @param haystack 256 * @param needle 257 * @return true if the needle was found in the haystack, false otherwise. 258 */ 259 public final static boolean contains(Collection<Conversation> haystack, Conversation needle) { 260 // If the haystack is empty, it cannot contain anything. 261 if (haystack == null || haystack.size() <= 0) { 262 return false; 263 } 264 // The null folder exists everywhere. 265 if (needle == null) { 266 return true; 267 } 268 final long toFind = needle.id; 269 for (final Conversation c : haystack) { 270 if (toFind == c.id) { 271 return true; 272 } 273 } 274 return false; 275 } 276 277 /** 278 * Returns a collection of a single conversation. This method always returns a valid collection 279 * even if the input conversation is null. 280 * @param in a conversation, possibly null. 281 * @return a collection of the conversation. 282 */ 283 public static Collection<Conversation> listOf(Conversation in) { 284 final Collection<Conversation> target = (in == null) ? EMPTY : ImmutableList.of(in); 285 return target; 286 } 287 288 /** 289 * Create a human-readable string of all the conversations 290 * @param collection Any collection of conversations 291 * @return string with a human readable representation of the conversations. 292 */ 293 public static String toString(Collection<Conversation> collection) { 294 final StringBuilder out = new StringBuilder(collection.size() + " conversations:"); 295 int count = 0; 296 for (final Conversation c : collection) { 297 count++; 298 // Indent the conversations to make them easy to read in debug output. 299 out.append(" " + count + ": " + c.toString() + "\n"); 300 } 301 return out.toString(); 302 } 303}