Home | History | Annotate | Download | only in model
      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.contacts.model;
     18 
     19 import com.android.contacts.R;
     20 import com.google.android.collect.Lists;
     21 
     22 import android.content.ContentValues;
     23 import android.content.Context;
     24 import android.content.res.Resources;
     25 import android.database.Cursor;
     26 import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
     27 import android.provider.ContactsContract.CommonDataKinds.Email;
     28 import android.provider.ContactsContract.CommonDataKinds.Event;
     29 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
     30 import android.provider.ContactsContract.CommonDataKinds.Im;
     31 import android.provider.ContactsContract.CommonDataKinds.Nickname;
     32 import android.provider.ContactsContract.CommonDataKinds.Note;
     33 import android.provider.ContactsContract.CommonDataKinds.Organization;
     34 import android.provider.ContactsContract.CommonDataKinds.Phone;
     35 import android.provider.ContactsContract.CommonDataKinds.Photo;
     36 import android.provider.ContactsContract.CommonDataKinds.Relation;
     37 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
     38 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
     39 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
     40 import android.provider.ContactsContract.CommonDataKinds.Website;
     41 import android.view.inputmethod.EditorInfo;
     42 
     43 public abstract class BaseAccountType extends AccountType {
     44     protected static final int FLAGS_PHONE = EditorInfo.TYPE_CLASS_PHONE;
     45     protected static final int FLAGS_EMAIL = EditorInfo.TYPE_CLASS_TEXT
     46             | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
     47     protected static final int FLAGS_PERSON_NAME = EditorInfo.TYPE_CLASS_TEXT
     48             | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME;
     49     protected static final int FLAGS_PHONETIC = EditorInfo.TYPE_CLASS_TEXT
     50             | EditorInfo.TYPE_TEXT_VARIATION_PHONETIC;
     51     protected static final int FLAGS_GENERIC_NAME = EditorInfo.TYPE_CLASS_TEXT
     52             | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
     53     protected static final int FLAGS_NOTE = EditorInfo.TYPE_CLASS_TEXT
     54             | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
     55     protected static final int FLAGS_EVENT = EditorInfo.TYPE_CLASS_TEXT;
     56     protected static final int FLAGS_WEBSITE = EditorInfo.TYPE_CLASS_TEXT
     57             | EditorInfo.TYPE_TEXT_VARIATION_URI;
     58     protected static final int FLAGS_POSTAL = EditorInfo.TYPE_CLASS_TEXT
     59             | EditorInfo.TYPE_TEXT_VARIATION_POSTAL_ADDRESS | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS
     60             | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
     61     protected static final int FLAGS_SIP_ADDRESS = EditorInfo.TYPE_CLASS_TEXT
     62             | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;  // since SIP addresses have the same
     63                                                              // basic format as email addresses
     64 
     65     public BaseAccountType() {
     66         this.accountType = null;
     67         this.dataSet = null;
     68         this.titleRes = R.string.account_phone;
     69         this.iconRes = R.mipmap.ic_launcher_contacts;
     70     }
     71 
     72     protected EditType buildPhoneType(int type) {
     73         return new EditType(type, Phone.getTypeLabelResource(type));
     74     }
     75 
     76     protected EditType buildEmailType(int type) {
     77         return new EditType(type, Email.getTypeLabelResource(type));
     78     }
     79 
     80     protected EditType buildPostalType(int type) {
     81         return new EditType(type, StructuredPostal.getTypeLabelResource(type));
     82     }
     83 
     84     protected EditType buildImType(int type) {
     85         return new EditType(type, Im.getProtocolLabelResource(type));
     86     }
     87 
     88     protected EditType buildEventType(int type, boolean yearOptional) {
     89         return new EventEditType(type, Event.getTypeResource(type)).setYearOptional(yearOptional);
     90     }
     91 
     92     protected EditType buildRelationType(int type) {
     93         return new EditType(type, Relation.getTypeLabelResource(type));
     94     }
     95 
     96     protected DataKind addDataKindStructuredName(Context context) {
     97         DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
     98                 R.string.nameLabelsGroup, -1, true, R.layout.structured_name_editor_view));
     99         kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
    100         kind.actionBody = new SimpleInflater(Nickname.NAME);
    101 
    102         kind.fieldList = Lists.newArrayList();
    103         kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME,
    104                 R.string.full_name, FLAGS_PERSON_NAME));
    105         kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
    106                 FLAGS_PERSON_NAME).setLongForm(true));
    107         kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
    108                 FLAGS_PERSON_NAME).setLongForm(true));
    109         kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
    110                 FLAGS_PERSON_NAME).setLongForm(true));
    111         kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
    112                 FLAGS_PERSON_NAME).setLongForm(true));
    113         kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
    114                 FLAGS_PERSON_NAME).setLongForm(true));
    115         kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
    116                 R.string.name_phonetic_family, FLAGS_PHONETIC));
    117         kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
    118                 R.string.name_phonetic_middle, FLAGS_PHONETIC));
    119         kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
    120                 R.string.name_phonetic_given, FLAGS_PHONETIC));
    121 
    122         return kind;
    123     }
    124 
    125     protected DataKind addDataKindDisplayName(Context context) {
    126         DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME,
    127                 R.string.nameLabelsGroup, -1, true, R.layout.text_fields_editor_view));
    128         kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
    129         kind.actionBody = new SimpleInflater(Nickname.NAME);
    130 
    131         kind.fieldList = Lists.newArrayList();
    132         kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME,
    133                 R.string.full_name, FLAGS_PERSON_NAME).setShortForm(true));
    134 
    135         boolean displayOrderPrimary =
    136                 context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
    137 
    138         if (!displayOrderPrimary) {
    139             kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
    140                     FLAGS_PERSON_NAME).setLongForm(true));
    141             kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
    142                     FLAGS_PERSON_NAME).setLongForm(true));
    143             kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
    144                     FLAGS_PERSON_NAME).setLongForm(true));
    145             kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
    146                     FLAGS_PERSON_NAME).setLongForm(true));
    147             kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
    148                     FLAGS_PERSON_NAME).setLongForm(true));
    149         } else {
    150             kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
    151                     FLAGS_PERSON_NAME).setLongForm(true));
    152             kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
    153                     FLAGS_PERSON_NAME).setLongForm(true));
    154             kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
    155                     FLAGS_PERSON_NAME).setLongForm(true));
    156             kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
    157                     FLAGS_PERSON_NAME).setLongForm(true));
    158             kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
    159                     FLAGS_PERSON_NAME).setLongForm(true));
    160         }
    161 
    162         return kind;
    163     }
    164 
    165     protected DataKind addDataKindPhoneticName(Context context) {
    166         DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME,
    167                 R.string.name_phonetic, -1, true, R.layout.phonetic_name_editor_view));
    168         kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
    169         kind.actionBody = new SimpleInflater(Nickname.NAME);
    170 
    171         kind.fieldList = Lists.newArrayList();
    172         kind.fieldList.add(new EditField(DataKind.PSEUDO_COLUMN_PHONETIC_NAME,
    173                 R.string.name_phonetic, FLAGS_PHONETIC).setShortForm(true));
    174         kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME,
    175                 R.string.name_phonetic_family, FLAGS_PHONETIC).setLongForm(true));
    176         kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME,
    177                 R.string.name_phonetic_middle, FLAGS_PHONETIC).setLongForm(true));
    178         kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME,
    179                 R.string.name_phonetic_given, FLAGS_PHONETIC).setLongForm(true));
    180 
    181         return kind;
    182     }
    183 
    184     protected DataKind addDataKindNickname(Context context) {
    185         DataKind kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE,
    186                     R.string.nicknameLabelsGroup, 115, true, R.layout.text_fields_editor_view));
    187         kind.typeOverallMax = 1;
    188         kind.actionHeader = new SimpleInflater(R.string.nicknameLabelsGroup);
    189         kind.actionBody = new SimpleInflater(Nickname.NAME);
    190         kind.defaultValues = new ContentValues();
    191         kind.defaultValues.put(Nickname.TYPE, Nickname.TYPE_DEFAULT);
    192 
    193         kind.fieldList = Lists.newArrayList();
    194         kind.fieldList.add(new EditField(Nickname.NAME, R.string.nicknameLabelsGroup,
    195                 FLAGS_PERSON_NAME));
    196 
    197         return kind;
    198     }
    199 
    200     protected DataKind addDataKindPhone(Context context) {
    201         DataKind kind = addKind(new DataKind(Phone.CONTENT_ITEM_TYPE, R.string.phoneLabelsGroup,
    202                 10, true, R.layout.text_fields_editor_view));
    203         kind.iconAltRes = R.drawable.ic_text_holo_light;
    204         kind.iconAltDescriptionRes = R.string.sms;
    205         kind.actionHeader = new PhoneActionInflater();
    206         kind.actionAltHeader = new PhoneActionAltInflater();
    207         kind.actionBody = new SimpleInflater(Phone.NUMBER);
    208         kind.typeColumn = Phone.TYPE;
    209         kind.typeList = Lists.newArrayList();
    210         kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));
    211         kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
    212         kind.typeList.add(buildPhoneType(Phone.TYPE_WORK));
    213         kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true));
    214         kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true));
    215         kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true));
    216         kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER));
    217         kind.typeList.add(
    218                 buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true).setCustomColumn(Phone.LABEL));
    219         kind.typeList.add(buildPhoneType(Phone.TYPE_CALLBACK).setSecondary(true));
    220         kind.typeList.add(buildPhoneType(Phone.TYPE_CAR).setSecondary(true));
    221         kind.typeList.add(buildPhoneType(Phone.TYPE_COMPANY_MAIN).setSecondary(true));
    222         kind.typeList.add(buildPhoneType(Phone.TYPE_ISDN).setSecondary(true));
    223         kind.typeList.add(buildPhoneType(Phone.TYPE_MAIN).setSecondary(true));
    224         kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER_FAX).setSecondary(true));
    225         kind.typeList.add(buildPhoneType(Phone.TYPE_RADIO).setSecondary(true));
    226         kind.typeList.add(buildPhoneType(Phone.TYPE_TELEX).setSecondary(true));
    227         kind.typeList.add(buildPhoneType(Phone.TYPE_TTY_TDD).setSecondary(true));
    228         kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_MOBILE).setSecondary(true));
    229         kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_PAGER).setSecondary(true));
    230         kind.typeList.add(buildPhoneType(Phone.TYPE_ASSISTANT).setSecondary(true).setCustomColumn(
    231                 Phone.LABEL));
    232         kind.typeList.add(buildPhoneType(Phone.TYPE_MMS).setSecondary(true));
    233 
    234         kind.fieldList = Lists.newArrayList();
    235         kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));
    236 
    237         return kind;
    238     }
    239 
    240     protected DataKind addDataKindEmail(Context context) {
    241         DataKind kind = addKind(new DataKind(Email.CONTENT_ITEM_TYPE, R.string.emailLabelsGroup,
    242                 15, true, R.layout.text_fields_editor_view));
    243         kind.actionHeader = new EmailActionInflater();
    244         kind.actionBody = new SimpleInflater(Email.DATA);
    245         kind.typeColumn = Email.TYPE;
    246         kind.typeList = Lists.newArrayList();
    247         kind.typeList.add(buildEmailType(Email.TYPE_HOME));
    248         kind.typeList.add(buildEmailType(Email.TYPE_WORK));
    249         kind.typeList.add(buildEmailType(Email.TYPE_OTHER));
    250         kind.typeList.add(buildEmailType(Email.TYPE_MOBILE));
    251         kind.typeList.add(
    252                 buildEmailType(Email.TYPE_CUSTOM).setSecondary(true).setCustomColumn(Email.LABEL));
    253 
    254         kind.fieldList = Lists.newArrayList();
    255         kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL));
    256 
    257         return kind;
    258     }
    259 
    260     protected DataKind addDataKindStructuredPostal(Context context) {
    261         DataKind kind = addKind(new DataKind(StructuredPostal.CONTENT_ITEM_TYPE,
    262                 R.string.postalLabelsGroup, 25, true, R.layout.text_fields_editor_view));
    263         kind.actionHeader = new PostalActionInflater();
    264         kind.actionBody = new SimpleInflater(StructuredPostal.FORMATTED_ADDRESS);
    265         kind.typeColumn = StructuredPostal.TYPE;
    266         kind.typeList = Lists.newArrayList();
    267         kind.typeList.add(buildPostalType(StructuredPostal.TYPE_HOME));
    268         kind.typeList.add(buildPostalType(StructuredPostal.TYPE_WORK));
    269         kind.typeList.add(buildPostalType(StructuredPostal.TYPE_OTHER));
    270         kind.typeList.add(buildPostalType(StructuredPostal.TYPE_CUSTOM).setSecondary(true)
    271                 .setCustomColumn(StructuredPostal.LABEL));
    272 
    273         kind.fieldList = Lists.newArrayList();
    274         kind.fieldList.add(
    275                 new EditField(StructuredPostal.FORMATTED_ADDRESS, R.string.postal_address,
    276                         FLAGS_POSTAL));
    277 
    278         return kind;
    279     }
    280 
    281     protected DataKind addDataKindIm(Context context) {
    282         DataKind kind = addKind(new DataKind(Im.CONTENT_ITEM_TYPE, R.string.imLabelsGroup, 20, true,
    283                     R.layout.text_fields_editor_view));
    284         kind.actionHeader = new ImActionInflater();
    285         kind.actionBody = new SimpleInflater(Im.DATA);
    286 
    287         // NOTE: even though a traditional "type" exists, for editing
    288         // purposes we're using the protocol to pick labels
    289 
    290         kind.defaultValues = new ContentValues();
    291         kind.defaultValues.put(Im.TYPE, Im.TYPE_OTHER);
    292 
    293         kind.typeColumn = Im.PROTOCOL;
    294         kind.typeList = Lists.newArrayList();
    295         kind.typeList.add(buildImType(Im.PROTOCOL_AIM));
    296         kind.typeList.add(buildImType(Im.PROTOCOL_MSN));
    297         kind.typeList.add(buildImType(Im.PROTOCOL_YAHOO));
    298         kind.typeList.add(buildImType(Im.PROTOCOL_SKYPE));
    299         kind.typeList.add(buildImType(Im.PROTOCOL_QQ));
    300         kind.typeList.add(buildImType(Im.PROTOCOL_GOOGLE_TALK));
    301         kind.typeList.add(buildImType(Im.PROTOCOL_ICQ));
    302         kind.typeList.add(buildImType(Im.PROTOCOL_JABBER));
    303         kind.typeList.add(buildImType(Im.PROTOCOL_CUSTOM).setSecondary(true).setCustomColumn(
    304                 Im.CUSTOM_PROTOCOL));
    305 
    306         kind.fieldList = Lists.newArrayList();
    307         kind.fieldList.add(new EditField(Im.DATA, R.string.imLabelsGroup, FLAGS_EMAIL));
    308 
    309         return kind;
    310     }
    311 
    312     protected DataKind addDataKindOrganization(Context context) {
    313         DataKind kind = addKind(new DataKind(Organization.CONTENT_ITEM_TYPE,
    314                     R.string.organizationLabelsGroup, 5, true,
    315                     R.layout.text_fields_editor_view));
    316         kind.actionHeader = new SimpleInflater(Organization.COMPANY);
    317         kind.actionBody = new SimpleInflater(Organization.TITLE);
    318         kind.typeOverallMax = 1;
    319 
    320         kind.fieldList = Lists.newArrayList();
    321         kind.fieldList.add(new EditField(Organization.COMPANY, R.string.ghostData_company,
    322                 FLAGS_GENERIC_NAME));
    323         kind.fieldList.add(new EditField(Organization.TITLE, R.string.ghostData_title,
    324                 FLAGS_GENERIC_NAME));
    325 
    326         return kind;
    327     }
    328 
    329     protected DataKind addDataKindPhoto(Context context) {
    330         DataKind kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, -1, true, -1));
    331         kind.fieldList = Lists.newArrayList();
    332         kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1));
    333         return kind;
    334     }
    335 
    336     protected DataKind addDataKindNote(Context context) {
    337         DataKind kind = addKind(new DataKind(Note.CONTENT_ITEM_TYPE,
    338                     R.string.label_notes, 110, true, R.layout.text_fields_editor_view));
    339         kind.typeOverallMax = 1;
    340         kind.actionHeader = new SimpleInflater(R.string.label_notes);
    341         kind.actionBody = new SimpleInflater(Note.NOTE);
    342         kind.fieldList = Lists.newArrayList();
    343         kind.fieldList.add(new EditField(Note.NOTE, R.string.label_notes, FLAGS_NOTE));
    344 
    345         return kind;
    346     }
    347 
    348     protected DataKind addDataKindWebsite(Context context) {
    349         DataKind kind = addKind(new DataKind(Website.CONTENT_ITEM_TYPE,
    350                 R.string.websiteLabelsGroup, 120, true, R.layout.text_fields_editor_view));
    351         kind.actionHeader = new SimpleInflater(R.string.websiteLabelsGroup);
    352         kind.actionBody = new SimpleInflater(Website.URL);
    353         kind.defaultValues = new ContentValues();
    354         kind.defaultValues.put(Website.TYPE, Website.TYPE_OTHER);
    355 
    356         kind.fieldList = Lists.newArrayList();
    357         kind.fieldList.add(new EditField(Website.URL, R.string.websiteLabelsGroup, FLAGS_WEBSITE));
    358 
    359         return kind;
    360     }
    361 
    362     protected DataKind addDataKindSipAddress(Context context) {
    363         // The icon specified here is the one that gets displayed for
    364         // "Internet call" items, in the "view contact" UI within the
    365         // Contacts app.
    366         //
    367         // This is independent of the "SIP call" icon that gets
    368         // displayed in the Quick Contacts widget, which comes from
    369         // the android:icon attribute of the SIP-related
    370         // intent-filters in the Phone app's manifest.
    371         DataKind kind = addKind(new DataKind(SipAddress.CONTENT_ITEM_TYPE,
    372                     R.string.label_sip_address, 130, true, R.layout.text_fields_editor_view));
    373 
    374         kind.typeOverallMax = 1;
    375         kind.actionHeader = new SimpleInflater(R.string.label_sip_address);
    376         kind.actionBody = new SimpleInflater(SipAddress.SIP_ADDRESS);
    377         kind.fieldList = Lists.newArrayList();
    378         kind.fieldList.add(new EditField(SipAddress.SIP_ADDRESS,
    379                                          R.string.label_sip_address, FLAGS_SIP_ADDRESS));
    380 
    381         return kind;
    382     }
    383 
    384     protected DataKind addDataKindGroupMembership(Context context) {
    385         DataKind kind = getKindForMimetype(GroupMembership.CONTENT_ITEM_TYPE);
    386         kind = addKind(new DataKind(GroupMembership.CONTENT_ITEM_TYPE,
    387                 R.string.groupsLabel, 999, true, -1));
    388 
    389         kind.typeOverallMax = 1;
    390         kind.fieldList = Lists.newArrayList();
    391         kind.fieldList.add(new EditField(GroupMembership.GROUP_ROW_ID, -1, -1));
    392 
    393         return kind;
    394     }
    395 
    396     /**
    397      * Simple inflater that assumes a string resource has a "%s" that will be
    398      * filled from the given column.
    399      */
    400     public static class SimpleInflater implements StringInflater {
    401         private final int mStringRes;
    402         private final String mColumnName;
    403 
    404         public SimpleInflater(int stringRes) {
    405             this(stringRes, null);
    406         }
    407 
    408         public SimpleInflater(String columnName) {
    409             this(-1, columnName);
    410         }
    411 
    412         public SimpleInflater(int stringRes, String columnName) {
    413             mStringRes = stringRes;
    414             mColumnName = columnName;
    415         }
    416 
    417         public CharSequence inflateUsing(Context context, Cursor cursor) {
    418             final int index = mColumnName != null ? cursor.getColumnIndex(mColumnName) : -1;
    419             final boolean validString = mStringRes > 0;
    420             final boolean validColumn = index != -1;
    421 
    422             final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
    423             final CharSequence columnValue = validColumn ? cursor.getString(index) : null;
    424 
    425             if (validString && validColumn) {
    426                 return String.format(stringValue.toString(), columnValue);
    427             } else if (validString) {
    428                 return stringValue;
    429             } else if (validColumn) {
    430                 return columnValue;
    431             } else {
    432                 return null;
    433             }
    434         }
    435 
    436         public CharSequence inflateUsing(Context context, ContentValues values) {
    437             final boolean validColumn = values.containsKey(mColumnName);
    438             final boolean validString = mStringRes > 0;
    439 
    440             final CharSequence stringValue = validString ? context.getText(mStringRes) : null;
    441             final CharSequence columnValue = validColumn ? values.getAsString(mColumnName) : null;
    442 
    443             if (validString && validColumn) {
    444                 return String.format(stringValue.toString(), columnValue);
    445             } else if (validString) {
    446                 return stringValue;
    447             } else if (validColumn) {
    448                 return columnValue;
    449             } else {
    450                 return null;
    451             }
    452         }
    453     }
    454 
    455     public static abstract class CommonInflater implements StringInflater {
    456         protected abstract int getTypeLabelResource(Integer type);
    457 
    458         protected boolean isCustom(Integer type) {
    459             return type == BaseTypes.TYPE_CUSTOM;
    460         }
    461 
    462         protected String getTypeColumn() {
    463             return Phone.TYPE;
    464         }
    465 
    466         protected String getLabelColumn() {
    467             return Phone.LABEL;
    468         }
    469 
    470         protected CharSequence getTypeLabel(Resources res, Integer type, CharSequence label) {
    471             final int labelRes = getTypeLabelResource(type);
    472             if (type == null) {
    473                 return res.getText(labelRes);
    474             } else if (isCustom(type)) {
    475                 return res.getString(labelRes, label == null ? "" : label);
    476             } else {
    477                 return res.getText(labelRes);
    478             }
    479         }
    480 
    481         public CharSequence inflateUsing(Context context, Cursor cursor) {
    482             final Integer type = cursor.getInt(cursor.getColumnIndex(getTypeColumn()));
    483             final String label = cursor.getString(cursor.getColumnIndex(getLabelColumn()));
    484             return getTypeLabel(context.getResources(), type, label);
    485         }
    486 
    487         public CharSequence inflateUsing(Context context, ContentValues values) {
    488             final Integer type = values.getAsInteger(getTypeColumn());
    489             final String label = values.getAsString(getLabelColumn());
    490             return getTypeLabel(context.getResources(), type, label);
    491         }
    492     }
    493 
    494     public static class PhoneActionInflater extends CommonInflater {
    495         @Override
    496         protected boolean isCustom(Integer type) {
    497             return type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT;
    498         }
    499 
    500         @Override
    501         protected int getTypeLabelResource(Integer type) {
    502             if (type == null) return R.string.call_other;
    503             switch (type) {
    504                 case Phone.TYPE_HOME: return R.string.call_home;
    505                 case Phone.TYPE_MOBILE: return R.string.call_mobile;
    506                 case Phone.TYPE_WORK: return R.string.call_work;
    507                 case Phone.TYPE_FAX_WORK: return R.string.call_fax_work;
    508                 case Phone.TYPE_FAX_HOME: return R.string.call_fax_home;
    509                 case Phone.TYPE_PAGER: return R.string.call_pager;
    510                 case Phone.TYPE_OTHER: return R.string.call_other;
    511                 case Phone.TYPE_CALLBACK: return R.string.call_callback;
    512                 case Phone.TYPE_CAR: return R.string.call_car;
    513                 case Phone.TYPE_COMPANY_MAIN: return R.string.call_company_main;
    514                 case Phone.TYPE_ISDN: return R.string.call_isdn;
    515                 case Phone.TYPE_MAIN: return R.string.call_main;
    516                 case Phone.TYPE_OTHER_FAX: return R.string.call_other_fax;
    517                 case Phone.TYPE_RADIO: return R.string.call_radio;
    518                 case Phone.TYPE_TELEX: return R.string.call_telex;
    519                 case Phone.TYPE_TTY_TDD: return R.string.call_tty_tdd;
    520                 case Phone.TYPE_WORK_MOBILE: return R.string.call_work_mobile;
    521                 case Phone.TYPE_WORK_PAGER: return R.string.call_work_pager;
    522                 case Phone.TYPE_ASSISTANT: return R.string.call_assistant;
    523                 case Phone.TYPE_MMS: return R.string.call_mms;
    524                 default: return R.string.call_custom;
    525             }
    526         }
    527     }
    528 
    529     public static class PhoneActionAltInflater extends CommonInflater {
    530         @Override
    531         protected boolean isCustom(Integer type) {
    532             return (type == Phone.TYPE_CUSTOM || type == Phone.TYPE_ASSISTANT);
    533         }
    534 
    535         @Override
    536         protected int getTypeLabelResource(Integer type) {
    537             if (type == null) return R.string.sms_other;
    538             switch (type) {
    539                 case Phone.TYPE_HOME: return R.string.sms_home;
    540                 case Phone.TYPE_MOBILE: return R.string.sms_mobile;
    541                 case Phone.TYPE_WORK: return R.string.sms_work;
    542                 case Phone.TYPE_FAX_WORK: return R.string.sms_fax_work;
    543                 case Phone.TYPE_FAX_HOME: return R.string.sms_fax_home;
    544                 case Phone.TYPE_PAGER: return R.string.sms_pager;
    545                 case Phone.TYPE_OTHER: return R.string.sms_other;
    546                 case Phone.TYPE_CALLBACK: return R.string.sms_callback;
    547                 case Phone.TYPE_CAR: return R.string.sms_car;
    548                 case Phone.TYPE_COMPANY_MAIN: return R.string.sms_company_main;
    549                 case Phone.TYPE_ISDN: return R.string.sms_isdn;
    550                 case Phone.TYPE_MAIN: return R.string.sms_main;
    551                 case Phone.TYPE_OTHER_FAX: return R.string.sms_other_fax;
    552                 case Phone.TYPE_RADIO: return R.string.sms_radio;
    553                 case Phone.TYPE_TELEX: return R.string.sms_telex;
    554                 case Phone.TYPE_TTY_TDD: return R.string.sms_tty_tdd;
    555                 case Phone.TYPE_WORK_MOBILE: return R.string.sms_work_mobile;
    556                 case Phone.TYPE_WORK_PAGER: return R.string.sms_work_pager;
    557                 case Phone.TYPE_ASSISTANT: return R.string.sms_assistant;
    558                 case Phone.TYPE_MMS: return R.string.sms_mms;
    559                 default: return R.string.sms_custom;
    560             }
    561         }
    562     }
    563 
    564     public static class EmailActionInflater extends CommonInflater {
    565         @Override
    566         protected int getTypeLabelResource(Integer type) {
    567             if (type == null) return R.string.email;
    568             switch (type) {
    569                 case Email.TYPE_HOME: return R.string.email_home;
    570                 case Email.TYPE_WORK: return R.string.email_work;
    571                 case Email.TYPE_OTHER: return R.string.email_other;
    572                 case Email.TYPE_MOBILE: return R.string.email_mobile;
    573                 default: return R.string.email_custom;
    574             }
    575         }
    576     }
    577 
    578     public static class EventActionInflater extends CommonInflater {
    579         @Override
    580         protected int getTypeLabelResource(Integer type) {
    581             return Event.getTypeResource(type);
    582         }
    583     }
    584 
    585     public static class RelationActionInflater extends CommonInflater {
    586         @Override
    587         protected int getTypeLabelResource(Integer type) {
    588             return Relation.getTypeLabelResource(type == null ? Relation.TYPE_CUSTOM : type);
    589         }
    590     }
    591 
    592     public static class PostalActionInflater extends CommonInflater {
    593         @Override
    594         protected int getTypeLabelResource(Integer type) {
    595             if (type == null) return R.string.map_other;
    596             switch (type) {
    597                 case StructuredPostal.TYPE_HOME: return R.string.map_home;
    598                 case StructuredPostal.TYPE_WORK: return R.string.map_work;
    599                 case StructuredPostal.TYPE_OTHER: return R.string.map_other;
    600                 default: return R.string.map_custom;
    601             }
    602         }
    603     }
    604 
    605     public static class ImActionInflater extends CommonInflater {
    606         @Override
    607         protected String getTypeColumn() {
    608             return Im.PROTOCOL;
    609         }
    610 
    611         @Override
    612         protected String getLabelColumn() {
    613             return Im.CUSTOM_PROTOCOL;
    614         }
    615 
    616         @Override
    617         protected int getTypeLabelResource(Integer type) {
    618             if (type == null) return R.string.chat;
    619             switch (type) {
    620                 case Im.PROTOCOL_AIM: return R.string.chat_aim;
    621                 case Im.PROTOCOL_MSN: return R.string.chat_msn;
    622                 case Im.PROTOCOL_YAHOO: return R.string.chat_yahoo;
    623                 case Im.PROTOCOL_SKYPE: return R.string.chat_skype;
    624                 case Im.PROTOCOL_QQ: return R.string.chat_qq;
    625                 case Im.PROTOCOL_GOOGLE_TALK: return R.string.chat_gtalk;
    626                 case Im.PROTOCOL_ICQ: return R.string.chat_icq;
    627                 case Im.PROTOCOL_JABBER: return R.string.chat_jabber;
    628                 case Im.PROTOCOL_NETMEETING: return R.string.chat;
    629                 default: return R.string.chat;
    630             }
    631         }
    632     }
    633 
    634     @Override
    635     public int getHeaderColor(Context context) {
    636         return 0xff7f93bc;
    637     }
    638 
    639     @Override
    640     public int getSideBarColor(Context context) {
    641         return 0xffbdc7b8;
    642     }
    643 
    644     @Override
    645     public boolean isGroupMembershipEditable() {
    646         return false;
    647     }
    648 }
    649