1/*
2 * Copyright (C) 2011 The Android Open Source Project
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.contacts.util;
18
19import android.content.Context;
20import android.database.Cursor;
21import android.provider.ContactsContract.StreamItems;
22import android.text.Html;
23
24import com.android.contacts.detail.ContactDetailDisplayUtils;
25import com.android.contacts.test.NeededForTesting;
26
27import java.util.ArrayList;
28import java.util.Collections;
29import java.util.List;
30
31/**
32 * Data object for a social stream item.  Social stream items may contain multiple
33 * mPhotos.  Social stream item entries are comparable; entries with more recent
34 * timestamps will be displayed on top.
35 */
36public class StreamItemEntry implements Comparable<StreamItemEntry> {
37
38    // Basic stream item fields.
39    private final long mId;
40    private final String mText;
41    private final String mComments;
42    private final long mTimestamp;
43    private final String mAccountType;
44    private final String mAccountName;
45    private final String mDataSet;
46
47    private boolean mDecoded;
48    private CharSequence mDecodedText;
49    private CharSequence mDecodedComments;
50
51    // Package references for label and icon resources.
52    private final String mResPackage;
53    private final String mIconRes;
54    private final String mLabelRes;
55
56    // Photos associated with this stream item.
57    private List<StreamItemPhotoEntry> mPhotos;
58
59    @NeededForTesting
60    public static StreamItemEntry createForTest(long id, String text, String comments,
61            long timestamp, String accountType, String accountName, String dataSet,
62            String resPackage, String iconRes, String labelRes) {
63        return new StreamItemEntry(id, text, comments, timestamp, accountType, accountName, dataSet,
64                resPackage, iconRes, labelRes);
65    }
66
67    private StreamItemEntry(long id, String text, String comments, long timestamp,
68            String accountType, String accountName, String dataSet, String resPackage,
69            String iconRes, String labelRes) {
70        mId = id;
71        mText = text;
72        mComments = comments;
73        mTimestamp = timestamp;
74        mAccountType = accountType;
75        mAccountName = accountName;
76        mDataSet = dataSet;
77        mResPackage = resPackage;
78        mIconRes = iconRes;
79        mLabelRes = labelRes;
80        mPhotos = new ArrayList<StreamItemPhotoEntry>();
81    }
82
83    public StreamItemEntry(Cursor cursor) {
84        // This is expected to be populated via a cursor containing all StreamItems columns in
85        // its projection.
86        mId = getLong(cursor, StreamItems._ID);
87        mText = getString(cursor, StreamItems.TEXT);
88        mComments = getString(cursor, StreamItems.COMMENTS);
89        mTimestamp = getLong(cursor, StreamItems.TIMESTAMP);
90        mAccountType = getString(cursor, StreamItems.ACCOUNT_TYPE);
91        mAccountName = getString(cursor, StreamItems.ACCOUNT_NAME);
92        mDataSet = getString(cursor, StreamItems.DATA_SET);
93        mResPackage = getString(cursor, StreamItems.RES_PACKAGE);
94        mIconRes = getString(cursor, StreamItems.RES_ICON);
95        mLabelRes = getString(cursor, StreamItems.RES_LABEL);
96        mPhotos = new ArrayList<StreamItemPhotoEntry>();
97    }
98
99    public void addPhoto(StreamItemPhotoEntry photoEntry) {
100        mPhotos.add(photoEntry);
101    }
102
103    @Override
104    public int compareTo(StreamItemEntry other) {
105        return mTimestamp == other.mTimestamp ? 0 : mTimestamp > other.mTimestamp ? -1 : 1;
106    }
107
108    public long getId() {
109        return mId;
110    }
111
112    public String getText() {
113        return mText;
114    }
115
116    public String getComments() {
117        return mComments;
118    }
119
120    public long getTimestamp() {
121        return mTimestamp;
122    }
123
124    public String getAccountType() {
125        return mAccountType;
126    }
127
128    public String getAccountName() {
129        return mAccountName;
130    }
131
132    public String getDataSet() {
133        return mDataSet;
134    }
135
136    public String getResPackage() {
137        return mResPackage;
138    }
139
140    public String getIconRes() {
141        return mIconRes;
142    }
143
144    public String getLabelRes() {
145        return mLabelRes;
146    }
147
148    public List<StreamItemPhotoEntry> getPhotos() {
149        Collections.sort(mPhotos);
150        return mPhotos;
151    }
152
153    /**
154     * Make {@link #getDecodedText} and {@link #getDecodedComments} available.  Must be called
155     * before calling those.
156     *
157     * We can't do this automatically in the getters, because it'll require a {@link Context}.
158     */
159    public void decodeHtml(Context context) {
160        final Html.ImageGetter imageGetter = ContactDetailDisplayUtils.getImageGetter(context);
161        if (mText != null) {
162            mDecodedText = HtmlUtils.fromHtml(context, mText, imageGetter, null);
163        }
164        if (mComments != null) {
165            mDecodedComments = HtmlUtils.fromHtml(context, mComments, imageGetter, null);
166        }
167        mDecoded = true;
168    }
169
170    public CharSequence getDecodedText() {
171        checkDecoded();
172        return mDecodedText;
173    }
174
175    public CharSequence getDecodedComments() {
176        checkDecoded();
177        return mDecodedComments;
178    }
179
180    private void checkDecoded() {
181        if (!mDecoded) {
182            throw new IllegalStateException("decodeHtml must have been called");
183        }
184    }
185
186    private static String getString(Cursor cursor, String columnName) {
187        return cursor.getString(cursor.getColumnIndex(columnName));
188    }
189
190    private static long getLong(Cursor cursor, String columnName) {
191        final int columnIndex = cursor.getColumnIndex(columnName);
192        return cursor.getLong(columnIndex);
193    }
194}
195