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 */
16package com.android.contacts.util;
17
18
19import android.content.ContentValues;
20import android.content.Context;
21import android.database.Cursor;
22import android.net.Uri;
23import android.net.Uri.Builder;
24import android.provider.ContactsContract;
25import android.provider.ContactsContract.CommonDataKinds.StructuredName;
26import android.text.TextUtils;
27
28import java.util.Map;
29import 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 */
35public 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