DataRowHandlerForStructuredName.java revision f6d4922f664127d0455b45b1f7444c4553581282
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License 15 */ 16package com.android.providers.contacts; 17 18import android.content.ContentValues; 19import android.database.Cursor; 20import android.database.sqlite.SQLiteDatabase; 21import android.provider.ContactsContract.CommonDataKinds.StructuredName; 22import android.provider.ContactsContract.FullNameStyle; 23import android.text.TextUtils; 24 25/** 26 * Handler for email address data rows. 27 */ 28public class DataRowHandlerForStructuredName extends DataRowHandler { 29 private final NameSplitter mSplitter; 30 private final NameLookupBuilder mNameLookupBuilder; 31 32 public DataRowHandlerForStructuredName(ContactsDatabaseHelper dbHelper, 33 ContactAggregator aggregator, NameSplitter splitter, 34 NameLookupBuilder nameLookupBuilder) { 35 super(dbHelper, aggregator, StructuredName.CONTENT_ITEM_TYPE); 36 mSplitter = splitter; 37 mNameLookupBuilder = nameLookupBuilder; 38 } 39 40 @Override 41 public long insert(SQLiteDatabase db, TransactionContext txContext, long rawContactId, 42 ContentValues values) { 43 fixStructuredNameComponents(values, values); 44 45 long dataId = super.insert(db, txContext, rawContactId, values); 46 47 String name = values.getAsString(StructuredName.DISPLAY_NAME); 48 Integer fullNameStyle = values.getAsInteger(StructuredName.FULL_NAME_STYLE); 49 mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name, 50 fullNameStyle != null 51 ? mSplitter.getAdjustedFullNameStyle(fullNameStyle) 52 : FullNameStyle.UNDEFINED); 53 insertNameLookupForPhoneticName(rawContactId, dataId, values); 54 fixRawContactDisplayName(db, txContext, rawContactId); 55 triggerAggregation(rawContactId); 56 return dataId; 57 } 58 59 @Override 60 public boolean update(SQLiteDatabase db, TransactionContext txContext, ContentValues values, 61 Cursor c, boolean callerIsSyncAdapter) { 62 final long dataId = c.getLong(DataUpdateQuery._ID); 63 final long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID); 64 65 final ContentValues augmented = getAugmentedValues(db, dataId, values); 66 if (augmented == null) { // No change 67 return false; 68 } 69 70 fixStructuredNameComponents(augmented, values); 71 72 super.update(db, txContext, values, c, callerIsSyncAdapter); 73 if (values.containsKey(StructuredName.DISPLAY_NAME) || 74 values.containsKey(StructuredName.PHONETIC_FAMILY_NAME) || 75 values.containsKey(StructuredName.PHONETIC_MIDDLE_NAME) || 76 values.containsKey(StructuredName.PHONETIC_GIVEN_NAME)) { 77 augmented.putAll(values); 78 String name = augmented.getAsString(StructuredName.DISPLAY_NAME); 79 mDbHelper.deleteNameLookup(dataId); 80 Integer fullNameStyle = augmented.getAsInteger(StructuredName.FULL_NAME_STYLE); 81 mNameLookupBuilder.insertNameLookup(rawContactId, dataId, name, 82 fullNameStyle != null 83 ? mSplitter.getAdjustedFullNameStyle(fullNameStyle) 84 : FullNameStyle.UNDEFINED); 85 insertNameLookupForPhoneticName(rawContactId, dataId, augmented); 86 } 87 fixRawContactDisplayName(db, txContext, rawContactId); 88 triggerAggregation(rawContactId); 89 return true; 90 } 91 92 @Override 93 public int delete(SQLiteDatabase db, TransactionContext txContext, Cursor c) { 94 long dataId = c.getLong(DataDeleteQuery._ID); 95 long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID); 96 97 int count = super.delete(db, txContext, c); 98 99 mDbHelper.deleteNameLookup(dataId); 100 fixRawContactDisplayName(db, txContext, rawContactId); 101 triggerAggregation(rawContactId); 102 return count; 103 } 104 105 /** 106 * Specific list of structured fields. 107 */ 108 private final String[] STRUCTURED_FIELDS = new String[] { 109 StructuredName.PREFIX, StructuredName.GIVEN_NAME, StructuredName.MIDDLE_NAME, 110 StructuredName.FAMILY_NAME, StructuredName.SUFFIX 111 }; 112 113 /** 114 * Parses the supplied display name, but only if the incoming values do 115 * not already contain structured name parts. Also, if the display name 116 * is not provided, generate one by concatenating first name and last 117 * name. 118 */ 119 public void fixStructuredNameComponents(ContentValues augmented, ContentValues update) { 120 final String unstruct = update.getAsString(StructuredName.DISPLAY_NAME); 121 122 final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 123 final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 124 125 if (touchedUnstruct && !touchedStruct) { 126 NameSplitter.Name name = new NameSplitter.Name(); 127 mSplitter.split(name, unstruct); 128 name.toValues(update); 129 } else if (!touchedUnstruct 130 && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 131 // We need to update the display name when any structured components 132 // are specified, even when they are null, which is why we are checking 133 // areAnySpecified. The touchedStruct in the condition is an optimization: 134 // if there are non-null values, we know for a fact that some values are present. 135 NameSplitter.Name name = new NameSplitter.Name(); 136 name.fromValues(augmented); 137 // As the name could be changed, let's guess the name style again. 138 name.fullNameStyle = FullNameStyle.UNDEFINED; 139 mSplitter.guessNameStyle(name); 140 int unadjustedFullNameStyle = name.fullNameStyle; 141 name.fullNameStyle = mSplitter.getAdjustedFullNameStyle(name.fullNameStyle); 142 final String joined = mSplitter.join(name, true); 143 update.put(StructuredName.DISPLAY_NAME, joined); 144 145 update.put(StructuredName.FULL_NAME_STYLE, unadjustedFullNameStyle); 146 update.put(StructuredName.PHONETIC_NAME_STYLE, name.phoneticNameStyle); 147 } else if (touchedUnstruct && touchedStruct){ 148 if (!update.containsKey(StructuredName.FULL_NAME_STYLE)) { 149 update.put(StructuredName.FULL_NAME_STYLE, 150 mSplitter.guessFullNameStyle(unstruct)); 151 } 152 if (!update.containsKey(StructuredName.PHONETIC_NAME_STYLE)) { 153 update.put(StructuredName.PHONETIC_NAME_STYLE, 154 mSplitter.guessPhoneticNameStyle(unstruct)); 155 } 156 } 157 } 158 159 public void insertNameLookupForPhoneticName(long rawContactId, long dataId, 160 ContentValues values) { 161 if (values.containsKey(StructuredName.PHONETIC_FAMILY_NAME) 162 || values.containsKey(StructuredName.PHONETIC_GIVEN_NAME) 163 || values.containsKey(StructuredName.PHONETIC_MIDDLE_NAME)) { 164 mDbHelper.insertNameLookupForPhoneticName(rawContactId, dataId, 165 values.getAsString(StructuredName.PHONETIC_FAMILY_NAME), 166 values.getAsString(StructuredName.PHONETIC_MIDDLE_NAME), 167 values.getAsString(StructuredName.PHONETIC_GIVEN_NAME)); 168 } 169 } 170} 171