summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/datamodel/data/ConversationListItemData.java
blob: b2e6e1cab144b9fbe458cfd3a1f3954abc0be11e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.messaging.datamodel.data;

import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;

import com.android.messaging.datamodel.DatabaseHelper;
import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
import com.android.messaging.datamodel.DatabaseHelper.MessageColumns;
import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
import com.android.messaging.datamodel.DatabaseWrapper;
import com.android.messaging.datamodel.action.DeleteConversationAction;
import com.android.messaging.util.Assert;
import com.android.messaging.util.Dates;
import com.google.common.base.Joiner;

import java.util.ArrayList;
import java.util.List;

/**
 * Class wrapping the conversation list view used to display each item in conversation list
 */
public class ConversationListItemData {
    private String mConversationId;
    private String mName;
    private String mIcon;
    private boolean mIsRead;
    private long mTimestamp;
    private String mSnippetText;
    private Uri mPreviewUri;
    private String mPreviewContentType;
    private long mParticipantContactId;
    private String mParticipantLookupKey;
    private String mOtherParticipantNormalizedDestination;
    private String mSelfId;
    private int mParticipantCount;
    private boolean mNotificationEnabled;
    private String mNotificationSoundUri;
    private boolean mNotificationVibrate;
    private boolean mIncludeEmailAddress;
    private int mMessageStatus;
    private int mMessageRawTelephonyStatus;
    private boolean mShowDraft;
    private Uri mDraftPreviewUri;
    private String mDraftPreviewContentType;
    private String mDraftSnippetText;
    private boolean mIsArchived;
    private String mSubject;
    private String mDraftSubject;
    private String mSnippetSenderFirstName;
    private String mSnippetSenderDisplayDestination;

    public ConversationListItemData() {
    }

    public void bind(final Cursor cursor) {
        bind(cursor, false);
    }

    public void bind(final Cursor cursor, final boolean ignoreDraft) {
        mConversationId = cursor.getString(INDEX_ID);
        mName = cursor.getString(INDEX_CONVERSATION_NAME);
        mIcon = cursor.getString(INDEX_CONVERSATION_ICON);
        mSnippetText = cursor.getString(INDEX_SNIPPET_TEXT);
        mTimestamp = cursor.getLong(INDEX_SORT_TIMESTAMP);
        mIsRead = cursor.getInt(INDEX_READ) == 1;
        final String previewUriString = cursor.getString(INDEX_PREVIEW_URI);
        mPreviewUri = TextUtils.isEmpty(previewUriString) ? null : Uri.parse(previewUriString);
        mPreviewContentType = cursor.getString(INDEX_PREVIEW_CONTENT_TYPE);
        mParticipantContactId = cursor.getLong(INDEX_PARTICIPANT_CONTACT_ID);
        mParticipantLookupKey = cursor.getString(INDEX_PARTICIPANT_LOOKUP_KEY);
        mOtherParticipantNormalizedDestination = cursor.getString(
                INDEX_OTHER_PARTICIPANT_NORMALIZED_DESTINATION);
        mSelfId = cursor.getString(INDEX_SELF_ID);
        mParticipantCount = cursor.getInt(INDEX_PARTICIPANT_COUNT);
        mNotificationEnabled = cursor.getInt(INDEX_NOTIFICATION_ENABLED) == 1;
        mNotificationSoundUri = cursor.getString(INDEX_NOTIFICATION_SOUND_URI);
        mNotificationVibrate = cursor.getInt(INDEX_NOTIFICATION_VIBRATION) == 1;
        mIncludeEmailAddress = cursor.getInt(INDEX_INCLUDE_EMAIL_ADDRESS) == 1;
        mMessageStatus = cursor.getInt(INDEX_MESSAGE_STATUS);
        mMessageRawTelephonyStatus = cursor.getInt(INDEX_MESSAGE_RAW_TELEPHONY_STATUS);
        if (!ignoreDraft) {
            mShowDraft = cursor.getInt(INDEX_SHOW_DRAFT) == 1;
            final String draftPreviewUriString = cursor.getString(INDEX_DRAFT_PREVIEW_URI);
            mDraftPreviewUri = TextUtils.isEmpty(draftPreviewUriString) ?
                    null : Uri.parse(draftPreviewUriString);
            mDraftPreviewContentType = cursor.getString(INDEX_DRAFT_PREVIEW_CONTENT_TYPE);
            mDraftSnippetText = cursor.getString(INDEX_DRAFT_SNIPPET_TEXT);
            mDraftSubject = cursor.getString(INDEX_DRAFT_SUBJECT_TEXT);
        } else {
            mShowDraft = false;
            mDraftPreviewUri = null;
            mDraftPreviewContentType = null;
            mDraftSnippetText = null;
            mDraftSubject = null;
        }

        mIsArchived = cursor.getInt(INDEX_ARCHIVE_STATUS) == 1;
        mSubject = cursor.getString(INDEX_SUBJECT_TEXT);
        mSnippetSenderFirstName = cursor.getString(INDEX_SNIPPET_SENDER_FIRST_NAME);
        mSnippetSenderDisplayDestination =
                cursor.getString(INDEX_SNIPPET_SENDER_DISPLAY_DESTINATION);
    }

