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 com.android.providers.contacts.SearchIndexManager.IndexBuilder; 19 20import android.content.ContentValues; 21import android.content.Context; 22import android.database.Cursor; 23import android.database.sqlite.SQLiteDatabase; 24import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; 25import android.text.TextUtils; 26 27/** 28 * Handler for postal address data rows. 29 */ 30public class DataRowHandlerForStructuredPostal extends DataRowHandler { 31 32 /** 33 * Specific list of structured fields. 34 */ 35 private final String[] STRUCTURED_FIELDS = new String[] { 36 StructuredPostal.STREET, 37 StructuredPostal.POBOX, 38 StructuredPostal.NEIGHBORHOOD, 39 StructuredPostal.CITY, 40 StructuredPostal.REGION, 41 StructuredPostal.POSTCODE, 42 StructuredPostal.COUNTRY, 43 }; 44 45 private final PostalSplitter mSplitter; 46 47 public DataRowHandlerForStructuredPostal(Context context, ContactsDatabaseHelper dbHelper, 48 ContactAggregator aggregator, PostalSplitter splitter) { 49 super(context, dbHelper, aggregator, StructuredPostal.CONTENT_ITEM_TYPE); 50 mSplitter = splitter; 51 } 52 53 @Override 54 public long insert(SQLiteDatabase db, TransactionContext txContext, long rawContactId, 55 ContentValues values) { 56 fixStructuredPostalComponents(values, values); 57 return super.insert(db, txContext, rawContactId, values); 58 } 59 60 @Override 61 public boolean update(SQLiteDatabase db, TransactionContext txContext, ContentValues values, 62 Cursor c, boolean callerIsSyncAdapter) { 63 final long dataId = c.getLong(DataUpdateQuery._ID); 64 final ContentValues augmented = getAugmentedValues(db, dataId, values); 65 if (augmented == null) { // No change 66 return false; 67 } 68 69 fixStructuredPostalComponents(augmented, values); 70 super.update(db, txContext, values, c, callerIsSyncAdapter); 71 return true; 72 } 73 74 /** 75 * Prepares the given {@link StructuredPostal} row, building 76 * {@link StructuredPostal#FORMATTED_ADDRESS} to match the structured 77 * values when missing. When structured components are missing, the 78 * unstructured value is assigned to {@link StructuredPostal#STREET}. 79 */ 80 private void fixStructuredPostalComponents(ContentValues augmented, ContentValues update) { 81 final String unstruct = update.getAsString(StructuredPostal.FORMATTED_ADDRESS); 82 83 final boolean touchedUnstruct = !TextUtils.isEmpty(unstruct); 84 final boolean touchedStruct = !areAllEmpty(update, STRUCTURED_FIELDS); 85 86 final PostalSplitter.Postal postal = new PostalSplitter.Postal(); 87 88 if (touchedUnstruct && !touchedStruct) { 89 mSplitter.split(postal, unstruct); 90 postal.toValues(update); 91 } else if (!touchedUnstruct 92 && (touchedStruct || areAnySpecified(update, STRUCTURED_FIELDS))) { 93 postal.fromValues(augmented); 94 final String joined = mSplitter.join(postal); 95 update.put(StructuredPostal.FORMATTED_ADDRESS, joined); 96 } 97 } 98 99 100 @Override 101 public boolean hasSearchableData() { 102 return true; 103 } 104 105 @Override 106 public boolean containsSearchableColumns(ContentValues values) { 107 return values.containsKey(StructuredPostal.FORMATTED_ADDRESS); 108 } 109 110 @Override 111 public void appendSearchableData(IndexBuilder builder) { 112 builder.appendContentFromColumn(StructuredPostal.FORMATTED_ADDRESS); 113 } 114} 115