/** * Returns a list of candidate contacts where the query is a prefix of the dialpad index of the * contact's name or phone number. * * @param query The prefix of a contact's dialpad index. * @return A list of top candidate contacts that will be suggested to user to match their input. */ public ArrayList<ContactNumber> getLooseMatches(String query, SmartDialNameMatcher nameMatcher) { final boolean inUpdate = sInUpdate.get(); if (inUpdate) { return Lists.newArrayList(); } final SQLiteDatabase db = getReadableDatabase(); /** Uses SQL query wildcard '%' to represent prefix matching. */ final String looseQuery = query + "%"; final ArrayList<ContactNumber> result = Lists.newArrayList(); final StopWatch stopWatch = DEBUG ? StopWatch.start(":Name Prefix query") : null; final String currentTimeStamp = Long.toString(System.currentTimeMillis()); /** Queries the database to find contacts that have an index matching the query prefix. */ final Cursor cursor = db.rawQuery( "SELECT " + SmartDialDbColumns.DATA_ID + ", " + SmartDialDbColumns.DISPLAY_NAME_PRIMARY + ", " + SmartDialDbColumns.PHOTO_ID + ", " + SmartDialDbColumns.NUMBER + ", " + SmartDialDbColumns.CONTACT_ID + ", " + SmartDialDbColumns.LOOKUP_KEY + " FROM " + Tables.SMARTDIAL_TABLE + " WHERE " + SmartDialDbColumns.CONTACT_ID + " IN " + " (SELECT " + PrefixColumns.CONTACT_ID + " FROM " + Tables.PREFIX_TABLE + " WHERE " + Tables.PREFIX_TABLE + "." + PrefixColumns.PREFIX + " LIKE '" + looseQuery + "')" + " ORDER BY " + SmartDialSortingOrder.SORT_ORDER, new String[] {currentTimeStamp}); if (DEBUG) { stopWatch.lap("Prefix query completed"); } /** Gets the column ID from the cursor. */ final int columnDataId = 0; final int columnDisplayNamePrimary = 1; final int columnPhotoId = 2; final int columnNumber = 3; final int columnId = 4; final int columnLookupKey = 5; if (DEBUG) { stopWatch.lap("Found column IDs"); } final Set<ContactMatch> duplicates = new HashSet<ContactMatch>(); int counter = 0; try { if (DEBUG) { stopWatch.lap("Moved cursor to start"); } /** Iterates the cursor to find top contact suggestions without duplication. */ while ((cursor.moveToNext()) && (counter < MAX_ENTRIES)) { final long dataID = cursor.getLong(columnDataId); final String displayName = cursor.getString(columnDisplayNamePrimary); final String phoneNumber = cursor.getString(columnNumber); final long id = cursor.getLong(columnId); final long photoId = cursor.getLong(columnPhotoId); final String lookupKey = cursor.getString(columnLookupKey); /** * If a contact already exists and another phone number of the contact is being processed, * skip the second instance. */ final ContactMatch contactMatch = new ContactMatch(lookupKey, id); if (duplicates.contains(contactMatch)) { continue; } /** * If the contact has either the name or number that matches the query, add to the result. */ final boolean nameMatches = nameMatcher.matches(displayName); final boolean numberMatches = (nameMatcher.matchesNumber(phoneNumber, query) != null); if (nameMatches || numberMatches) { /** If a contact has not been added, add it to the result and the hash set. */ duplicates.add(contactMatch); result.add(new ContactNumber(id, dataID, displayName, phoneNumber, lookupKey, photoId)); counter++; if (DEBUG) { stopWatch.lap("Added one result"); } } } if (DEBUG) { stopWatch.stopAndLog(TAG + "Finished loading cursor", 0); } } finally { cursor.close(); } return result; }