MessageCursor.java revision c42ad5ea3a49e6045a79d1fde3d858033176e67b
17bdc3750454efe59617b7df945eadd7e59bee954Andy Huang/* 27bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * Copyright (C) 2012 Google Inc. 37bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * Licensed to The Android Open Source Project. 47bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * 57bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * Licensed under the Apache License, Version 2.0 (the "License"); 67bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * you may not use this file except in compliance with the License. 77bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * You may obtain a copy of the License at 87bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * 97bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * http://www.apache.org/licenses/LICENSE-2.0 107bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * 117bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * Unless required by applicable law or agreed to in writing, software 127bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * distributed under the License is distributed on an "AS IS" BASIS, 137bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 147bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * See the License for the specific language governing permissions and 157bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * limitations under the License. 167bdc3750454efe59617b7df945eadd7e59bee954Andy Huang */ 177bdc3750454efe59617b7df945eadd7e59bee954Andy Huang 187bdc3750454efe59617b7df945eadd7e59bee954Andy Huangpackage com.android.mail.browse; 197bdc3750454efe59617b7df945eadd7e59bee954Andy Huang 207bdc3750454efe59617b7df945eadd7e59bee954Andy Huangimport android.database.Cursor; 21fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huangimport android.net.Uri; 2247aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huangimport android.os.Bundle; 23839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huangimport android.os.Parcelable; 247bdc3750454efe59617b7df945eadd7e59bee954Andy Huang 25c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrookimport com.android.mail.content.CursorCreator; 26c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrookimport com.android.mail.content.ObjectCursor; 27bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Weiimport com.android.mail.providers.Account; 286766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huangimport com.android.mail.providers.Attachment; 29839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huangimport com.android.mail.providers.Conversation; 307bdc3750454efe59617b7df945eadd7e59bee954Andy Huangimport com.android.mail.providers.Message; 3147aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huangimport com.android.mail.providers.UIProvider.CursorExtraKeys; 3247aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huangimport com.android.mail.providers.UIProvider.CursorStatus; 33839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huangimport com.android.mail.ui.ConversationUpdater; 34bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei 35cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huangimport com.google.common.base.Objects; 36fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huangimport com.google.common.collect.Lists; 377bdc3750454efe59617b7df945eadd7e59bee954Andy Huang 38fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huangimport java.util.List; 397bdc3750454efe59617b7df945eadd7e59bee954Andy Huang 407bdc3750454efe59617b7df945eadd7e59bee954Andy Huang/** 417bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * MessageCursor contains the messages within a conversation; the public methods within should 427bdc3750454efe59617b7df945eadd7e59bee954Andy Huang * only be called by the UI thread, as cursor position isn't guaranteed to be maintained 437bdc3750454efe59617b7df945eadd7e59bee954Andy Huang */ 44c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrookpublic class MessageCursor extends ObjectCursor<MessageCursor.ConversationMessage> { 4502133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang /** 4602133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang * The current controller that this cursor can use to reference the owning {@link Conversation}, 4702133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang * and a current {@link ConversationUpdater}. Since this cursor will survive a rotation, but 4802133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang * the controller does not, whatever the new controller is MUST update this reference before 4902133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang * using this cursor. 5002133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang */ 5102133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang private ConversationController mController; 527bdc3750454efe59617b7df945eadd7e59bee954Andy Huang 5347aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang private Integer mStatus; 5447aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang 55cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang public interface ConversationController { 5602133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang Conversation getConversation(); 57cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang ConversationUpdater getListController(); 58cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang MessageCursor getMessageCursor(); 59bbe74aee04f669990e888095b0d6858dc1e17ce1Mark Wei Account getAccount(); 60cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang } 61cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang 62839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang /** 63839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang * A message created as part of a conversation view. Sometimes, like during star/unstar, it's 64cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang * handy to have the owning {@link Conversation} for context. 65cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang * 66cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang * <p>This class must remain separate from the {@link MessageCursor} from whence it came, 67cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang * because cursors can be closed by their Loaders at any time. The 68cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang * {@link ConversationController} intermediate is used to obtain the currently opened cursor. 69839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang * 70839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang * <p>(N.B. This is a {@link Parcelable}, so try not to add non-transient fields here. 71839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang * Parcelable state belongs either in {@link Message} or {@link MessageViewState}. The 72839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang * assumption is that this class never needs the state of its extra context saved.) 73839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang */ 74cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang public static final class ConversationMessage extends Message { 75839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang 7602133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang private transient ConversationController mController; 77839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang 78c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook private ConversationMessage(Cursor cursor) { 79839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang super(cursor); 8002133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang } 8102133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang 8202133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang public void setController(ConversationController controller) { 83cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang mController = controller; 84cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang } 85cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang 8602133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang public Conversation getConversation() { 8702133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang return mController.getConversation(); 8802133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang } 8902133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang 90cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang /** 91cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang * Returns a hash code based on this message's identity, contents and current state. 92cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang * This is a separate method from hashCode() to allow for an instance of this class to be 93cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang * a functional key in a hash-based data structure. 94cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang * 95cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang */ 96cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang public int getStateHashCode() { 976766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang return Objects.hashCode(uri, read, starred, getAttachmentsStateHashCode()); 986766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang } 996766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang 1006766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang private int getAttachmentsStateHashCode() { 1016766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang int hash = 0; 1026766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang for (Attachment a : getAttachments()) { 103fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huang final Uri uri = a.getIdentifierUri(); 104fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huang hash += (uri != null ? uri.hashCode() : 0); 1056766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang } 1066766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang return hash; 107839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang } 108839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang 109839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang public boolean isConversationStarred() { 110cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang final MessageCursor c = mController.getMessageCursor(); 111cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang return c != null && c.isConversationStarred(); 112839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang } 113839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang 114839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang public void star(boolean newStarred) { 115cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang final ConversationUpdater listController = mController.getListController(); 116cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang if (listController != null) { 117cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang listController.starMessage(this, newStarred); 118cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang } 119839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang } 120839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang 121c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook /** 122c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook * Public object that knows how to construct Messages given Cursors. 123c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook */ 124c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook public static final CursorCreator<ConversationMessage> FACTORY = 125c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook new CursorCreator<ConversationMessage>() { 126c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook @Override 127c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook public ConversationMessage createFromCursor(Cursor c) { 128c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook return new ConversationMessage(c); 129c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook } 130c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook 131c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook @Override 132c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook public String toString() { 133c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook return "ConversationMessage CursorCreator"; 134c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook } 135c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook }; 136c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook 137839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang } 138839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang 13902133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang public MessageCursor(Cursor inner) { 140c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook super(inner, ConversationMessage.FACTORY); 14102133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang } 14202133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang 14302133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang public void setController(ConversationController controller) { 144cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang mController = controller; 1457bdc3750454efe59617b7df945eadd7e59bee954Andy Huang } 1467bdc3750454efe59617b7df945eadd7e59bee954Andy Huang 147839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang public ConversationMessage getMessage() { 148c42ad5ea3a49e6045a79d1fde3d858033176e67bPaul Westbrook final ConversationMessage m = getModel(); 14902133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang // ALWAYS set up each ConversationMessage with the latest controller. 15002133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang // Rotation invalidates everything except this Cursor, its Loader and the cached Messages, 15102133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang // so if we want to continue using them after rotate, we have to ensure their controller 15202133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang // references always point to the current controller. 15302133aa80d4ff68739a8b8c6f4cc00150a3cfc80Andy Huang m.setController(mController); 1547bdc3750454efe59617b7df945eadd7e59bee954Andy Huang return m; 1557bdc3750454efe59617b7df945eadd7e59bee954Andy Huang } 156cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank 157cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank // Is the conversation starred? 158cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank public boolean isConversationStarred() { 159cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank int pos = -1; 160cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank while (moveToPosition(++pos)) { 161423bea25992492efea7d414819729f9eae7ce72eAndy Huang if (getMessage().starred) { 162cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank return true; 163cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank } 164cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank } 165cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank return false; 166cf164d64bcb1da92b427bda99b97f7ec310ef704Marc Blank } 167bf232c3735f65b1a4746943e4a134e59e36f0bdePaul Westbrook 168423bea25992492efea7d414819729f9eae7ce72eAndy Huang 169423bea25992492efea7d414819729f9eae7ce72eAndy Huang public boolean isConversationRead() { 170423bea25992492efea7d414819729f9eae7ce72eAndy Huang int pos = -1; 171423bea25992492efea7d414819729f9eae7ce72eAndy Huang while (moveToPosition(++pos)) { 172423bea25992492efea7d414819729f9eae7ce72eAndy Huang if (!getMessage().read) { 173423bea25992492efea7d414819729f9eae7ce72eAndy Huang return false; 174423bea25992492efea7d414819729f9eae7ce72eAndy Huang } 175423bea25992492efea7d414819729f9eae7ce72eAndy Huang } 176423bea25992492efea7d414819729f9eae7ce72eAndy Huang return true; 177423bea25992492efea7d414819729f9eae7ce72eAndy Huang } 178cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang public void markMessagesRead() { 179cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang int pos = -1; 180cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang while (moveToPosition(++pos)) { 181cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang getMessage().read = true; 182cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang } 183cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang } 184cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang 1856766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang public int getStateHashCode() { 18606c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang return getStateHashCode(0); 18706c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang } 18806c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang 18906c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang /** 19006c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang * Calculate a hash code that compactly summarizes the state of the messages in this cursor, 19106c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang * with respect to the way the messages are displayed in conversation view. This is not a 19206c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang * general-purpose hash code. When the state hash codes of a new cursor differs from the 19306c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang * existing cursor's hash code, the conversation view will re-render from scratch. 19406c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang * 19506c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang * @param exceptLast optional number of messages to exclude iterating through at the end of the 19606c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang * cursor. pass zero to iterate through all messages (or use {@link #getStateHashCode()}). 19706c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang * @return state hash code of the selected messages in this cursor 19806c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang */ 19906c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang public int getStateHashCode(int exceptLast) { 200cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang int hashCode = 17; 201cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang int pos = -1; 20206c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang final int stopAt = getCount() - exceptLast; 20306c0362f59437f3ea2b5832272fb66158bb4b8c0Andy Huang while (moveToPosition(++pos) && pos < stopAt) { 204cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang hashCode = 31 * hashCode + getMessage().getStateHashCode(); 205cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang } 206cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang return hashCode; 207cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang } 208cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang 20947aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang public int getStatus() { 21047aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang if (mStatus != null) { 21147aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang return mStatus; 21247aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang } 21347aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang 21447aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang mStatus = CursorStatus.LOADED; 21547aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang final Bundle extras = getExtras(); 21647aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang if (extras != null && extras.containsKey(CursorExtraKeys.EXTRA_STATUS)) { 21747aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang mStatus = extras.getInt(CursorExtraKeys.EXTRA_STATUS); 21847aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang } 21947aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang return mStatus; 22047aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang } 22147aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang 222838c8c9b385d5907d3dc3e52aaeec87bdde2ae22Vikram Aggarwal /** 223838c8c9b385d5907d3dc3e52aaeec87bdde2ae22Vikram Aggarwal * Returns true if the cursor is fully loaded. Returns false if the cursor is expected to get 224838c8c9b385d5907d3dc3e52aaeec87bdde2ae22Vikram Aggarwal * new messages. 225838c8c9b385d5907d3dc3e52aaeec87bdde2ae22Vikram Aggarwal * @return 226838c8c9b385d5907d3dc3e52aaeec87bdde2ae22Vikram Aggarwal */ 22747aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang public boolean isLoaded() { 228838c8c9b385d5907d3dc3e52aaeec87bdde2ae22Vikram Aggarwal return !CursorStatus.isWaitingForResults(getStatus()); 22947aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang } 23047aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang 23147aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang public String getDebugDump() { 23247aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang StringBuilder sb = new StringBuilder(); 2339e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang sb.append(String.format("conv='%s' status=%d messages:\n", 2349e4ca7993213d296043d20fe9cf4e166b5d595e8Andy Huang mController.getConversation(), getStatus())); 23547aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang int pos = -1; 23647aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang while (moveToPosition(++pos)) { 2376766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang final ConversationMessage m = getMessage(); 238fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huang final List<Uri> attUris = Lists.newArrayList(); 239fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huang for (Attachment a : m.getAttachments()) { 240fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huang attUris.add(a.uri); 241fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huang } 24247aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang sb.append(String.format( 2436766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang "[Message #%d hash=%s uri=%s id=%s serverId=%s from='%s' draftType=%d" + 244fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huang " isSending=%s read=%s starred=%s attUris=%s]\n", 2458960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy pos, m.getStateHashCode(), m.uri, m.id, m.serverId, m.getFrom(), m.draftType, 246fc0eab16cbb294dd388011dfb2b6b3a846c4731fAndy Huang m.isSending, m.read, m.starred, attUris)); 24747aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang } 24847aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang return sb.toString(); 24947aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang } 25047aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang 2517bdc3750454efe59617b7df945eadd7e59bee954Andy Huang}