1624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey/*
2624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Copyright (C) 2009 The Android Open Source Project
3624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey *
4624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * you may not use this file except in compliance with the License.
6624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * You may obtain a copy of the License at
7624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey *
8624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey *
10624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * See the License for the specific language governing permissions and
14624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * limitations under the License.
15624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey */
16624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
17624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeypackage com.android.contacts.util;
18624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
19624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.content.Context;
20624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.content.pm.PackageManager;
21624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.database.Cursor;
22624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.graphics.drawable.Drawable;
23624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.provider.ContactsContract.Data;
24624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.text.TextUtils;
25624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeyimport android.text.format.DateUtils;
26624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
279fcf4b162328ccc35a473a1b3c11f4d02ab06bcaEric Fischerimport com.android.contacts.R;
289fcf4b162328ccc35a473a1b3c11f4d02ab06bcaEric Fischer
29624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey/**
30624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * Storage for a social status update. Holds a single update, but can use
31624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * {@link #possibleUpdate(Cursor)} to consider updating when a better status
32624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey * exists. Statuses with timestamps, or with newer timestamps win.
33624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey */
34624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkeypublic class DataStatus {
35624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private int mPresence = -1;
36624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private String mStatus = null;
37624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private long mTimestamp = -1;
38624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
39624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private String mResPackage = null;
40624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private int mIconRes = -1;
41624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private int mLabelRes = -1;
42624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
43624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    public DataStatus() {
44624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
45624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
46624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    public DataStatus(Cursor cursor) {
47624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        // When creating from cursor row, fill normally
48624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        fromCursor(cursor);
49624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
50624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
51624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    /**
52624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey     * Attempt updating this {@link DataStatus} based on values at the
53624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey     * current row of the given {@link Cursor}.
54624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey     */
55624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    public void possibleUpdate(Cursor cursor) {
56624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final boolean hasStatus = !isNull(cursor, Data.STATUS);
57624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final boolean hasTimestamp = !isNull(cursor, Data.STATUS_TIMESTAMP);
58624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
59624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        // Bail early when not valid status, or when previous status was
60624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        // found and we can't compare this one.
61624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        if (!hasStatus) return;
62624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        if (isValid() && !hasTimestamp) return;
63624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
64624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        if (hasTimestamp) {
65624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey            // Compare timestamps and bail if older status
66624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey            final long newTimestamp = getLong(cursor, Data.STATUS_TIMESTAMP, -1);
67624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey            if (newTimestamp < mTimestamp) return;
68624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
69624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey            mTimestamp = newTimestamp;
70624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        }
71624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
72624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        // Fill in remaining details from cursor
73624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        fromCursor(cursor);
74624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
75624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
76624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private void fromCursor(Cursor cursor) {
77624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        mPresence = getInt(cursor, Data.PRESENCE, -1);
78624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        mStatus = getString(cursor, Data.STATUS);
79624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        mTimestamp = getLong(cursor, Data.STATUS_TIMESTAMP, -1);
80624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        mResPackage = getString(cursor, Data.STATUS_RES_PACKAGE);
81624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        mIconRes = getInt(cursor, Data.STATUS_ICON, -1);
82624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        mLabelRes = getInt(cursor, Data.STATUS_LABEL, -1);
83624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
84624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
85624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    public boolean isValid() {
86624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        return !TextUtils.isEmpty(mStatus);
87624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
88624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
89624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    public int getPresence() {
90624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        return mPresence;
91624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
92624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
93624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    public CharSequence getStatus() {
94624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        return mStatus;
95624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
96624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
977f10d5670893aad216a90adba12b1faeec9b42a7Dmitri Plotnikov    public long getTimestamp() {
987f10d5670893aad216a90adba12b1faeec9b42a7Dmitri Plotnikov        return mTimestamp;
997f10d5670893aad216a90adba12b1faeec9b42a7Dmitri Plotnikov    }
1007f10d5670893aad216a90adba12b1faeec9b42a7Dmitri Plotnikov
101624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    /**
102624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey     * Build any timestamp and label into a single string.
103624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey     */
104624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    public CharSequence getTimestampLabel(Context context) {
105624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final PackageManager pm = context.getPackageManager();
106624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
107b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey        // Use local package for resources when none requested
108b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey        if (mResPackage == null) mResPackage = context.getPackageName();
109b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey
110624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final boolean validTimestamp = mTimestamp > 0;
111624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final boolean validLabel = mResPackage != null && mLabelRes != -1;
112624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
113624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final CharSequence timeClause = validTimestamp ? DateUtils.getRelativeTimeSpanString(
114624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey                mTimestamp, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS,
115624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey                DateUtils.FORMAT_ABBREV_RELATIVE) : null;
116624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final CharSequence labelClause = validLabel ? pm.getText(mResPackage, mLabelRes,
117624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey                null) : null;
118624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
119624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        if (validTimestamp && validLabel) {
120624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey            return context.getString(
1219fcf4b162328ccc35a473a1b3c11f4d02ab06bcaEric Fischer                    R.string.contact_status_update_attribution_with_date,
122624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey                    timeClause, labelClause);
123624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        } else if (validLabel) {
124624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey            return context.getString(
1259fcf4b162328ccc35a473a1b3c11f4d02ab06bcaEric Fischer                    R.string.contact_status_update_attribution,
126624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey                    labelClause);
127624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        } else if (validTimestamp) {
128624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey            return timeClause;
129624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        } else {
130624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey            return null;
131624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        }
132624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
133624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
134624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    public Drawable getIcon(Context context) {
135624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final PackageManager pm = context.getPackageManager();
136b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey
137b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey        // Use local package for resources when none requested
138b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey        if (mResPackage == null) mResPackage = context.getPackageName();
139b7da2d0f30e012f786686bedea065af01f20a4e2Jeff Sharkey
140624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final boolean validIcon = mResPackage != null && mIconRes != -1;
141624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        return validIcon ? pm.getDrawable(mResPackage, mIconRes, null) : null;
142624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
143624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
144624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private static String getString(Cursor cursor, String columnName) {
145624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        return cursor.getString(cursor.getColumnIndex(columnName));
146624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
147624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
148624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private static int getInt(Cursor cursor, String columnName) {
149624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        return cursor.getInt(cursor.getColumnIndex(columnName));
150624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
151624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
152624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private static int getInt(Cursor cursor, String columnName, int missingValue) {
153624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final int columnIndex = cursor.getColumnIndex(columnName);
154624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        return cursor.isNull(columnIndex) ? missingValue : cursor.getInt(columnIndex);
155624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
156624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
157624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private static long getLong(Cursor cursor, String columnName, long missingValue) {
158624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        final int columnIndex = cursor.getColumnIndex(columnName);
159624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        return cursor.isNull(columnIndex) ? missingValue : cursor.getLong(columnIndex);
160624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
161624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey
162624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    private static boolean isNull(Cursor cursor, String columnName) {
163624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey        return cursor.isNull(cursor.getColumnIndex(columnName));
164624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey    }
165624ddc3cce02e3d9216e87564766fd86e814675dJeff Sharkey}
166