Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2011 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 package com.android.contacts.common.util;
     17 
     18 
     19 import android.content.ContentValues;
     20 import android.content.Context;
     21 import android.database.Cursor;
     22 import android.net.Uri;
     23 import android.net.Uri.Builder;
     24 import android.provider.ContactsContract;
     25 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
     26 import android.text.TextUtils;
     27 
     28 import com.android.contacts.common.model.dataitem.StructuredNameDataItem;
     29 
     30 import java.util.Map;
     31 import java.util.TreeMap;
     32 
     33 /**
     34  * Utility class for converting between a display name and structured name (and vice-versa), via
     35  * calls to the contact provider.
     36  */
     37 public class NameConverter {
     38 
     39     /**
     40      * The array of fields that comprise a structured name.
     41      */
     42     public static final String[] STRUCTURED_NAME_FIELDS = new String[] {
     43             StructuredName.PREFIX,
     44             StructuredName.GIVEN_NAME,
     45             StructuredName.MIDDLE_NAME,
     46             StructuredName.FAMILY_NAME,
     47             StructuredName.SUFFIX
     48     };
     49 
     50     /**
     51      * Converts the given structured name (provided as a map from {@link StructuredName} fields to
     52      * corresponding values) into a display name string.
     53      * <p>
     54      * Note that this operates via a call back to the ContactProvider, but it does not access the
     55      * database, so it should be safe to call from the UI thread.  See
     56      * ContactsProvider2.completeName() for the underlying method call.
     57      * @param context Activity context.
     58      * @param structuredName The structured name map to convert.
     59      * @return The display name computed from the structured name map.
     60      */
     61     public static String structuredNameToDisplayName(Context context,
     62             Map<String, String> structuredName) {
     63         Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
     64         for (String key : STRUCTURED_NAME_FIELDS) {
     65             if (structuredName.containsKey(key)) {
     66                 appendQueryParameter(builder, key, structuredName.get(key));
     67             }
     68         }
     69         return fetchDisplayName(context, builder.build());
     70     }
     71 
     72     /**
     73      * Converts the given structured name (provided as ContentValues) into a display name string.
     74      * @param context Activity context.
     75      * @param values The content values containing values comprising the structured name.
     76      * @return
     77      */
     78     public static String structuredNameToDisplayName(Context context, ContentValues values) {
     79         Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
     80         for (String key : STRUCTURED_NAME_FIELDS) {
     81             if (values.containsKey(key)) {
     82                 appendQueryParameter(builder, key, values.getAsString(key));
     83             }
     84         }
     85         return fetchDisplayName(context, builder.build());
     86     }
     87 
     88     /**
     89      * Helper method for fetching the display name via the given URI.
     90      */
     91     private static String fetchDisplayName(Context context, Uri uri) {
     92         String displayName = null;
     93         Cursor cursor = context.getContentResolver().query(uri, new String[]{
     94                 StructuredName.DISPLAY_NAME,
     95         }, null, null, null);
     96 
     97         if (cursor != null) {
     98             try {
     99                 if (cursor.moveToFirst()) {
    100                     displayName = cursor.getString(0);
    101                 }
    102             } finally {
    103                 cursor.close();
    104             }
    105         }
    106         return displayName;
    107     }
    108 
    109     /**
    110      * Converts the given display name string into a structured name (as a map from
    111      * {@link StructuredName} fields to corresponding values).
    112      * <p>
    113      * Note that this operates via a call back to the ContactProvider, but it does not access the
    114      * database, so it should be safe to call from the UI thread.
    115      * @param context Activity context.
    116      * @param displayName The display name to convert.
    117      * @return The structured name map computed from the display name.
    118      */
    119     public static Map<String, String> displayNameToStructuredName(Context context,
    120             String displayName) {
    121         Map<String, String> structuredName = new TreeMap<String, String>();
    122         Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
    123 
    124         appendQueryParameter(builder, StructuredName.DISPLAY_NAME, displayName);
    125         Cursor cursor = context.getContentResolver().query(builder.build(), STRUCTURED_NAME_FIELDS,
    126                 null, null, null);
    127 
    128         if (cursor != null) {
    129             try {
    130                 if (cursor.moveToFirst()) {
    131                     for (int i = 0; i < STRUCTURED_NAME_FIELDS.length; i++) {
    132                         structuredName.put(STRUCTURED_NAME_FIELDS[i], cursor.getString(i));
    133                     }
    134                 }
    135             } finally {
    136                 cursor.close();
    137             }
    138         }
    139         return structuredName;
    140     }
    141 
    142     /**
    143      * Converts the given display name string into a structured name (inserting the structured
    144      * values into a new or existing ContentValues object).
    145      * <p>
    146      * Note that this operates via a call back to the ContactProvider, but it does not access the
    147      * database, so it should be safe to call from the UI thread.
    148      * @param context Activity context.
    149      * @param displayName The display name to convert.
    150      * @param contentValues The content values object to place the structured name values into.  If
    151      *     null, a new one will be created and returned.
    152      * @return The ContentValues object containing the structured name fields derived from the
    153      *     display name.
    154      */
    155     public static ContentValues displayNameToStructuredName(Context context, String displayName,
    156             ContentValues contentValues) {
    157         if (contentValues == null) {
    158             contentValues = new ContentValues();
    159         }
    160         Map<String, String> mapValues = displayNameToStructuredName(context, displayName);
    161         for (String key : mapValues.keySet()) {
    162             contentValues.put(key, mapValues.get(key));
    163         }
    164         return contentValues;
    165     }
    166 
    167     private static void appendQueryParameter(Builder builder, String field, String value) {
    168         if (!TextUtils.isEmpty(value)) {
    169             builder.appendQueryParameter(field, value);
    170         }
    171     }
    172 
    173     /**
    174      * Parses phonetic name and returns parsed data (family, middle, given) as ContentValues.
    175      * Parsed data should be {@link StructuredName#PHONETIC_FAMILY_NAME},
    176      * {@link StructuredName#PHONETIC_MIDDLE_NAME}, and
    177      * {@link StructuredName#PHONETIC_GIVEN_NAME}.
    178      * If this method cannot parse given phoneticName, null values will be stored.
    179      *
    180      * @param phoneticName Phonetic name to be parsed
    181      * @param values ContentValues to be used for storing data. If null, new instance will be
    182      * created.
    183      * @return ContentValues with parsed data. Those data can be null.
    184      */
    185     public static StructuredNameDataItem parsePhoneticName(String phoneticName,
    186             StructuredNameDataItem item) {
    187         String family = null;
    188         String middle = null;
    189         String given = null;
    190 
    191         if (!TextUtils.isEmpty(phoneticName)) {
    192             String[] strings = phoneticName.split(" ", 3);
    193             switch (strings.length) {
    194                 case 1:
    195                     family = strings[0];
    196                     break;
    197                 case 2:
    198                     family = strings[0];
    199                     given = strings[1];
    200                     break;
    201                 case 3:
    202                     family = strings[0];
    203                     middle = strings[1];
    204                     given = strings[2];
    205                     break;
    206             }
    207         }
    208 
    209         if (item == null) {
    210             item = new StructuredNameDataItem();
    211         }
    212         item.setPhoneticFamilyName(family);
    213         item.setPhoneticMiddleName(middle);
    214         item.setPhoneticGivenName(given);
    215         return item;
    216     }
    217 
    218     /**
    219      * Constructs and returns a phonetic full name from given parts.
    220      */
    221     public static String buildPhoneticName(String family, String middle, String given) {
    222         if (!TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
    223                 || !TextUtils.isEmpty(given)) {
    224             StringBuilder sb = new StringBuilder();
    225             if (!TextUtils.isEmpty(family)) {
    226                 sb.append(family.trim()).append(' ');
    227             }
    228             if (!TextUtils.isEmpty(middle)) {
    229                 sb.append(middle.trim()).append(' ');
    230             }
    231             if (!TextUtils.isEmpty(given)) {
    232                 sb.append(given.trim()).append(' ');
    233             }
    234             sb.setLength(sb.length() - 1); // Yank the last space
    235             return sb.toString();
    236         } else {
    237             return null;
    238         }
    239     }
    240 }
    241