    public String getConversationId() {
        return mConversationId;
    }

    public String getName() {
        return mName;
    }

    public String getIcon() {
        return mIcon;
    }

    public boolean getIsRead() {
        return mIsRead;
    }

    public String getFormattedTimestamp() {
        return Dates.getConversationTimeString(mTimestamp).toString();
    }

    public long getTimestamp() {
        return mTimestamp;
    }

    public String getSnippetText() {
        return mSnippetText;
    }

    public Uri getPreviewUri() {
        return mPreviewUri;
    }

    public String getPreviewContentType() {
        return mPreviewContentType;
    }

    public long getParticipantContactId() {
        return mParticipantContactId;
    }

    public String getParticipantLookupKey() {
        return mParticipantLookupKey;
    }

    public String getOtherParticipantNormalizedDestination() {
        return mOtherParticipantNormalizedDestination;
    }

    public String getSelfId() {
        return mSelfId;
    }

    public int getParticipantCount() {
        return mParticipantCount;
    }

    public boolean getIsGroup() {
        // Participant count excludes self
        return (mParticipantCount > 1);
    }

    public boolean getIncludeEmailAddress() {
        return mIncludeEmailAddress;
    }

    public boolean getNotificationEnabled() {
        return mNotificationEnabled;
    }

    public String getNotificationSoundUri() {
        return mNotificationSoundUri;
    }

    public boolean getNotifiationVibrate() {
        return mNotificationVibrate;
    }

    public final boolean getIsFailedStatus() {
        return (mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_FAILED ||
                mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER ||
                mMessageStatus == MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED ||
                mMessageStatus == MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE);
    }

    public final boolean getIsSendRequested() {
        return (mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND ||
                mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY ||
                mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_SENDING ||
                mMessageStatus == MessageData.BUGLE_STATUS_OUTGOING_RESENDING);
    }

    public boolean getIsMessageTypeOutgoing() {
        return !MessageData.getIsIncoming(mMessageStatus);
    }

    public int getMessageRawTelephonyStatus() {
        return mMessageRawTelephonyStatus;
    }

    public int getMessageStatus() {
        return mMessageStatus;
    }

    public boolean getShowDraft() {
        return mShowDraft;
    }

    public String getDraftSnippetText() {
        return mDraftSnippetText;
    }

    public Uri getDraftPreviewUri() {
        return mDraftPreviewUri;
    }

    public String getDraftPreviewContentType() {
        return mDraftPreviewContentType;
    }

    public boolean getIsArchived() {
        return mIsArchived;
    }

    public String getSubject() {
        return mSubject;
    }

    public String getDraftSubject() {
        return mDraftSubject;
    }

    public String getSnippetSenderName() {
        if (!TextUtils.isEmpty(mSnippetSenderFirstName)) {
            return mSnippetSenderFirstName;
        }
        return mSnippetSenderDisplayDestination;
    }

    public void deleteConversation() {
        DeleteConversationAction.deleteConversation(mConversationId, mTimestamp);
    }

    /**
     * Get the name of the view for this data item
     */
    public static final String getConversationListView() {
        return CONVERSATION_LIST_VIEW;
    }

    public static final String getConversationListViewSql() {
        return CONVERSATION_LIST_VIEW_SQL;
    }

    private static final String CONVERSATION_LIST_VIEW = "conversation_list_view";

