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