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