1 /* 2 * Copyright (C) 2009 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 17 package com.android.loaderapp.util; 18 19 import android.content.Context; 20 import android.content.pm.PackageManager; 21 import android.database.Cursor; 22 import android.graphics.drawable.Drawable; 23 import android.provider.ContactsContract.Data; 24 import android.text.TextUtils; 25 import android.text.format.DateUtils; 26 27 /** 28 * Storage for a social status update. Holds a single update, but can use 29 * {@link #possibleUpdate(Cursor)} to consider updating when a better status 30 * exists. Statuses with timestamps, or with newer timestamps win. 31 */ 32 public class DataStatus { 33 private int mPresence = -1; 34 private String mStatus = null; 35 private long mTimestamp = -1; 36 37 private String mResPackage = null; 38 private int mIconRes = -1; 39 private int mLabelRes = -1; 40 41 public DataStatus() { 42 } 43 44 public DataStatus(Cursor cursor) { 45 // When creating from cursor row, fill normally 46 fromCursor(cursor); 47 } 48 49 /** 50 * Attempt updating this {@link DataStatus} based on values at the 51 * current row of the given {@link Cursor}. 52 */ 53 public void possibleUpdate(Cursor cursor) { 54 final boolean hasStatus = !isNull(cursor, Data.STATUS); 55 final boolean hasTimestamp = !isNull(cursor, Data.STATUS_TIMESTAMP); 56 57 // Bail early when not valid status, or when previous status was 58 // found and we can't compare this one. 59 if (!hasStatus) return; 60 if (isValid() && !hasTimestamp) return; 61 62 if (hasTimestamp) { 63 // Compare timestamps and bail if older status 64 final long newTimestamp = getLong(cursor, Data.STATUS_TIMESTAMP, -1); 65 if (newTimestamp < mTimestamp) return; 66 67 mTimestamp = newTimestamp; 68 } 69 70 // Fill in remaining details from cursor 71 fromCursor(cursor); 72 } 73 74 private void fromCursor(Cursor cursor) { 75 mPresence = getInt(cursor, Data.PRESENCE, -1); 76 mStatus = getString(cursor, Data.STATUS); 77 mTimestamp = getLong(cursor, Data.STATUS_TIMESTAMP, -1); 78 mResPackage = getString(cursor, Data.STATUS_RES_PACKAGE); 79 mIconRes = getInt(cursor, Data.STATUS_ICON, -1); 80 mLabelRes = getInt(cursor, Data.STATUS_LABEL, -1); 81 } 82 83 public boolean isValid() { 84 return !TextUtils.isEmpty(mStatus); 85 } 86 87 public int getPresence() { 88 return mPresence; 89 } 90 91 public CharSequence getStatus() { 92 return mStatus; 93 } 94 95 /** 96 * Build any timestamp and label into a single string. 97 */ 98 public CharSequence getTimestampLabel(Context context) { 99 final PackageManager pm = context.getPackageManager(); 100 101 // Use local package for resources when none requested 102 if (mResPackage == null) mResPackage = context.getPackageName(); 103 104 final boolean validTimestamp = mTimestamp > 0; 105 final boolean validLabel = mResPackage != null && mLabelRes != -1; 106 107 final CharSequence timeClause = validTimestamp ? DateUtils.getRelativeTimeSpanString( 108 mTimestamp, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, 109 DateUtils.FORMAT_ABBREV_RELATIVE) : null; 110 final CharSequence labelClause = validLabel ? pm.getText(mResPackage, mLabelRes, 111 null) : null; 112 113 if (validTimestamp && validLabel) { 114 return context.getString( 115 com.android.internal.R.string.contact_status_update_attribution_with_date, 116 timeClause, labelClause); 117 } else if (validLabel) { 118 return context.getString( 119 com.android.internal.R.string.contact_status_update_attribution, 120 labelClause); 121 } else if (validTimestamp) { 122 return timeClause; 123 } else { 124 return null; 125 } 126 } 127 128 public Drawable getIcon(Context context) { 129 final PackageManager pm = context.getPackageManager(); 130 131 // Use local package for resources when none requested 132 if (mResPackage == null) mResPackage = context.getPackageName(); 133 134 final boolean validIcon = mResPackage != null && mIconRes != -1; 135 return validIcon ? pm.getDrawable(mResPackage, mIconRes, null) : null; 136 } 137 138 private static String getString(Cursor cursor, String columnName) { 139 return cursor.getString(cursor.getColumnIndex(columnName)); 140 } 141 142 private static int getInt(Cursor cursor, String columnName) { 143 return cursor.getInt(cursor.getColumnIndex(columnName)); 144 } 145 146 private static int getInt(Cursor cursor, String columnName, int missingValue) { 147 final int columnIndex = cursor.getColumnIndex(columnName); 148 return cursor.isNull(columnIndex) ? missingValue : cursor.getInt(columnIndex); 149 } 150 151 private static long getLong(Cursor cursor, String columnName, long missingValue) { 152 final int columnIndex = cursor.getColumnIndex(columnName); 153 return cursor.isNull(columnIndex) ? missingValue : cursor.getLong(columnIndex); 154 } 155 156 private static boolean isNull(Cursor cursor, String columnName) { 157 return cursor.isNull(cursor.getColumnIndex(columnName)); 158 } 159 } 160