15ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee/*
25ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Copyright (C) 2011 The Android Open Source Project
35ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *
45ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Licensed under the Apache License, Version 2.0 (the "License");
55ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * you may not use this file except in compliance with the License.
65ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * You may obtain a copy of the License at
75ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *
85ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *      http://www.apache.org/licenses/LICENSE-2.0
95ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *
105ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Unless required by applicable law or agreed to in writing, software
115ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * distributed under the License is distributed on an "AS IS" BASIS,
125ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * See the License for the specific language governing permissions and
145ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * limitations under the License.
155ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee */
165ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leepackage com.android.contacts.common.util;
175ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
185ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
195ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.content.ContentValues;
205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.content.Context;
215ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.database.Cursor;
225ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.net.Uri;
235ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.net.Uri.Builder;
245ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.provider.ContactsContract;
255ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
265ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.text.TextUtils;
275ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
285ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport com.android.contacts.common.model.dataitem.StructuredNameDataItem;
295ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
305ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport java.util.Map;
315ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport java.util.TreeMap;
325ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
335ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee/**
345ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Utility class for converting between a display name and structured name (and vice-versa), via
355ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * calls to the contact provider.
365ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee */
375ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leepublic class NameConverter {
385ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
395ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
405ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * The array of fields that comprise a structured name.
415ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
425ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static final String[] STRUCTURED_NAME_FIELDS = new String[] {
435ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            StructuredName.PREFIX,
445ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            StructuredName.GIVEN_NAME,
455ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            StructuredName.MIDDLE_NAME,
465ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            StructuredName.FAMILY_NAME,
475ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            StructuredName.SUFFIX
485ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    };
495ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
505ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
515ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Converts the given structured name (provided as a map from {@link StructuredName} fields to
525ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * corresponding values) into a display name string.
535ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * <p>
545ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Note that this operates via a call back to the ContactProvider, but it does not access the
555ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * database, so it should be safe to call from the UI thread.  See
565ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * ContactsProvider2.completeName() for the underlying method call.
575ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param context Activity context.
585ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param structuredName The structured name map to convert.
595ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @return The display name computed from the structured name map.
605ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
615ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static String structuredNameToDisplayName(Context context,
625ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            Map<String, String> structuredName) {
635ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
645ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        for (String key : STRUCTURED_NAME_FIELDS) {
655ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            if (structuredName.containsKey(key)) {
665ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                appendQueryParameter(builder, key, structuredName.get(key));
675ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            }
685ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
695ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return fetchDisplayName(context, builder.build());
705ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
715ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
725ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
735ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Converts the given structured name (provided as ContentValues) into a display name string.
745ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param context Activity context.
755ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param values The content values containing values comprising the structured name.
765ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @return
775ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
785ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static String structuredNameToDisplayName(Context context, ContentValues values) {
795ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
805ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        for (String key : STRUCTURED_NAME_FIELDS) {
815ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            if (values.containsKey(key)) {
825ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                appendQueryParameter(builder, key, values.getAsString(key));
835ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            }
845ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
855ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return fetchDisplayName(context, builder.build());
865ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
875ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
885ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
895ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Helper method for fetching the display name via the given URI.
905ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
915ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    private static String fetchDisplayName(Context context, Uri uri) {
925ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String displayName = null;
935ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        Cursor cursor = context.getContentResolver().query(uri, new String[]{
945ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                StructuredName.DISPLAY_NAME,
955ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }, null, null, null);
965ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
975ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        try {
985ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            if (cursor.moveToFirst()) {
995ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                displayName = cursor.getString(0);
1005ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            }
1015ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        } finally {
1025ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            cursor.close();
1035ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
1045ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return displayName;
1055ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1065ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1075ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
1085ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Converts the given display name string into a structured name (as a map from
1095ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * {@link StructuredName} fields to corresponding values).
1105ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * <p>
1115ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Note that this operates via a call back to the ContactProvider, but it does not access the
1125ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * database, so it should be safe to call from the UI thread.
1135ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param context Activity context.
1145ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param displayName The display name to convert.
1155ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @return The structured name map computed from the display name.
1165ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
1175ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static Map<String, String> displayNameToStructuredName(Context context,
1185ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            String displayName) {
1195ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        Map<String, String> structuredName = new TreeMap<String, String>();
1205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
1215ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1225ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        appendQueryParameter(builder, StructuredName.DISPLAY_NAME, displayName);
1235ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        Cursor cursor = context.getContentResolver().query(builder.build(), STRUCTURED_NAME_FIELDS,
1245ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                null, null, null);
1255ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1265ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        try {
1275ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            if (cursor.moveToFirst()) {
1285ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                for (int i = 0; i < STRUCTURED_NAME_FIELDS.length; i++) {
1295ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    structuredName.put(STRUCTURED_NAME_FIELDS[i], cursor.getString(i));
1305ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                }
1315ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            }
1325ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        } finally {
1335ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            cursor.close();
1345ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
1355ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return structuredName;
1365ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1375ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1385ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
1395ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Converts the given display name string into a structured name (inserting the structured
1405ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * values into a new or existing ContentValues object).
1415ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * <p>
1425ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Note that this operates via a call back to the ContactProvider, but it does not access the
1435ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * database, so it should be safe to call from the UI thread.
1445ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param context Activity context.
1455ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param displayName The display name to convert.
1465ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param contentValues The content values object to place the structured name values into.  If
1475ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     *     null, a new one will be created and returned.
1485ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @return The ContentValues object containing the structured name fields derived from the
1495ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     *     display name.
1505ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
1515ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static ContentValues displayNameToStructuredName(Context context, String displayName,
1525ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            ContentValues contentValues) {
1535ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        if (contentValues == null) {
1545ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            contentValues = new ContentValues();
1555ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
1565ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        Map<String, String> mapValues = displayNameToStructuredName(context, displayName);
1575ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        for (String key : mapValues.keySet()) {
1585ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            contentValues.put(key, mapValues.get(key));
1595ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
1605ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return contentValues;
1615ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1625ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1635ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    private static void appendQueryParameter(Builder builder, String field, String value) {
1645ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        if (!TextUtils.isEmpty(value)) {
1655ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            builder.appendQueryParameter(field, value);
1665ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
1675ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1685ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1695ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
1705ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Parses phonetic name and returns parsed data (family, middle, given) as ContentValues.
1715ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Parsed data should be {@link StructuredName#PHONETIC_FAMILY_NAME},
1725ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * {@link StructuredName#PHONETIC_MIDDLE_NAME}, and
1735ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * {@link StructuredName#PHONETIC_GIVEN_NAME}.
1745ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * If this method cannot parse given phoneticName, null values will be stored.
1755ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     *
1765ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param phoneticName Phonetic name to be parsed
1775ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @param values ContentValues to be used for storing data. If null, new instance will be
1785ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * created.
1795ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * @return ContentValues with parsed data. Those data can be null.
1805ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
1815ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static StructuredNameDataItem parsePhoneticName(String phoneticName,
1825ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            StructuredNameDataItem item) {
1835ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String family = null;
1845ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String middle = null;
1855ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        String given = null;
1865ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1875ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        if (!TextUtils.isEmpty(phoneticName)) {
1885ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            String[] strings = phoneticName.split(" ", 3);
1895ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            switch (strings.length) {
1905ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                case 1:
1915ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    family = strings[0];
1925ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    break;
1935ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                case 2:
1945ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    family = strings[0];
1955ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    given = strings[1];
1965ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    break;
1975ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                case 3:
1985ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    family = strings[0];
1995ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    middle = strings[1];
2005ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    given = strings[2];
2015ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                    break;
2025ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            }
2035ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2045ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2055ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        if (item == null) {
2065ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            item = new StructuredNameDataItem();
2075ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2085ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        item.setPhoneticFamilyName(family);
2095ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        item.setPhoneticMiddleName(middle);
2105ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        item.setPhoneticGivenName(given);
2115ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return item;
2125ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
2135ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2145ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
2155ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Constructs and returns a phonetic full name from given parts.
2165ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
2175ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static String buildPhoneticName(String family, String middle, String given) {
2185ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        if (!TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
2195ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                || !TextUtils.isEmpty(given)) {
2205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            StringBuilder sb = new StringBuilder();
2215ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            if (!TextUtils.isEmpty(family)) {
2225ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                sb.append(family.trim()).append(' ');
2235ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            }
2245ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            if (!TextUtils.isEmpty(middle)) {
2255ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                sb.append(middle.trim()).append(' ');
2265ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            }
2275ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            if (!TextUtils.isEmpty(given)) {
2285ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee                sb.append(given.trim()).append(' ');
2295ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            }
2305ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            sb.setLength(sb.length() - 1); // Yank the last space
2315ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            return sb.toString();
2325ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        } else {
2335ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            return null;
2345ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2355ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
2365ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee}
237