1273399bf829133a8385332ad43add3c34c889102Chiao Cheng/* 2273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Copyright (C) 2011 The Android Open Source Project 3273399bf829133a8385332ad43add3c34c889102Chiao Cheng * 4273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 5273399bf829133a8385332ad43add3c34c889102Chiao Cheng * you may not use this file except in compliance with the License. 6273399bf829133a8385332ad43add3c34c889102Chiao Cheng * You may obtain a copy of the License at 7273399bf829133a8385332ad43add3c34c889102Chiao Cheng * 8273399bf829133a8385332ad43add3c34c889102Chiao Cheng * http://www.apache.org/licenses/LICENSE-2.0 9273399bf829133a8385332ad43add3c34c889102Chiao Cheng * 10273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Unless required by applicable law or agreed to in writing, software 11273399bf829133a8385332ad43add3c34c889102Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS, 12273399bf829133a8385332ad43add3c34c889102Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13273399bf829133a8385332ad43add3c34c889102Chiao Cheng * See the License for the specific language governing permissions and 14273399bf829133a8385332ad43add3c34c889102Chiao Cheng * limitations under the License. 15273399bf829133a8385332ad43add3c34c889102Chiao Cheng */ 16273399bf829133a8385332ad43add3c34c889102Chiao Cheng 17273399bf829133a8385332ad43add3c34c889102Chiao Chengpackage com.android.contacts.common.model.account; 18273399bf829133a8385332ad43add3c34c889102Chiao Cheng 19273399bf829133a8385332ad43add3c34c889102Chiao Chengimport android.accounts.Account; 20273399bf829133a8385332ad43add3c34c889102Chiao Chengimport android.content.Context; 21273399bf829133a8385332ad43add3c34c889102Chiao Chengimport android.database.Cursor; 22273399bf829133a8385332ad43add3c34c889102Chiao Chengimport android.net.Uri; 23c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shraunerimport android.os.Parcelable; 24273399bf829133a8385332ad43add3c34c889102Chiao Chengimport android.os.Parcel; 25273399bf829133a8385332ad43add3c34c889102Chiao Chengimport android.provider.BaseColumns; 26273399bf829133a8385332ad43add3c34c889102Chiao Chengimport android.provider.ContactsContract; 27273399bf829133a8385332ad43add3c34c889102Chiao Chengimport android.provider.ContactsContract.RawContacts; 28273399bf829133a8385332ad43add3c34c889102Chiao Chengimport android.text.TextUtils; 29273399bf829133a8385332ad43add3c34c889102Chiao Cheng 305e9f2a7a744b8ee651b258f60131d6d266b4ce06Chiao Chengimport com.google.common.base.Objects; 31273399bf829133a8385332ad43add3c34c889102Chiao Chengimport com.google.common.collect.Lists; 32273399bf829133a8385332ad43add3c34c889102Chiao Cheng 33273399bf829133a8385332ad43add3c34c889102Chiao Chengimport java.util.ArrayList; 34273399bf829133a8385332ad43add3c34c889102Chiao Chengimport java.util.List; 35273399bf829133a8385332ad43add3c34c889102Chiao Chengimport java.util.regex.Pattern; 36273399bf829133a8385332ad43add3c34c889102Chiao Cheng 37273399bf829133a8385332ad43add3c34c889102Chiao Cheng/** 38273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Wrapper for an account that includes a data set (which may be null). 39273399bf829133a8385332ad43add3c34c889102Chiao Cheng */ 40c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shraunerpublic class AccountWithDataSet implements Parcelable { 41273399bf829133a8385332ad43add3c34c889102Chiao Cheng private static final String STRINGIFY_SEPARATOR = "\u0001"; 42273399bf829133a8385332ad43add3c34c889102Chiao Cheng private static final String ARRAY_STRINGIFY_SEPARATOR = "\u0002"; 43273399bf829133a8385332ad43add3c34c889102Chiao Cheng 44273399bf829133a8385332ad43add3c34c889102Chiao Cheng private static final Pattern STRINGIFY_SEPARATOR_PAT = 45273399bf829133a8385332ad43add3c34c889102Chiao Cheng Pattern.compile(Pattern.quote(STRINGIFY_SEPARATOR)); 46273399bf829133a8385332ad43add3c34c889102Chiao Cheng private static final Pattern ARRAY_STRINGIFY_SEPARATOR_PAT = 47273399bf829133a8385332ad43add3c34c889102Chiao Cheng Pattern.compile(Pattern.quote(ARRAY_STRINGIFY_SEPARATOR)); 48273399bf829133a8385332ad43add3c34c889102Chiao Cheng 49c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner public final String name; 50c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner public final String type; 51273399bf829133a8385332ad43add3c34c889102Chiao Cheng public final String dataSet; 52273399bf829133a8385332ad43add3c34c889102Chiao Cheng private final AccountTypeWithDataSet mAccountTypeWithDataSet; 53273399bf829133a8385332ad43add3c34c889102Chiao Cheng 54273399bf829133a8385332ad43add3c34c889102Chiao Cheng private static final String[] ID_PROJECTION = new String[] {BaseColumns._ID}; 55273399bf829133a8385332ad43add3c34c889102Chiao Cheng private static final Uri RAW_CONTACTS_URI_LIMIT_1 = RawContacts.CONTENT_URI.buildUpon() 56273399bf829133a8385332ad43add3c34c889102Chiao Cheng .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, "1").build(); 57273399bf829133a8385332ad43add3c34c889102Chiao Cheng 58273399bf829133a8385332ad43add3c34c889102Chiao Cheng 59273399bf829133a8385332ad43add3c34c889102Chiao Cheng public AccountWithDataSet(String name, String type, String dataSet) { 60c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner this.name = emptyToNull(name); 61c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner this.type = emptyToNull(type); 62c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner this.dataSet = emptyToNull(dataSet); 63273399bf829133a8385332ad43add3c34c889102Chiao Cheng mAccountTypeWithDataSet = AccountTypeWithDataSet.get(type, dataSet); 64273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 65273399bf829133a8385332ad43add3c34c889102Chiao Cheng 66c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner private static final String emptyToNull(String text) { 67c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner return TextUtils.isEmpty(text) ? null : text; 68c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner } 69c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner 70273399bf829133a8385332ad43add3c34c889102Chiao Cheng public AccountWithDataSet(Parcel in) { 71c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner this.name = in.readString(); 72c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner this.type = in.readString(); 73273399bf829133a8385332ad43add3c34c889102Chiao Cheng this.dataSet = in.readString(); 74273399bf829133a8385332ad43add3c34c889102Chiao Cheng mAccountTypeWithDataSet = AccountTypeWithDataSet.get(type, dataSet); 75273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 76273399bf829133a8385332ad43add3c34c889102Chiao Cheng 77c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner public boolean isLocalAccount() { 78c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner return name == null && type == null; 79c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner } 80c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner 81c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner public Account getAccountOrNull() { 82c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner if (name != null && type != null) { 83c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner return new Account(name, type); 84c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner } 85c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner return null; 86c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner } 87c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner 88c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner public int describeContents() { 89c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner return 0; 90c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner } 91c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner 92273399bf829133a8385332ad43add3c34c889102Chiao Cheng public void writeToParcel(Parcel dest, int flags) { 93c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner dest.writeString(name); 94c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner dest.writeString(type); 95273399bf829133a8385332ad43add3c34c889102Chiao Cheng dest.writeString(dataSet); 96273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 97273399bf829133a8385332ad43add3c34c889102Chiao Cheng 98273399bf829133a8385332ad43add3c34c889102Chiao Cheng // For Parcelable 99273399bf829133a8385332ad43add3c34c889102Chiao Cheng public static final Creator<AccountWithDataSet> CREATOR = new Creator<AccountWithDataSet>() { 100273399bf829133a8385332ad43add3c34c889102Chiao Cheng public AccountWithDataSet createFromParcel(Parcel source) { 101273399bf829133a8385332ad43add3c34c889102Chiao Cheng return new AccountWithDataSet(source); 102273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 103273399bf829133a8385332ad43add3c34c889102Chiao Cheng 104273399bf829133a8385332ad43add3c34c889102Chiao Cheng public AccountWithDataSet[] newArray(int size) { 105273399bf829133a8385332ad43add3c34c889102Chiao Cheng return new AccountWithDataSet[size]; 106273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 107273399bf829133a8385332ad43add3c34c889102Chiao Cheng }; 108273399bf829133a8385332ad43add3c34c889102Chiao Cheng 109273399bf829133a8385332ad43add3c34c889102Chiao Cheng public AccountTypeWithDataSet getAccountTypeWithDataSet() { 110273399bf829133a8385332ad43add3c34c889102Chiao Cheng return mAccountTypeWithDataSet; 111273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 112273399bf829133a8385332ad43add3c34c889102Chiao Cheng 113273399bf829133a8385332ad43add3c34c889102Chiao Cheng /** 114273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Return {@code true} if this account has any contacts in the database. 115273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Touches DB. Don't use in the UI thread. 116273399bf829133a8385332ad43add3c34c889102Chiao Cheng */ 117273399bf829133a8385332ad43add3c34c889102Chiao Cheng public boolean hasData(Context context) { 118273399bf829133a8385332ad43add3c34c889102Chiao Cheng final String BASE_SELECTION = 119273399bf829133a8385332ad43add3c34c889102Chiao Cheng RawContacts.ACCOUNT_TYPE + " = ?" + " AND " + RawContacts.ACCOUNT_NAME + " = ?"; 120273399bf829133a8385332ad43add3c34c889102Chiao Cheng final String selection; 121273399bf829133a8385332ad43add3c34c889102Chiao Cheng final String[] args; 122273399bf829133a8385332ad43add3c34c889102Chiao Cheng if (TextUtils.isEmpty(dataSet)) { 123273399bf829133a8385332ad43add3c34c889102Chiao Cheng selection = BASE_SELECTION + " AND " + RawContacts.DATA_SET + " IS NULL"; 124273399bf829133a8385332ad43add3c34c889102Chiao Cheng args = new String[] {type, name}; 125273399bf829133a8385332ad43add3c34c889102Chiao Cheng } else { 126273399bf829133a8385332ad43add3c34c889102Chiao Cheng selection = BASE_SELECTION + " AND " + RawContacts.DATA_SET + " = ?"; 127273399bf829133a8385332ad43add3c34c889102Chiao Cheng args = new String[] {type, name, dataSet}; 128273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 129273399bf829133a8385332ad43add3c34c889102Chiao Cheng 130273399bf829133a8385332ad43add3c34c889102Chiao Cheng final Cursor c = context.getContentResolver().query(RAW_CONTACTS_URI_LIMIT_1, 131273399bf829133a8385332ad43add3c34c889102Chiao Cheng ID_PROJECTION, selection, args, null); 132273399bf829133a8385332ad43add3c34c889102Chiao Cheng if (c == null) return false; 133273399bf829133a8385332ad43add3c34c889102Chiao Cheng try { 134273399bf829133a8385332ad43add3c34c889102Chiao Cheng return c.moveToFirst(); 135273399bf829133a8385332ad43add3c34c889102Chiao Cheng } finally { 136273399bf829133a8385332ad43add3c34c889102Chiao Cheng c.close(); 137273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 138273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 139273399bf829133a8385332ad43add3c34c889102Chiao Cheng 140c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner public boolean equals(Object obj) { 141c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner if (obj instanceof AccountWithDataSet) { 142c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner AccountWithDataSet other = (AccountWithDataSet) obj; 143c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner return Objects.equal(name, other.name) 144c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner && Objects.equal(type, other.type) 145c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner && Objects.equal(dataSet, other.dataSet); 146c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner } 147c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner return false; 148273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 149273399bf829133a8385332ad43add3c34c889102Chiao Cheng 150273399bf829133a8385332ad43add3c34c889102Chiao Cheng public int hashCode() { 151c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner int result = 17; 152c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner result = 31 * result + (name != null ? name.hashCode() : 0); 153c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner result = 31 * result + (type != null ? type.hashCode() : 0); 154c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner result = 31 * result + (dataSet != null ? dataSet.hashCode() : 0); 155c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner return result; 156273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 157273399bf829133a8385332ad43add3c34c889102Chiao Cheng 158273399bf829133a8385332ad43add3c34c889102Chiao Cheng public String toString() { 159273399bf829133a8385332ad43add3c34c889102Chiao Cheng return "AccountWithDataSet {name=" + name + ", type=" + type + ", dataSet=" + dataSet + "}"; 160273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 161273399bf829133a8385332ad43add3c34c889102Chiao Cheng 162273399bf829133a8385332ad43add3c34c889102Chiao Cheng private static StringBuilder addStringified(StringBuilder sb, AccountWithDataSet account) { 163c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner if (!TextUtils.isEmpty(account.name)) sb.append(account.name); 164273399bf829133a8385332ad43add3c34c889102Chiao Cheng sb.append(STRINGIFY_SEPARATOR); 165c84821b8f8c1760c6515d86462708c39e9ce0fa1Jay Shrauner if (!TextUtils.isEmpty(account.type)) sb.append(account.type); 166273399bf829133a8385332ad43add3c34c889102Chiao Cheng sb.append(STRINGIFY_SEPARATOR); 167273399bf829133a8385332ad43add3c34c889102Chiao Cheng if (!TextUtils.isEmpty(account.dataSet)) sb.append(account.dataSet); 168273399bf829133a8385332ad43add3c34c889102Chiao Cheng 169273399bf829133a8385332ad43add3c34c889102Chiao Cheng return sb; 170273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 171273399bf829133a8385332ad43add3c34c889102Chiao Cheng 172273399bf829133a8385332ad43add3c34c889102Chiao Cheng /** 173273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Pack the instance into a string. 174273399bf829133a8385332ad43add3c34c889102Chiao Cheng */ 175273399bf829133a8385332ad43add3c34c889102Chiao Cheng public String stringify() { 176273399bf829133a8385332ad43add3c34c889102Chiao Cheng return addStringified(new StringBuilder(), this).toString(); 177273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 178273399bf829133a8385332ad43add3c34c889102Chiao Cheng 179273399bf829133a8385332ad43add3c34c889102Chiao Cheng /** 180273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Unpack a string created by {@link #stringify}. 181273399bf829133a8385332ad43add3c34c889102Chiao Cheng * 182273399bf829133a8385332ad43add3c34c889102Chiao Cheng * @throws IllegalArgumentException if it's an invalid string. 183273399bf829133a8385332ad43add3c34c889102Chiao Cheng */ 184273399bf829133a8385332ad43add3c34c889102Chiao Cheng public static AccountWithDataSet unstringify(String s) { 185273399bf829133a8385332ad43add3c34c889102Chiao Cheng final String[] array = STRINGIFY_SEPARATOR_PAT.split(s, 3); 186273399bf829133a8385332ad43add3c34c889102Chiao Cheng if (array.length < 3) { 187273399bf829133a8385332ad43add3c34c889102Chiao Cheng throw new IllegalArgumentException("Invalid string " + s); 188273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 189273399bf829133a8385332ad43add3c34c889102Chiao Cheng return new AccountWithDataSet(array[0], array[1], 190273399bf829133a8385332ad43add3c34c889102Chiao Cheng TextUtils.isEmpty(array[2]) ? null : array[2]); 191273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 192273399bf829133a8385332ad43add3c34c889102Chiao Cheng 193273399bf829133a8385332ad43add3c34c889102Chiao Cheng /** 194273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Pack a list of {@link AccountWithDataSet} into a string. 195273399bf829133a8385332ad43add3c34c889102Chiao Cheng */ 196273399bf829133a8385332ad43add3c34c889102Chiao Cheng public static String stringifyList(List<AccountWithDataSet> accounts) { 197273399bf829133a8385332ad43add3c34c889102Chiao Cheng final StringBuilder sb = new StringBuilder(); 198273399bf829133a8385332ad43add3c34c889102Chiao Cheng 199273399bf829133a8385332ad43add3c34c889102Chiao Cheng for (AccountWithDataSet account : accounts) { 200273399bf829133a8385332ad43add3c34c889102Chiao Cheng if (sb.length() > 0) { 201273399bf829133a8385332ad43add3c34c889102Chiao Cheng sb.append(ARRAY_STRINGIFY_SEPARATOR); 202273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 203273399bf829133a8385332ad43add3c34c889102Chiao Cheng addStringified(sb, account); 204273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 205273399bf829133a8385332ad43add3c34c889102Chiao Cheng 206273399bf829133a8385332ad43add3c34c889102Chiao Cheng return sb.toString(); 207273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 208273399bf829133a8385332ad43add3c34c889102Chiao Cheng 209273399bf829133a8385332ad43add3c34c889102Chiao Cheng /** 210273399bf829133a8385332ad43add3c34c889102Chiao Cheng * Unpack a list of {@link AccountWithDataSet} into a string. 211273399bf829133a8385332ad43add3c34c889102Chiao Cheng * 212273399bf829133a8385332ad43add3c34c889102Chiao Cheng * @throws IllegalArgumentException if it's an invalid string. 213273399bf829133a8385332ad43add3c34c889102Chiao Cheng */ 214273399bf829133a8385332ad43add3c34c889102Chiao Cheng public static List<AccountWithDataSet> unstringifyList(String s) { 215273399bf829133a8385332ad43add3c34c889102Chiao Cheng final ArrayList<AccountWithDataSet> ret = Lists.newArrayList(); 216273399bf829133a8385332ad43add3c34c889102Chiao Cheng if (TextUtils.isEmpty(s)) { 217273399bf829133a8385332ad43add3c34c889102Chiao Cheng return ret; 218273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 219273399bf829133a8385332ad43add3c34c889102Chiao Cheng 220273399bf829133a8385332ad43add3c34c889102Chiao Cheng final String[] array = ARRAY_STRINGIFY_SEPARATOR_PAT.split(s); 221273399bf829133a8385332ad43add3c34c889102Chiao Cheng 222273399bf829133a8385332ad43add3c34c889102Chiao Cheng for (int i = 0; i < array.length; i++) { 223273399bf829133a8385332ad43add3c34c889102Chiao Cheng ret.add(unstringify(array[i])); 224273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 225273399bf829133a8385332ad43add3c34c889102Chiao Cheng 226273399bf829133a8385332ad43add3c34c889102Chiao Cheng return ret; 227273399bf829133a8385332ad43add3c34c889102Chiao Cheng } 228273399bf829133a8385332ad43add3c34c889102Chiao Cheng} 229