    private static final String CONVERSATION_LIST_VIEW_PROJECTION =
            DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns._ID
            + " as " + ConversationListViewColumns._ID + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NAME
            + " as " + ConversationListViewColumns.NAME + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.CURRENT_SELF_ID
            + " as " + ConversationListViewColumns.CURRENT_SELF_ID + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.ARCHIVE_STATUS
            + " as " + ConversationListViewColumns.ARCHIVE_STATUS + ", "
            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.READ
            + " as " + ConversationListViewColumns.READ + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.ICON
            + " as " + ConversationListViewColumns.ICON + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PARTICIPANT_CONTACT_ID
            + " as " + ConversationListViewColumns.PARTICIPANT_CONTACT_ID + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PARTICIPANT_LOOKUP_KEY
            + " as " + ConversationListViewColumns.PARTICIPANT_LOOKUP_KEY + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.'
                    + ConversationColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION
            + " as " + ConversationListViewColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SORT_TIMESTAMP
            + " as " + ConversationListViewColumns.SORT_TIMESTAMP + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SHOW_DRAFT
            + " as " + ConversationListViewColumns.SHOW_DRAFT + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.DRAFT_SNIPPET_TEXT
            + " as " + ConversationListViewColumns.DRAFT_SNIPPET_TEXT + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.DRAFT_PREVIEW_URI
            + " as " + ConversationListViewColumns.DRAFT_PREVIEW_URI + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.DRAFT_SUBJECT_TEXT
            + " as " + ConversationListViewColumns.DRAFT_SUBJECT_TEXT + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.'
                    + ConversationColumns.DRAFT_PREVIEW_CONTENT_TYPE
            + " as " + ConversationListViewColumns.DRAFT_PREVIEW_CONTENT_TYPE + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PREVIEW_URI
            + " as " + ConversationListViewColumns.PREVIEW_URI + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PREVIEW_CONTENT_TYPE
            + " as " + ConversationListViewColumns.PREVIEW_CONTENT_TYPE + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.PARTICIPANT_COUNT
            + " as " + ConversationListViewColumns.PARTICIPANT_COUNT + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NOTIFICATION_ENABLED
            + " as " + ConversationListViewColumns.NOTIFICATION_ENABLED + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NOTIFICATION_SOUND_URI
            + " as " + ConversationListViewColumns.NOTIFICATION_SOUND_URI + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.NOTIFICATION_VIBRATION
            + " as " + ConversationListViewColumns.NOTIFICATION_VIBRATION + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' +
                    ConversationColumns.INCLUDE_EMAIL_ADDRESS
            + " as " + ConversationListViewColumns.INCLUDE_EMAIL_ADDRESS + ", "
            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.STATUS
            + " as " + ConversationListViewColumns.MESSAGE_STATUS + ", "
            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.RAW_TELEPHONY_STATUS
            + " as " + ConversationListViewColumns.MESSAGE_RAW_TELEPHONY_STATUS + ", "
            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID
            + " as " + ConversationListViewColumns.MESSAGE_ID + ", "
            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.FIRST_NAME
            + " as " + ConversationListViewColumns.SNIPPET_SENDER_FIRST_NAME + ", "
            + DatabaseHelper.PARTICIPANTS_TABLE + '.' + ParticipantColumns.DISPLAY_DESTINATION
            + " as " + ConversationListViewColumns.SNIPPET_SENDER_DISPLAY_DESTINATION;

    private static final String JOIN_PARTICIPANTS =
            " LEFT JOIN " + DatabaseHelper.PARTICIPANTS_TABLE + " ON ("
            + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns.SENDER_PARTICIPANT_ID
            + '=' + DatabaseHelper.PARTICIPANTS_TABLE + '.' + DatabaseHelper.ParticipantColumns._ID
            + ") ";

    // View that makes latest message read flag available with rest of conversation data.
    private static final String CONVERSATION_LIST_VIEW_SQL = "CREATE VIEW " +
            CONVERSATION_LIST_VIEW + " AS SELECT "
            + CONVERSATION_LIST_VIEW_PROJECTION + ", "
            // Snippet not part of the base projection shared with search view
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SNIPPET_TEXT
            + " as " + ConversationListViewColumns.SNIPPET_TEXT + ", "
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' + ConversationColumns.SUBJECT_TEXT
            + " as " + ConversationListViewColumns.SUBJECT_TEXT + " "
            + " FROM " + DatabaseHelper.CONVERSATIONS_TABLE
            + " LEFT JOIN " + DatabaseHelper.MESSAGES_TABLE + " ON ("
            + DatabaseHelper.CONVERSATIONS_TABLE + '.' +  ConversationColumns.LATEST_MESSAGE_ID
            + '=' + DatabaseHelper.MESSAGES_TABLE + '.' + MessageColumns._ID + ") "
            + JOIN_PARTICIPANTS
            + "ORDER BY " + DatabaseHelper.CONVERSATIONS_TABLE + '.'
            + ConversationColumns.SORT_TIMESTAMP + " DESC";

