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.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 java.util.Map; 29 import java.util.TreeMap; 30 31 /** 32 * Utility class for converting between a display name and structured name (and vice-versa), via 33 * calls to the contact provider. 34 */ 35 public class NameConverter { 36 37 /** 38 * The array of fields that comprise a structured name. 39 */ 40 public static final String[] STRUCTURED_NAME_FIELDS = new String[] { 41 StructuredName.PREFIX, 42 StructuredName.GIVEN_NAME, 43 StructuredName.MIDDLE_NAME, 44 StructuredName.FAMILY_NAME, 45 StructuredName.SUFFIX 46 }; 47 48 /** 49 * Converts the given structured name (provided as a map from {@link StructuredName} fields to 50 * corresponding values) into a display name string. 51 * <p> 52 * Note that this operates via a call back to the ContactProvider, but it does not access the 53 * database, so it should be safe to call from the UI thread. See 54 * ContactsProvider2.completeName() for the underlying method call. 55 * @param context Activity context. 56 * @param structuredName The structured name map to convert. 57 * @return The display name computed from the structured name map. 58 */ 59 public static String structuredNameToDisplayName(Context context, 60 Map<String, String> structuredName) { 61 Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name"); 62 for (String key : STRUCTURED_NAME_FIELDS) { 63 if (structuredName.containsKey(key)) { 64 appendQueryParameter(builder, key, structuredName.get(key)); 65 } 66 } 67 return fetchDisplayName(context, builder.build()); 68 } 69 70 /** 71 * Converts the given structured name (provided as ContentValues) into a display name string. 72 * @param context Activity context. 73 * @param values The content values containing values comprising the structured name. 74 * @return 75 */ 76 public static String structuredNameToDisplayName(Context context, ContentValues values) { 77 Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name"); 78 for (String key : STRUCTURED_NAME_FIELDS) { 79 if (values.containsKey(key)) { 80 appendQueryParameter(builder, key, values.getAsString(key)); 81 } 82 } 83 return fetchDisplayName(context, builder.build()); 84 } 85 86 /** 87 * Helper method for fetching the display name via the given URI. 88 */ 89 private static String fetchDisplayName(Context context, Uri uri) { 90 String displayName = null; 91 Cursor cursor = context.getContentResolver().query(uri, new String[]{ 92 StructuredName.DISPLAY_NAME, 93 }, null, null, null); 94 95 try { 96 if (cursor.moveToFirst()) { 97 displayName = cursor.getString(0); 98 } 99 } finally { 100 cursor.close(); 101 } 102 return displayName; 103 } 104 105 /** 106 * Converts the given display name string into a structured name (as a map from 107 * {@link StructuredName} fields to corresponding values). 108 * <p> 109 * Note that this operates via a call back to the ContactProvider, but it does not access the 110 * database, so it should be safe to call from the UI thread. 111 * @param context Activity context. 112 * @param displayName The display name to convert. 113 * @return The structured name map computed from the display name. 114 */ 115 public static Map<String, String> displayNameToStructuredName(Context context, 116 String displayName) { 117 Map<String, String> structuredName = new TreeMap<String, String>(); 118 Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name"); 119 120 appendQueryParameter(builder, StructuredName.DISPLAY_NAME, displayName); 121 Cursor cursor = context.getContentResolver().query(builder.build(), STRUCTURED_NAME_FIELDS, 122 null, null, null); 123 124 try { 125 if (cursor.moveToFirst()) { 126 for (int i = 0; i < STRUCTURED_NAME_FIELDS.length; i++) { 127 structuredName.put(STRUCTURED_NAME_FIELDS[i], cursor.getString(i)); 128 } 129 } 130 } finally { 131 cursor.close(); 132 } 133 return structuredName; 134 } 135 136 /** 137 * Converts the given display name string into a structured name (inserting the structured 138 * values into a new or existing ContentValues object). 139 * <p> 140 * Note that this operates via a call back to the ContactProvider, but it does not access the 141 * database, so it should be safe to call from the UI thread. 142 * @param context Activity context. 143 * @param displayName The display name to convert. 144 * @param contentValues The content values object to place the structured name values into. If 145 * null, a new one will be created and returned. 146 * @return The ContentValues object containing the structured name fields derived from the 147 * display name. 148 */ 149 public static ContentValues displayNameToStructuredName(Context context, String displayName, 150 ContentValues contentValues) { 151 if (contentValues == null) { 152 contentValues = new ContentValues(); 153 } 154 Map<String, String> mapValues = displayNameToStructuredName(context, displayName); 155 for (String key : mapValues.keySet()) { 156 contentValues.put(key, mapValues.get(key)); 157 } 158 return contentValues; 159 } 160 161 private static void appendQueryParameter(Builder builder, String field, String value) { 162 if (!TextUtils.isEmpty(value)) { 163 builder.appendQueryParameter(field, value); 164 } 165 } 166 } 167