Home | History | Annotate | Download | only in list
      1 /*
      2  * Copyright (C) 2010 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.contacts.common.list;
     18 
     19 import android.content.SharedPreferences;
     20 import android.graphics.drawable.Drawable;
     21 import android.net.Uri;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 import android.provider.ContactsContract.RawContacts;
     25 import android.text.TextUtils;
     26 
     27 /**
     28  * Contact list filter parameters.
     29  */
     30 public final class ContactListFilter implements Comparable<ContactListFilter>, Parcelable {
     31 
     32     public static final int FILTER_TYPE_DEFAULT = -1;
     33     public static final int FILTER_TYPE_ALL_ACCOUNTS = -2;
     34     public static final int FILTER_TYPE_CUSTOM = -3;
     35     public static final int FILTER_TYPE_STARRED = -4;
     36     public static final int FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY = -5;
     37     public static final int FILTER_TYPE_SINGLE_CONTACT = -6;
     38 
     39     public static final int FILTER_TYPE_ACCOUNT = 0;
     40 
     41     /**
     42      * Obsolete filter which had been used in Honeycomb. This may be stored in
     43      * {@link SharedPreferences}, but should be replaced with ALL filter when it is found.
     44      *
     45      * TODO: "group" filter and relevant variables are all obsolete. Remove them.
     46      */
     47     private static final int FILTER_TYPE_GROUP = 1;
     48 
     49     private static final String KEY_FILTER_TYPE = "filter.type";
     50     private static final String KEY_ACCOUNT_NAME = "filter.accountName";
     51     private static final String KEY_ACCOUNT_TYPE = "filter.accountType";
     52     private static final String KEY_DATA_SET = "filter.dataSet";
     53 
     54     public final int filterType;
     55     public final String accountType;
     56     public final String accountName;
     57     public final String dataSet;
     58     public final Drawable icon;
     59     private String mId;
     60 
     61     public ContactListFilter(int filterType, String accountType, String accountName, String dataSet,
     62             Drawable icon) {
     63         this.filterType = filterType;
     64         this.accountType = accountType;
     65         this.accountName = accountName;
     66         this.dataSet = dataSet;
     67         this.icon = icon;
     68     }
     69 
     70     public static ContactListFilter createFilterWithType(int filterType) {
     71         return new ContactListFilter(filterType, null, null, null, null);
     72     }
     73 
     74     public static ContactListFilter createAccountFilter(String accountType, String accountName,
     75             String dataSet, Drawable icon) {
     76         return new ContactListFilter(ContactListFilter.FILTER_TYPE_ACCOUNT, accountType,
     77                 accountName, dataSet, icon);
     78     }
     79 
     80     /**
     81      * Returns true if this filter is based on data and may become invalid over time.
     82      */
     83     public boolean isValidationRequired() {
     84         return filterType == FILTER_TYPE_ACCOUNT;
     85     }
     86 
     87     @Override
     88     public String toString() {
     89         switch (filterType) {
     90             case FILTER_TYPE_DEFAULT:
     91                 return "default";
     92             case FILTER_TYPE_ALL_ACCOUNTS:
     93                 return "all_accounts";
     94             case FILTER_TYPE_CUSTOM:
     95                 return "custom";
     96             case FILTER_TYPE_STARRED:
     97                 return "starred";
     98             case FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY:
     99                 return "with_phones";
    100             case FILTER_TYPE_SINGLE_CONTACT:
    101                 return "single";
    102             case FILTER_TYPE_ACCOUNT:
    103                 return "account: " + accountType + (dataSet != null ? "/" + dataSet : "")
    104                         + " " + accountName;
    105         }
    106         return super.toString();
    107     }
    108 
    109     @Override
    110     public int compareTo(ContactListFilter another) {
    111         int res = accountName.compareTo(another.accountName);
    112         if (res != 0) {
    113             return res;
    114         }
    115 
    116         res = accountType.compareTo(another.accountType);
    117         if (res != 0) {
    118             return res;
    119         }
    120 
    121         return filterType - another.filterType;
    122     }
    123 
    124     @Override
    125     public int hashCode() {
    126         int code = filterType;
    127         if (accountType != null) {
    128             code = code * 31 + accountType.hashCode();
    129             code = code * 31 + accountName.hashCode();
    130         }
    131         if (dataSet != null) {
    132             code = code * 31 + dataSet.hashCode();
    133         }
    134         return code;
    135     }
    136 
    137     @Override
    138     public boolean equals(Object other) {
    139         if (this == other) {
    140             return true;
    141         }
    142 
    143         if (!(other instanceof ContactListFilter)) {
    144             return false;
    145         }
    146 
    147         ContactListFilter otherFilter = (ContactListFilter) other;
    148         if (filterType != otherFilter.filterType
    149                 || !TextUtils.equals(accountName, otherFilter.accountName)
    150                 || !TextUtils.equals(accountType, otherFilter.accountType)
    151                 || !TextUtils.equals(dataSet, otherFilter.dataSet)) {
    152             return false;
    153         }
    154 
    155         return true;
    156     }
    157 
    158     /**
    159      * Store the given {@link ContactListFilter} to preferences. If the requested filter is
    160      * of type {@link #FILTER_TYPE_SINGLE_CONTACT} then do not save it to preferences because
    161      * it is a temporary state.
    162      */
    163     public static void storeToPreferences(SharedPreferences prefs, ContactListFilter filter) {
    164         if (filter != null && filter.filterType == FILTER_TYPE_SINGLE_CONTACT) {
    165             return;
    166         }
    167         prefs.edit()
    168             .putInt(KEY_FILTER_TYPE, filter == null ? FILTER_TYPE_DEFAULT : filter.filterType)
    169             .putString(KEY_ACCOUNT_NAME, filter == null ? null : filter.accountName)
    170             .putString(KEY_ACCOUNT_TYPE, filter == null ? null : filter.accountType)
    171             .putString(KEY_DATA_SET, filter == null ? null : filter.dataSet)
    172             .apply();
    173     }
    174 
    175     /**
    176      * Try to obtain ContactListFilter object saved in SharedPreference.
    177      * If there's no info there, return ALL filter instead.
    178      */
    179     public static ContactListFilter restoreDefaultPreferences(SharedPreferences prefs) {
    180         ContactListFilter filter = restoreFromPreferences(prefs);
    181         if (filter == null) {
    182             filter = ContactListFilter.createFilterWithType(FILTER_TYPE_ALL_ACCOUNTS);
    183         }
    184         // "Group" filter is obsolete and thus is not exposed anymore. The "single contact mode"
    185         // should also not be stored in preferences anymore since it is a temporary state.
    186         if (filter.filterType == FILTER_TYPE_GROUP ||
    187                 filter.filterType == FILTER_TYPE_SINGLE_CONTACT) {
    188             filter = ContactListFilter.createFilterWithType(FILTER_TYPE_ALL_ACCOUNTS);
    189         }
    190         return filter;
    191     }
    192 
    193     private static ContactListFilter restoreFromPreferences(SharedPreferences prefs) {
    194         int filterType = prefs.getInt(KEY_FILTER_TYPE, FILTER_TYPE_DEFAULT);
    195         if (filterType == FILTER_TYPE_DEFAULT) {
    196             return null;
    197         }
    198 
    199         String accountName = prefs.getString(KEY_ACCOUNT_NAME, null);
    200         String accountType = prefs.getString(KEY_ACCOUNT_TYPE, null);
    201         String dataSet = prefs.getString(KEY_DATA_SET, null);
    202         return new ContactListFilter(filterType, accountType, accountName, dataSet, null);
    203     }
    204 
    205 
    206     @Override
    207     public void writeToParcel(Parcel dest, int flags) {
    208         dest.writeInt(filterType);
    209         dest.writeString(accountName);
    210         dest.writeString(accountType);
    211         dest.writeString(dataSet);
    212     }
    213 
    214     public static final Parcelable.Creator<ContactListFilter> CREATOR =
    215             new Parcelable.Creator<ContactListFilter>() {
    216         @Override
    217         public ContactListFilter createFromParcel(Parcel source) {
    218             int filterType = source.readInt();
    219             String accountName = source.readString();
    220             String accountType = source.readString();
    221             String dataSet = source.readString();
    222             return new ContactListFilter(filterType, accountType, accountName, dataSet, null);
    223         }
    224 
    225         @Override
    226         public ContactListFilter[] newArray(int size) {
    227             return new ContactListFilter[size];
    228         }
    229     };
    230 
    231     @Override
    232     public int describeContents() {
    233         return 0;
    234     }
    235 
    236     /**
    237      * Returns a string that can be used as a stable persistent identifier for this filter.
    238      */
    239     public String getId() {
    240         if (mId == null) {
    241             StringBuilder sb = new StringBuilder();
    242             sb.append(filterType);
    243             if (accountType != null) {
    244                 sb.append('-').append(accountType);
    245             }
    246             if (dataSet != null) {
    247                 sb.append('/').append(dataSet);
    248             }
    249             if (accountName != null) {
    250                 sb.append('-').append(accountName.replace('-', '_'));
    251             }
    252             mId = sb.toString();
    253         }
    254         return mId;
    255     }
    256 
    257     /**
    258      * Adds the account query parameters to the given {@code uriBuilder}.
    259      *
    260      * @throws IllegalStateException if the filter type is not {@link #FILTER_TYPE_ACCOUNT}.
    261      */
    262     public Uri.Builder addAccountQueryParameterToUrl(Uri.Builder uriBuilder) {
    263         if (filterType != FILTER_TYPE_ACCOUNT) {
    264             throw new IllegalStateException("filterType must be FILTER_TYPE_ACCOUNT");
    265         }
    266         uriBuilder.appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName);
    267         uriBuilder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType);
    268         if (!TextUtils.isEmpty(dataSet)) {
    269             uriBuilder.appendQueryParameter(RawContacts.DATA_SET, dataSet);
    270         }
    271         return uriBuilder;
    272     }
    273 
    274     public String toDebugString() {
    275         final StringBuilder builder = new StringBuilder();
    276         builder.append("[filter type: " + filterType + " (" + filterTypeToString(filterType) + ")");
    277         if (filterType == FILTER_TYPE_ACCOUNT) {
    278             builder.append(", accountType: " + accountType)
    279                     .append(", accountName: " + accountName)
    280                     .append(", dataSet: " + dataSet);
    281         }
    282         builder.append(", icon: " + icon + "]");
    283         return builder.toString();
    284     }
    285 
    286     public static final String filterTypeToString(int filterType) {
    287         switch (filterType) {
    288             case FILTER_TYPE_DEFAULT:
    289                 return "FILTER_TYPE_DEFAULT";
    290             case FILTER_TYPE_ALL_ACCOUNTS:
    291                 return "FILTER_TYPE_ALL_ACCOUNTS";
    292             case FILTER_TYPE_CUSTOM:
    293                 return "FILTER_TYPE_CUSTOM";
    294             case FILTER_TYPE_STARRED:
    295                 return "FILTER_TYPE_STARRED";
    296             case FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY:
    297                 return "FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY";
    298             case FILTER_TYPE_SINGLE_CONTACT:
    299                 return "FILTER_TYPE_SINGLE_CONTACT";
    300             case FILTER_TYPE_ACCOUNT:
    301                 return "FILTER_TYPE_ACCOUNT";
    302             default:
    303                 return "(unknown)";
    304         }
    305     }
    306 }
    307