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