diff options
Diffstat (limited to 'src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java')
-rw-r--r-- | src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java | 179 |
1 files changed, 0 insertions, 179 deletions
diff --git a/src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java b/src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java deleted file mode 100644 index 62483a0..0000000 --- a/src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.messaging.datamodel; - -import android.database.Cursor; -import android.database.MatrixCursor; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.support.v4.util.SimpleArrayMap; - -import com.android.messaging.util.Assert; -import com.android.messaging.util.ContactUtil; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -/** - * A cursor builder that takes the frequent contacts cursor and aggregate it with the all contacts - * cursor to fill in contact details such as phone numbers and strip away invalid contacts. - * - * Because the frequent contact list depends on the loading of two cursors, it needs to temporarily - * store the cursor that it receives with setFrequents() and setAllContacts() calls. Because it - * doesn't know which one will be finished first, it always checks whether both cursors are ready - * to pull data from and construct the aggregate cursor when it's ready to do so. Note that - * this cursor builder doesn't assume ownership of the cursors passed in - it merely references - * them and always does a isClosed() check before consuming them. The ownership still belongs to - * the loader framework and the cursor may be closed when the UI is torn down. - */ -public class FrequentContactsCursorBuilder { - private Cursor mAllContactsCursor; - private Cursor mFrequentContactsCursor; - - /** - * Sets the frequent contacts cursor as soon as it is loaded, or null if it's reset. - * @return this builder instance for chained operations - */ - public FrequentContactsCursorBuilder setFrequents(final Cursor frequentContactsCursor) { - mFrequentContactsCursor = frequentContactsCursor; - return this; - } - - /** - * Sets the all contacts cursor as soon as it is loaded, or null if it's reset. - * @return this builder instance for chained operations - */ - public FrequentContactsCursorBuilder setAllContacts(final Cursor allContactsCursor) { - mAllContactsCursor = allContactsCursor; - return this; - } - - /** - * Reset this builder. Must be called when the consumer resets its data. - */ - public void resetBuilder() { - mAllContactsCursor = null; - mFrequentContactsCursor = null; - } - - /** - * Attempt to build the cursor records from the frequent and all contacts cursor if they - * are both ready to be consumed. - * @return the frequent contact cursor if built successfully, or null if it can't be built yet. - */ - public Cursor build() { - if (mFrequentContactsCursor != null && mAllContactsCursor != null) { - Assert.isTrue(!mFrequentContactsCursor.isClosed()); - Assert.isTrue(!mAllContactsCursor.isClosed()); - - // Frequent contacts cursor has one record per contact, plus it doesn't contain info - // such as phone number and type. In order for the records to be usable by Bugle, we - // would like to populate it with information from the all contacts cursor. - final MatrixCursor retCursor = new MatrixCursor(ContactUtil.PhoneQuery.PROJECTION); - - // First, go through the frequents cursor and take note of all lookup keys and their - // corresponding rank in the frequents list. - final SimpleArrayMap<String, Integer> lookupKeyToRankMap = - new SimpleArrayMap<String, Integer>(); - int oldPosition = mFrequentContactsCursor.getPosition(); - int rank = 0; - mFrequentContactsCursor.moveToPosition(-1); - while (mFrequentContactsCursor.moveToNext()) { - final String lookupKey = mFrequentContactsCursor.getString( - ContactUtil.INDEX_LOOKUP_KEY_FREQUENT); - lookupKeyToRankMap.put(lookupKey, rank++); - } - mFrequentContactsCursor.moveToPosition(oldPosition); - - // Second, go through the all contacts cursor once and retrieve all information - // (multiple phone numbers etc.) and store that in an array list. Since the all - // contacts list only contains phone contacts, this step will ensure that we filter - // out any invalid/email contacts in the frequents list. - final ArrayList<Object[]> rows = - new ArrayList<Object[]>(mFrequentContactsCursor.getCount()); - oldPosition = mAllContactsCursor.getPosition(); - mAllContactsCursor.moveToPosition(-1); - while (mAllContactsCursor.moveToNext()) { - final String lookupKey = mAllContactsCursor.getString(ContactUtil.INDEX_LOOKUP_KEY); - if (lookupKeyToRankMap.containsKey(lookupKey)) { - final Object[] row = new Object[ContactUtil.PhoneQuery.PROJECTION.length]; - row[ContactUtil.INDEX_DATA_ID] = - mAllContactsCursor.getLong(ContactUtil.INDEX_DATA_ID); - row[ContactUtil.INDEX_CONTACT_ID] = - mAllContactsCursor.getLong(ContactUtil.INDEX_CONTACT_ID); - row[ContactUtil.INDEX_LOOKUP_KEY] = - mAllContactsCursor.getString(ContactUtil.INDEX_LOOKUP_KEY); - row[ContactUtil.INDEX_DISPLAY_NAME] = - mAllContactsCursor.getString(ContactUtil.INDEX_DISPLAY_NAME); - row[ContactUtil.INDEX_PHOTO_URI] = - mAllContactsCursor.getString(ContactUtil.INDEX_PHOTO_URI); - row[ContactUtil.INDEX_PHONE_EMAIL] = - mAllContactsCursor.getString(ContactUtil.INDEX_PHONE_EMAIL); - row[ContactUtil.INDEX_PHONE_EMAIL_TYPE] = - mAllContactsCursor.getInt(ContactUtil.INDEX_PHONE_EMAIL_TYPE); - row[ContactUtil.INDEX_PHONE_EMAIL_LABEL] = - mAllContactsCursor.getString(ContactUtil.INDEX_PHONE_EMAIL_LABEL); - rows.add(row); - } - } - mAllContactsCursor.moveToPosition(oldPosition); - - // Now we have a list of rows containing frequent contacts in alphabetical order. - // Therefore, sort all the rows according to their actual ranks in the frequents list. - Collections.sort(rows, new Comparator<Object[]>() { - @Override - public int compare(final Object[] lhs, final Object[] rhs) { - final String lookupKeyLhs = (String) lhs[ContactUtil.INDEX_LOOKUP_KEY]; - final String lookupKeyRhs = (String) rhs[ContactUtil.INDEX_LOOKUP_KEY]; - Assert.isTrue(lookupKeyToRankMap.containsKey(lookupKeyLhs) && - lookupKeyToRankMap.containsKey(lookupKeyRhs)); - final int rankLhs = lookupKeyToRankMap.get(lookupKeyLhs); - final int rankRhs = lookupKeyToRankMap.get(lookupKeyRhs); - if (rankLhs < rankRhs) { - return -1; - } else if (rankLhs > rankRhs) { - return 1; - } else { - // Same rank, so it's two contact records for the same contact. - // Perform secondary sorting on the phone type. Always place - // mobile before everything else. - final int phoneTypeLhs = (int) lhs[ContactUtil.INDEX_PHONE_EMAIL_TYPE]; - final int phoneTypeRhs = (int) rhs[ContactUtil.INDEX_PHONE_EMAIL_TYPE]; - if (phoneTypeLhs == Phone.TYPE_MOBILE && - phoneTypeRhs == Phone.TYPE_MOBILE) { - return 0; - } else if (phoneTypeLhs == Phone.TYPE_MOBILE) { - return -1; - } else if (phoneTypeRhs == Phone.TYPE_MOBILE) { - return 1; - } else { - // Use the default sort order, i.e. sort by phoneType value. - return phoneTypeLhs < phoneTypeRhs ? -1 : - (phoneTypeLhs == phoneTypeRhs ? 0 : 1); - } - } - } - }); - - // Finally, add all the rows to this cursor. - for (final Object[] row : rows) { - retCursor.addRow(row); - } - return retCursor; - } - return null; - } -} |