summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java')
-rw-r--r--src/com/android/messaging/datamodel/FrequentContactsCursorBuilder.java179
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;
- }
-}