1e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng/*
2e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * Copyright (C) 2011 The Android Open Source Project
3e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng *
4e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License");
5e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * you may not use this file except in compliance with the License.
6e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * You may obtain a copy of the License at
7e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng *
8e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng *      http://www.apache.org/licenses/LICENSE-2.0
9e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng *
10e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * Unless required by applicable law or agreed to in writing, software
11e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS,
12e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * See the License for the specific language governing permissions and
14e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * limitations under the License.
15e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng */
16e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
1769c182afb0e6d82a341a28b4317aa703af768906Gary Maipackage com.android.contacts.model.account;
18e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
19e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport android.accounts.Account;
20a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerottimport android.content.ContentProviderOperation;
21e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport android.content.Context;
22e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport android.database.Cursor;
23e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport android.net.Uri;
24e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport android.os.Parcel;
25819214d472fdadf3d69cb4580e238506194ed30eMarcus Hagerottimport android.os.Parcelable;
26e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport android.provider.BaseColumns;
27e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport android.provider.ContactsContract;
28e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport android.provider.ContactsContract.RawContacts;
29e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport android.text.TextUtils;
30e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
3169c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.AccountTypeManager;
3269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.preference.ContactsPreferences;
3341ba9e52de4f7ef962e6105095030f44fb9d6fefChiao Chengimport com.google.common.base.Objects;
34e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport com.google.common.collect.Lists;
35e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
36e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport java.util.ArrayList;
37e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport java.util.List;
38e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Chengimport java.util.regex.Pattern;
39e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
40e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng/**
41e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng * Wrapper for an account that includes a data set (which may be null).
42e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng */
432ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shraunerpublic class AccountWithDataSet implements Parcelable {
44e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    private static final String STRINGIFY_SEPARATOR = "\u0001";
45e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    private static final String ARRAY_STRINGIFY_SEPARATOR = "\u0002";
46e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
47e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    private static final Pattern STRINGIFY_SEPARATOR_PAT =
48e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            Pattern.compile(Pattern.quote(STRINGIFY_SEPARATOR));
49e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    private static final Pattern ARRAY_STRINGIFY_SEPARATOR_PAT =
50e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            Pattern.compile(Pattern.quote(ARRAY_STRINGIFY_SEPARATOR));
51e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
522ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    public final String name;
532ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    public final String type;
54e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public final String dataSet;
55e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    private final AccountTypeWithDataSet mAccountTypeWithDataSet;
56e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
57e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    private static final String[] ID_PROJECTION = new String[] {BaseColumns._ID};
58e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    private static final Uri RAW_CONTACTS_URI_LIMIT_1 = RawContacts.CONTENT_URI.buildUpon()
59e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, "1").build();
60e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
610ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang    public static final String LOCAL_ACCOUNT_SELECTION = RawContacts.ACCOUNT_TYPE + " IS NULL AND "
620ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang            + RawContacts.ACCOUNT_NAME + " IS NULL AND "
630ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang            + RawContacts.DATA_SET + " IS NULL";
64e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
65e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public AccountWithDataSet(String name, String type, String dataSet) {
662ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        this.name = emptyToNull(name);
672ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        this.type = emptyToNull(type);
682ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        this.dataSet = emptyToNull(dataSet);
69e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        mAccountTypeWithDataSet = AccountTypeWithDataSet.get(type, dataSet);
70e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
71e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
722ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    private static final String emptyToNull(String text) {
732ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        return TextUtils.isEmpty(text) ? null : text;
742ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    }
752ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner
76e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public AccountWithDataSet(Parcel in) {
772ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        this.name = in.readString();
782ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        this.type = in.readString();
79e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        this.dataSet = in.readString();
80e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        mAccountTypeWithDataSet = AccountTypeWithDataSet.get(type, dataSet);
81e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
82e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
83949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott    public boolean isNullAccount() {
840ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang        return name == null && type == null && dataSet == null;
850ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang    }
860ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang
87949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott    public static AccountWithDataSet getNullAccount() {
880ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang        return new AccountWithDataSet(null, null, null);
892ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    }
902ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner
912ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    public Account getAccountOrNull() {
922ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        if (name != null && type != null) {
932ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner            return new Account(name, type);
942ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        }
952ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        return null;
962ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    }
972ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner
982ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    public int describeContents() {
992ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        return 0;
1002ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    }
1012ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner
102e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public void writeToParcel(Parcel dest, int flags) {
1032ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        dest.writeString(name);
1042ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        dest.writeString(type);
105e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        dest.writeString(dataSet);
106e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
107e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
108e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    // For Parcelable
109e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public static final Creator<AccountWithDataSet> CREATOR = new Creator<AccountWithDataSet>() {
110e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        public AccountWithDataSet createFromParcel(Parcel source) {
111e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            return new AccountWithDataSet(source);
112e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        }
113e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
114e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        public AccountWithDataSet[] newArray(int size) {
115e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            return new AccountWithDataSet[size];
116e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        }
117e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    };
118e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
119e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public AccountTypeWithDataSet getAccountTypeWithDataSet() {
120e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        return mAccountTypeWithDataSet;
121e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
122e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
123e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    /**
124e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     * Return {@code true} if this account has any contacts in the database.
125e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     * Touches DB.  Don't use in the UI thread.
126e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     */
127e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public boolean hasData(Context context) {
1280ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang        String selection;
1290ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang        String[] args = null;
130949d4e88400761dac02992978f6b79997b5f0055Marcus Hagerott        if (isNullAccount()) {
1310ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang            selection = LOCAL_ACCOUNT_SELECTION;
132e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        } else {
1330ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang            final String BASE_SELECTION =
1340ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang                    RawContacts.ACCOUNT_TYPE + " = ?" + " AND " + RawContacts.ACCOUNT_NAME + " = ?";
1350ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang            if (TextUtils.isEmpty(dataSet)) {
1360ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang                selection = BASE_SELECTION + " AND " + RawContacts.DATA_SET + " IS NULL";
1370ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang                args = new String[] {type, name};
1380ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang            } else {
1390ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang                selection = BASE_SELECTION + " AND " + RawContacts.DATA_SET + " = ?";
1400ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang                args = new String[] {type, name, dataSet};
1410ac73ba01aa1f9fc9cc2cc23703cf6c24e40f488Tingting Wang            }
142e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        }
143bc5108495a35010073b925f9c7e04ee35fe1120eMarcus Hagerott        selection += " AND " + RawContacts.DELETED + "=0";
144e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
145e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        final Cursor c = context.getContentResolver().query(RAW_CONTACTS_URI_LIMIT_1,
146e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng                ID_PROJECTION, selection, args, null);
147e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        if (c == null) return false;
148e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        try {
149e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            return c.moveToFirst();
150e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        } finally {
151e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            c.close();
152e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        }
153e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
154e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
1552ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner    public boolean equals(Object obj) {
1562ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        if (obj instanceof AccountWithDataSet) {
1572ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner            AccountWithDataSet other = (AccountWithDataSet) obj;
1582ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner            return Objects.equal(name, other.name)
1592ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner                    && Objects.equal(type, other.type)
1602ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner                    && Objects.equal(dataSet, other.dataSet);
1612ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        }
1622ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        return false;
163e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
164e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
165e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public int hashCode() {
1662ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        int result = 17;
1672ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        result = 31 * result + (name != null ? name.hashCode() : 0);
1682ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        result = 31 * result + (type != null ? type.hashCode() : 0);
1692ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        result = 31 * result + (dataSet != null ? dataSet.hashCode() : 0);
1702ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        return result;
171e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
172e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
173e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public String toString() {
174e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        return "AccountWithDataSet {name=" + name + ", type=" + type + ", dataSet=" + dataSet + "}";
175e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
176e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
177e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    private static StringBuilder addStringified(StringBuilder sb, AccountWithDataSet account) {
1782ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        if (!TextUtils.isEmpty(account.name)) sb.append(account.name);
179e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        sb.append(STRINGIFY_SEPARATOR);
1802ae200dc7b2995f6758887cce8dedf563b3f3aa3Jay Shrauner        if (!TextUtils.isEmpty(account.type)) sb.append(account.type);
181e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        sb.append(STRINGIFY_SEPARATOR);
182e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        if (!TextUtils.isEmpty(account.dataSet)) sb.append(account.dataSet);
183e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
184e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        return sb;
185e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
186e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
187e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    /**
188e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     * Pack the instance into a string.
189e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     */
190e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public String stringify() {
191e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        return addStringified(new StringBuilder(), this).toString();
192e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
193e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
194e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    /**
195a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott     * Returns a {@link ContentProviderOperation} that will create a RawContact in this account
196a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott     */
197a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott    public ContentProviderOperation newRawContactOperation() {
198a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott        final ContentProviderOperation.Builder builder =
199a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott                ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
200a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott                        .withValue(RawContacts.ACCOUNT_NAME, name)
201a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott                        .withValue(RawContacts.ACCOUNT_TYPE, type);
202a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott        if (dataSet != null) {
203a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott            builder.withValue(RawContacts.DATA_SET, dataSet);
204a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott        }
205a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott        return builder.build();
206a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott    }
207a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott
208a75206b1cba895ce629b9383e4fd0fef24049e7bMarcus Hagerott    /**
209e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     * Unpack a string created by {@link #stringify}.
210e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     *
211e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     * @throws IllegalArgumentException if it's an invalid string.
212e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     */
213e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public static AccountWithDataSet unstringify(String s) {
214e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        final String[] array = STRINGIFY_SEPARATOR_PAT.split(s, 3);
215e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        if (array.length < 3) {
216e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            throw new IllegalArgumentException("Invalid string " + s);
217e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        }
218e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        return new AccountWithDataSet(array[0], array[1],
219e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng                TextUtils.isEmpty(array[2]) ? null : array[2]);
220e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
221e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
222e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    /**
223e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     * Pack a list of {@link AccountWithDataSet} into a string.
224e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     */
225e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public static String stringifyList(List<AccountWithDataSet> accounts) {
226e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        final StringBuilder sb = new StringBuilder();
227e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
228e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        for (AccountWithDataSet account : accounts) {
229e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            if (sb.length() > 0) {
230e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng                sb.append(ARRAY_STRINGIFY_SEPARATOR);
231e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            }
232e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            addStringified(sb, account);
233e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        }
234e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
235e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        return sb.toString();
236e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
237e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
238e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    /**
239e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     * Unpack a list of {@link AccountWithDataSet} into a string.
240e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     *
241e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     * @throws IllegalArgumentException if it's an invalid string.
242e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng     */
243e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    public static List<AccountWithDataSet> unstringifyList(String s) {
244e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        final ArrayList<AccountWithDataSet> ret = Lists.newArrayList();
245e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        if (TextUtils.isEmpty(s)) {
246e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            return ret;
247e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        }
248e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
249e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        final String[] array = ARRAY_STRINGIFY_SEPARATOR_PAT.split(s);
250e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
251e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        for (int i = 0; i < array.length; i++) {
252e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng            ret.add(unstringify(array[i]));
253e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        }
254e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng
255e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng        return ret;
256e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng    }
257e88fcd3e82377aa3579ddf98389b6e20bae34c07Chiao Cheng}
258f0e140aec2f5832a517243084bea626011be9c39Marcus Hagerott
259