    public static class ConversationListViewColumns implements BaseColumns {
        public static final String _ID = ConversationColumns._ID;
        static final String NAME = ConversationColumns.NAME;
        static final String ARCHIVE_STATUS = ConversationColumns.ARCHIVE_STATUS;
        static final String READ = MessageColumns.READ;
        static final String SORT_TIMESTAMP = ConversationColumns.SORT_TIMESTAMP;
        static final String PREVIEW_URI = ConversationColumns.PREVIEW_URI;
        static final String PREVIEW_CONTENT_TYPE = ConversationColumns.PREVIEW_CONTENT_TYPE;
        static final String SNIPPET_TEXT = ConversationColumns.SNIPPET_TEXT;
        static final String SUBJECT_TEXT = ConversationColumns.SUBJECT_TEXT;
        static final String ICON = ConversationColumns.ICON;
        static final String SHOW_DRAFT = ConversationColumns.SHOW_DRAFT;
        static final String DRAFT_SUBJECT_TEXT = ConversationColumns.DRAFT_SUBJECT_TEXT;
        static final String DRAFT_PREVIEW_URI = ConversationColumns.DRAFT_PREVIEW_URI;
        static final String DRAFT_PREVIEW_CONTENT_TYPE =
                ConversationColumns.DRAFT_PREVIEW_CONTENT_TYPE;
        static final String DRAFT_SNIPPET_TEXT = ConversationColumns.DRAFT_SNIPPET_TEXT;
        static final String PARTICIPANT_CONTACT_ID = ConversationColumns.PARTICIPANT_CONTACT_ID;
        static final String PARTICIPANT_LOOKUP_KEY = ConversationColumns.PARTICIPANT_LOOKUP_KEY;
        static final String OTHER_PARTICIPANT_NORMALIZED_DESTINATION =
                ConversationColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION;
        static final String CURRENT_SELF_ID = ConversationColumns.CURRENT_SELF_ID;
        static final String PARTICIPANT_COUNT = ConversationColumns.PARTICIPANT_COUNT;
        static final String NOTIFICATION_ENABLED = ConversationColumns.NOTIFICATION_ENABLED;
        static final String NOTIFICATION_SOUND_URI = ConversationColumns.NOTIFICATION_SOUND_URI;
        static final String NOTIFICATION_VIBRATION = ConversationColumns.NOTIFICATION_VIBRATION;
        static final String INCLUDE_EMAIL_ADDRESS =
                ConversationColumns.INCLUDE_EMAIL_ADDRESS;
        static final String MESSAGE_STATUS = MessageColumns.STATUS;
        static final String MESSAGE_RAW_TELEPHONY_STATUS = MessageColumns.RAW_TELEPHONY_STATUS;
        static final String MESSAGE_ID = "message_id";
        static final String SNIPPET_SENDER_FIRST_NAME = "snippet_sender_first_name";
        static final String SNIPPET_SENDER_DISPLAY_DESTINATION =
                "snippet_sender_display_destination";
    }

    public static final String[] PROJECTION = {
        ConversationListViewColumns._ID,
        ConversationListViewColumns.NAME,
        ConversationListViewColumns.ICON,
        ConversationListViewColumns.SNIPPET_TEXT,
        ConversationListViewColumns.SORT_TIMESTAMP,
        ConversationListViewColumns.READ,
        ConversationListViewColumns.PREVIEW_URI,
        ConversationListViewColumns.PREVIEW_CONTENT_TYPE,
        ConversationListViewColumns.PARTICIPANT_CONTACT_ID,
        ConversationListViewColumns.PARTICIPANT_LOOKUP_KEY,
        ConversationListViewColumns.OTHER_PARTICIPANT_NORMALIZED_DESTINATION,
        ConversationListViewColumns.PARTICIPANT_COUNT,
        ConversationListViewColumns.CURRENT_SELF_ID,
        ConversationListViewColumns.NOTIFICATION_ENABLED,
        ConversationListViewColumns.NOTIFICATION_SOUND_URI,
        ConversationListViewColumns.NOTIFICATION_VIBRATION,
        ConversationListViewColumns.INCLUDE_EMAIL_ADDRESS,
        ConversationListViewColumns.MESSAGE_STATUS,
        ConversationListViewColumns.SHOW_DRAFT,
        ConversationListViewColumns.DRAFT_PREVIEW_URI,
        ConversationListViewColumns.DRAFT_PREVIEW_CONTENT_TYPE,
        ConversationListViewColumns.DRAFT_SNIPPET_TEXT,
        ConversationListViewColumns.ARCHIVE_STATUS,
        ConversationListViewColumns.MESSAGE_ID,
        ConversationListViewColumns.SUBJECT_TEXT,
        ConversationListViewColumns.DRAFT_SUBJECT_TEXT,
        ConversationListViewColumns.MESSAGE_RAW_TELEPHONY_STATUS,
        ConversationListViewColumns.SNIPPET_SENDER_FIRST_NAME,
        ConversationListViewColumns.SNIPPET_SENDER_DISPLAY_DESTINATION,
    };

    private static final int INDEX_ID = 0;
    private static final int INDEX_CONVERSATION_NAME = 1;
    private static final int INDEX_CONVERSATION_ICON = 2;
    private static final int INDEX_SNIPPET_TEXT = 3;
    private static final int INDEX_SORT_TIMESTAMP = 4;
    private static final int INDEX_READ = 5;
    private static final int INDEX_PREVIEW_URI = 6;
    private static final int INDEX_PREVIEW_CONTENT_TYPE = 7;
    private static final int INDEX_PARTICIPANT_CONTACT_ID = 8;
    private static final int INDEX_PARTICIPANT_LOOKUP_KEY = 9;
    private static final int INDEX_OTHER_PARTICIPANT_NORMALIZED_DESTINATION = 10;
    private static final int INDEX_PARTICIPANT_COUNT = 11;
    private static final int INDEX_SELF_ID = 12;
    private static final int INDEX_NOTIFICATION_ENABLED = 13;
    private static final int INDEX_NOTIFICATION_SOUND_URI = 14;
    private static final int INDEX_NOTIFICATION_VIBRATION = 15;
    private static final int INDEX_INCLUDE_EMAIL_ADDRESS = 16;
    private static final int INDEX_MESSAGE_STATUS = 17;
    private static final int INDEX_SHOW_DRAFT = 18;
    private static final int INDEX_DRAFT_PREVIEW_URI = 19;
    private static final int INDEX_DRAFT_PREVIEW_CONTENT_TYPE = 20;
    private static final int INDEX_DRAFT_SNIPPET_TEXT = 21;
    private static final int INDEX_ARCHIVE_STATUS = 22;
    private static final int INDEX_MESSAGE_ID = 23;
    private static final int INDEX_SUBJECT_TEXT = 24;
    private static final int INDEX_DRAFT_SUBJECT_TEXT = 25;
    private static final int INDEX_MESSAGE_RAW_TELEPHONY_STATUS = 26;
    private static final int INDEX_SNIPPET_SENDER_FIRST_NAME = 27;
    private static final int INDEX_SNIPPET_SENDER_DISPLAY_DESTINATION = 28;

    private static final String DIVIDER_TEXT = ", ";

    /**
     * Get a conversation from the local DB based on the conversation id.
     *
     * @param dbWrapper       The database
     * @param conversationId  The conversation Id to read
     * @return The existing conversation or null
     */
    public static ConversationListItemData getExistingConversation(final DatabaseWrapper dbWrapper,
            final String conversationId) {
        ConversationListItemData conversation = null;

        // Look for an existing conversation in the db with this conversation id
        Cursor cursor = null;
        try {
            // TODO: Should we be able to read a row from just the conversation table?
            cursor = dbWrapper.query(getConversationListView(),
                    PROJECTION,
                    ConversationColumns._ID + "=?",
                    new String[] { conversationId },
                    null, null, null);
            Assert.inRange(cursor.getCount(), 0, 1);
            if (cursor.moveToFirst()) {
                conversation = new ConversationListItemData();
                conversation.bind(cursor);
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return conversation;
    }

    public static String generateConversationName(final List<ParticipantData>
            participants) {
        if (participants.size() == 1) {
            // Prefer full name over first name for 1:1 conversation
            return participants.get(0).getDisplayName(true);
        }

        final ArrayList<String> participantNames = new ArrayList<String>();
        for (final ParticipantData participant : participants) {
            // Prefer first name over full name for group conversation
            participantNames.add(participant.getDisplayName(false));
        }

        final Joiner joiner = Joiner.on(DIVIDER_TEXT).skipNulls();
        return joiner.join(participantNames);
    }

}