1c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang/* 2c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * Copyright (C) 2009 Google Inc. 3c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * 4c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * Licensed under the Apache License, Version 2.0 (the "License"); 5c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * you may not use this file except in compliance with the License. 6c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * You may obtain a copy of the License at 7c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * 8c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * http://www.apache.org/licenses/LICENSE-2.0 9c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * 10c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * Unless required by applicable law or agreed to in writing, software 11c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * distributed under the License is distributed on an "AS IS" BASIS, 12c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * See the License for the specific language governing permissions and 14c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang * limitations under the License. 15c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang */ 16c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang 17c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huangpackage com.android.mms; 18c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang 19f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport java.util.ArrayList; 20f114492537753bc68640d4a0d403861387296bcbMark Wagner 21f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.app.SearchManager; 22f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.content.ContentResolver; 23f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.content.ContentValues; 24f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.content.Intent; 25f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.database.CharArrayBuffer; 26f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.database.ContentObserver; 27f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.database.CrossProcessCursor; 28f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.database.Cursor; 29f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.database.CursorWindow; 30f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.database.DataSetObserver; 31627ffa0f154c4ed9ac5071af5f5fb2903234665eMark Wagnerimport android.database.sqlite.SQLiteException; 32f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.net.Uri; 33f114492537753bc68640d4a0d403861387296bcbMark Wagnerimport android.os.Bundle; 34c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagnerimport android.text.TextUtils; 35c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang 36c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang/** 37f114492537753bc68640d4a0d403861387296bcbMark Wagner * Suggestions provider for mms. Queries the "words" table to provide possible word suggestions. 38c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang */ 39f114492537753bc68640d4a0d403861387296bcbMark Wagnerpublic class SuggestionsProvider extends android.content.ContentProvider { 40c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang 41c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang final static String AUTHORITY = "com.android.mms.SuggestionsProvider"; 42f114492537753bc68640d4a0d403861387296bcbMark Wagner// final static int MODE = DATABASE_MODE_QUERIES + DATABASE_MODE_2LINES; 43c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang 44c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang public SuggestionsProvider() { 45c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang super(); 46f114492537753bc68640d4a0d403861387296bcbMark Wagner } 47f114492537753bc68640d4a0d403861387296bcbMark Wagner 48f114492537753bc68640d4a0d403861387296bcbMark Wagner @Override 49f114492537753bc68640d4a0d403861387296bcbMark Wagner public int delete(Uri uri, String selection, String[] selectionArgs) { 50f114492537753bc68640d4a0d403861387296bcbMark Wagner return 0; 51f114492537753bc68640d4a0d403861387296bcbMark Wagner } 52f114492537753bc68640d4a0d403861387296bcbMark Wagner 53f114492537753bc68640d4a0d403861387296bcbMark Wagner @Override 54f114492537753bc68640d4a0d403861387296bcbMark Wagner public String getType(Uri uri) { 55f114492537753bc68640d4a0d403861387296bcbMark Wagner return null; 56f114492537753bc68640d4a0d403861387296bcbMark Wagner } 57f114492537753bc68640d4a0d403861387296bcbMark Wagner 58f114492537753bc68640d4a0d403861387296bcbMark Wagner @Override 59f114492537753bc68640d4a0d403861387296bcbMark Wagner public Uri insert(Uri uri, ContentValues values) { 60f114492537753bc68640d4a0d403861387296bcbMark Wagner return null; 61f114492537753bc68640d4a0d403861387296bcbMark Wagner } 62f114492537753bc68640d4a0d403861387296bcbMark Wagner 63f114492537753bc68640d4a0d403861387296bcbMark Wagner @Override 64f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean onCreate() { 65f114492537753bc68640d4a0d403861387296bcbMark Wagner return true; 66f114492537753bc68640d4a0d403861387296bcbMark Wagner } 67f114492537753bc68640d4a0d403861387296bcbMark Wagner 68f114492537753bc68640d4a0d403861387296bcbMark Wagner @Override 69f114492537753bc68640d4a0d403861387296bcbMark Wagner public Cursor query(Uri uri, String[] projection, String selection, 70f114492537753bc68640d4a0d403861387296bcbMark Wagner String[] selectionArgs, String sortOrder) { 71f114492537753bc68640d4a0d403861387296bcbMark Wagner Uri u = Uri.parse(String.format( 72f114492537753bc68640d4a0d403861387296bcbMark Wagner "content://mms-sms/searchSuggest?pattern=%s", 73f114492537753bc68640d4a0d403861387296bcbMark Wagner selectionArgs[0])); 74f114492537753bc68640d4a0d403861387296bcbMark Wagner Cursor c = getContext().getContentResolver().query( 75f114492537753bc68640d4a0d403861387296bcbMark Wagner u, 76f114492537753bc68640d4a0d403861387296bcbMark Wagner null, 77f114492537753bc68640d4a0d403861387296bcbMark Wagner null, 78f114492537753bc68640d4a0d403861387296bcbMark Wagner null, 79f114492537753bc68640d4a0d403861387296bcbMark Wagner null); 80f114492537753bc68640d4a0d403861387296bcbMark Wagner 81f114492537753bc68640d4a0d403861387296bcbMark Wagner return new SuggestionsCursor(c, selectionArgs[0]); 82f114492537753bc68640d4a0d403861387296bcbMark Wagner } 83f114492537753bc68640d4a0d403861387296bcbMark Wagner 84f114492537753bc68640d4a0d403861387296bcbMark Wagner @Override 85f114492537753bc68640d4a0d403861387296bcbMark Wagner public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 86f114492537753bc68640d4a0d403861387296bcbMark Wagner return 0; 87f114492537753bc68640d4a0d403861387296bcbMark Wagner } 88f114492537753bc68640d4a0d403861387296bcbMark Wagner 89f114492537753bc68640d4a0d403861387296bcbMark Wagner private class SuggestionsCursor implements CrossProcessCursor { 90f114492537753bc68640d4a0d403861387296bcbMark Wagner Cursor mDatabaseCursor; 91f114492537753bc68640d4a0d403861387296bcbMark Wagner int mColumnCount; 92f114492537753bc68640d4a0d403861387296bcbMark Wagner int mCurrentRow; 93f114492537753bc68640d4a0d403861387296bcbMark Wagner ArrayList<Row> mRows = new ArrayList<Row>(); 94c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner String mQuery; 95f114492537753bc68640d4a0d403861387296bcbMark Wagner 96f114492537753bc68640d4a0d403861387296bcbMark Wagner public SuggestionsCursor(Cursor cursor, String query) { 97f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor = cursor; 98c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner mQuery = query; 99f114492537753bc68640d4a0d403861387296bcbMark Wagner 100f114492537753bc68640d4a0d403861387296bcbMark Wagner mColumnCount = cursor.getColumnCount(); 101627ffa0f154c4ed9ac5071af5f5fb2903234665eMark Wagner try { 102627ffa0f154c4ed9ac5071af5f5fb2903234665eMark Wagner computeRows(); 103627ffa0f154c4ed9ac5071af5f5fb2903234665eMark Wagner } catch (SQLiteException ex) { 104627ffa0f154c4ed9ac5071af5f5fb2903234665eMark Wagner // This can happen if the user enters -n (anything starting with -). 105627ffa0f154c4ed9ac5071af5f5fb2903234665eMark Wagner // sqlite3/fts3 can't handle it. Google for "logic error or missing database fts3" 106627ffa0f154c4ed9ac5071af5f5fb2903234665eMark Wagner // for commentary on it. 107627ffa0f154c4ed9ac5071af5f5fb2903234665eMark Wagner mRows.clear(); // assume no results 108627ffa0f154c4ed9ac5071af5f5fb2903234665eMark Wagner } 109f114492537753bc68640d4a0d403861387296bcbMark Wagner } 110f114492537753bc68640d4a0d403861387296bcbMark Wagner 111f114492537753bc68640d4a0d403861387296bcbMark Wagner public int getCount() { 112f114492537753bc68640d4a0d403861387296bcbMark Wagner return mRows.size(); 113f114492537753bc68640d4a0d403861387296bcbMark Wagner } 114f114492537753bc68640d4a0d403861387296bcbMark Wagner 115f114492537753bc68640d4a0d403861387296bcbMark Wagner private class Row { 116c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner private String mSnippet; 117c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner private int mRowNumber; 118c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner 119c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner public Row(int row, String snippet) { 120c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner mSnippet = snippet.trim(); 121f114492537753bc68640d4a0d403861387296bcbMark Wagner mRowNumber = row; 122f114492537753bc68640d4a0d403861387296bcbMark Wagner } 123c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner public String getSnippet() { 124c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner return mSnippet; 125f114492537753bc68640d4a0d403861387296bcbMark Wagner } 126f114492537753bc68640d4a0d403861387296bcbMark Wagner } 127f114492537753bc68640d4a0d403861387296bcbMark Wagner 128c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner /* 129c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner * Compute rows for rows in the cursor. The cursor can contain duplicates which 130c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner * are filtered out in the while loop. Using DISTINCT on the result of the 131c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner * FTS3 snippet function does not work so we do it here in the code. 132c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner */ 133f114492537753bc68640d4a0d403861387296bcbMark Wagner private void computeRows() { 134c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner int snippetColumn = mDatabaseCursor.getColumnIndex("snippet"); 135f114492537753bc68640d4a0d403861387296bcbMark Wagner 136f114492537753bc68640d4a0d403861387296bcbMark Wagner int count = mDatabaseCursor.getCount(); 137c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner String previousSnippet = null; 138c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner 139f114492537753bc68640d4a0d403861387296bcbMark Wagner for (int i = 0; i < count; i++) { 140f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.moveToPosition(i); 141c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner String snippet = mDatabaseCursor.getString(snippetColumn); 142c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner if (!TextUtils.equals(previousSnippet, snippet)) { 143c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner mRows.add(new Row(i, snippet)); 144c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner previousSnippet = snippet; 145c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner } 146f114492537753bc68640d4a0d403861387296bcbMark Wagner } 147f114492537753bc68640d4a0d403861387296bcbMark Wagner } 148f114492537753bc68640d4a0d403861387296bcbMark Wagner 149f114492537753bc68640d4a0d403861387296bcbMark Wagner private int [] computeOffsets(String offsetsString) { 150f114492537753bc68640d4a0d403861387296bcbMark Wagner String [] vals = offsetsString.split(" "); 151f114492537753bc68640d4a0d403861387296bcbMark Wagner 152f114492537753bc68640d4a0d403861387296bcbMark Wagner int [] retvals = new int[vals.length]; 153f114492537753bc68640d4a0d403861387296bcbMark Wagner for (int i = retvals.length-1; i >= 0; i--) { 154f114492537753bc68640d4a0d403861387296bcbMark Wagner retvals[i] = Integer.parseInt(vals[i]); 155f114492537753bc68640d4a0d403861387296bcbMark Wagner } 156f114492537753bc68640d4a0d403861387296bcbMark Wagner return retvals; 157f114492537753bc68640d4a0d403861387296bcbMark Wagner } 158f114492537753bc68640d4a0d403861387296bcbMark Wagner 159f114492537753bc68640d4a0d403861387296bcbMark Wagner public void fillWindow(int position, CursorWindow window) { 160f114492537753bc68640d4a0d403861387296bcbMark Wagner int count = getCount(); 161f114492537753bc68640d4a0d403861387296bcbMark Wagner if (position < 0 || position > count + 1) { 162f114492537753bc68640d4a0d403861387296bcbMark Wagner return; 163f114492537753bc68640d4a0d403861387296bcbMark Wagner } 164f114492537753bc68640d4a0d403861387296bcbMark Wagner window.acquireReference(); 165f114492537753bc68640d4a0d403861387296bcbMark Wagner try { 166f114492537753bc68640d4a0d403861387296bcbMark Wagner int oldpos = getPosition(); 167f114492537753bc68640d4a0d403861387296bcbMark Wagner int pos = position; 168f114492537753bc68640d4a0d403861387296bcbMark Wagner window.clear(); 169f114492537753bc68640d4a0d403861387296bcbMark Wagner window.setStartPosition(position); 170f114492537753bc68640d4a0d403861387296bcbMark Wagner int columnNum = getColumnCount(); 171f114492537753bc68640d4a0d403861387296bcbMark Wagner window.setNumColumns(columnNum); 172f114492537753bc68640d4a0d403861387296bcbMark Wagner while (moveToPosition(pos) && window.allocRow()) { 173f114492537753bc68640d4a0d403861387296bcbMark Wagner for (int i = 0; i < columnNum; i++) { 174f114492537753bc68640d4a0d403861387296bcbMark Wagner String field = getString(i); 175f114492537753bc68640d4a0d403861387296bcbMark Wagner if (field != null) { 176f114492537753bc68640d4a0d403861387296bcbMark Wagner if (!window.putString(field, pos, i)) { 177f114492537753bc68640d4a0d403861387296bcbMark Wagner window.freeLastRow(); 178f114492537753bc68640d4a0d403861387296bcbMark Wagner break; 179f114492537753bc68640d4a0d403861387296bcbMark Wagner } 180f114492537753bc68640d4a0d403861387296bcbMark Wagner } else { 181f114492537753bc68640d4a0d403861387296bcbMark Wagner if (!window.putNull(pos, i)) { 182f114492537753bc68640d4a0d403861387296bcbMark Wagner window.freeLastRow(); 183f114492537753bc68640d4a0d403861387296bcbMark Wagner break; 184f114492537753bc68640d4a0d403861387296bcbMark Wagner } 185f114492537753bc68640d4a0d403861387296bcbMark Wagner } 186f114492537753bc68640d4a0d403861387296bcbMark Wagner } 187f114492537753bc68640d4a0d403861387296bcbMark Wagner ++pos; 188f114492537753bc68640d4a0d403861387296bcbMark Wagner } 189f114492537753bc68640d4a0d403861387296bcbMark Wagner moveToPosition(oldpos); 190f114492537753bc68640d4a0d403861387296bcbMark Wagner } catch (IllegalStateException e){ 191f114492537753bc68640d4a0d403861387296bcbMark Wagner // simply ignore it 192f114492537753bc68640d4a0d403861387296bcbMark Wagner } finally { 193f114492537753bc68640d4a0d403861387296bcbMark Wagner window.releaseReference(); 194f114492537753bc68640d4a0d403861387296bcbMark Wagner } 195f114492537753bc68640d4a0d403861387296bcbMark Wagner } 196f114492537753bc68640d4a0d403861387296bcbMark Wagner 197f114492537753bc68640d4a0d403861387296bcbMark Wagner public CursorWindow getWindow() { 1982d869da0b1dc4bb09d204e4845ef24db48a24b52Mark Wagner return null; 199f114492537753bc68640d4a0d403861387296bcbMark Wagner } 200f114492537753bc68640d4a0d403861387296bcbMark Wagner 201f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean onMove(int oldPosition, int newPosition) { 202f114492537753bc68640d4a0d403861387296bcbMark Wagner return ((CrossProcessCursor)mDatabaseCursor).onMove(oldPosition, newPosition); 203f114492537753bc68640d4a0d403861387296bcbMark Wagner } 204f114492537753bc68640d4a0d403861387296bcbMark Wagner 205f114492537753bc68640d4a0d403861387296bcbMark Wagner /* 206f114492537753bc68640d4a0d403861387296bcbMark Wagner * These "virtual columns" are columns which don't exist in the underlying 207f114492537753bc68640d4a0d403861387296bcbMark Wagner * database cursor but are exported by this cursor. For example, we compute 208f114492537753bc68640d4a0d403861387296bcbMark Wagner * a "word" by taking the substring of the full row text in the words table 209f114492537753bc68640d4a0d403861387296bcbMark Wagner * using the provided offsets. 210f114492537753bc68640d4a0d403861387296bcbMark Wagner */ 211f114492537753bc68640d4a0d403861387296bcbMark Wagner private String [] mVirtualColumns = new String [] { 212f114492537753bc68640d4a0d403861387296bcbMark Wagner SearchManager.SUGGEST_COLUMN_INTENT_DATA, 213f114492537753bc68640d4a0d403861387296bcbMark Wagner SearchManager.SUGGEST_COLUMN_INTENT_ACTION, 214f114492537753bc68640d4a0d403861387296bcbMark Wagner SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA, 215c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner SearchManager.SUGGEST_COLUMN_TEXT_1, 216f114492537753bc68640d4a0d403861387296bcbMark Wagner }; 217f114492537753bc68640d4a0d403861387296bcbMark Wagner 218f114492537753bc68640d4a0d403861387296bcbMark Wagner // Cursor column offsets for the above virtual columns. 219f114492537753bc68640d4a0d403861387296bcbMark Wagner // These columns exist after the natural columns in the 220f114492537753bc68640d4a0d403861387296bcbMark Wagner // database cursor. So, for example, the column called 221f114492537753bc68640d4a0d403861387296bcbMark Wagner // SUGGEST_COLUMN_TEXT_1 comes 3 after mDatabaseCursor.getColumnCount(). 222f114492537753bc68640d4a0d403861387296bcbMark Wagner private final int INTENT_DATA_COLUMN = 0; 223f114492537753bc68640d4a0d403861387296bcbMark Wagner private final int INTENT_ACTION_COLUMN = 1; 224f114492537753bc68640d4a0d403861387296bcbMark Wagner private final int INTENT_EXTRA_DATA_COLUMN = 2; 225f114492537753bc68640d4a0d403861387296bcbMark Wagner private final int INTENT_TEXT_COLUMN = 3; 226f114492537753bc68640d4a0d403861387296bcbMark Wagner 227f114492537753bc68640d4a0d403861387296bcbMark Wagner 228f114492537753bc68640d4a0d403861387296bcbMark Wagner public int getColumnCount() { 229f114492537753bc68640d4a0d403861387296bcbMark Wagner return mColumnCount + mVirtualColumns.length; 230f114492537753bc68640d4a0d403861387296bcbMark Wagner } 231f114492537753bc68640d4a0d403861387296bcbMark Wagner 232f114492537753bc68640d4a0d403861387296bcbMark Wagner public int getColumnIndex(String columnName) { 233f114492537753bc68640d4a0d403861387296bcbMark Wagner for (int i = 0; i < mVirtualColumns.length; i++) { 234f114492537753bc68640d4a0d403861387296bcbMark Wagner if (mVirtualColumns[i].equals(columnName)) { 235f114492537753bc68640d4a0d403861387296bcbMark Wagner return mColumnCount + i; 236f114492537753bc68640d4a0d403861387296bcbMark Wagner } 237f114492537753bc68640d4a0d403861387296bcbMark Wagner } 238f114492537753bc68640d4a0d403861387296bcbMark Wagner return mDatabaseCursor.getColumnIndex(columnName); 239f114492537753bc68640d4a0d403861387296bcbMark Wagner } 240f114492537753bc68640d4a0d403861387296bcbMark Wagner 241f114492537753bc68640d4a0d403861387296bcbMark Wagner public String [] getColumnNames() { 242f114492537753bc68640d4a0d403861387296bcbMark Wagner String [] x = mDatabaseCursor.getColumnNames(); 243f114492537753bc68640d4a0d403861387296bcbMark Wagner String [] y = new String [x.length + mVirtualColumns.length]; 244f114492537753bc68640d4a0d403861387296bcbMark Wagner 245f114492537753bc68640d4a0d403861387296bcbMark Wagner for (int i = 0; i < x.length; i++) { 246f114492537753bc68640d4a0d403861387296bcbMark Wagner y[i] = x[i]; 247f114492537753bc68640d4a0d403861387296bcbMark Wagner } 248f114492537753bc68640d4a0d403861387296bcbMark Wagner 249f114492537753bc68640d4a0d403861387296bcbMark Wagner for (int i = 0; i < mVirtualColumns.length; i++) { 250f114492537753bc68640d4a0d403861387296bcbMark Wagner y[x.length + i] = mVirtualColumns[i]; 251f114492537753bc68640d4a0d403861387296bcbMark Wagner } 252f114492537753bc68640d4a0d403861387296bcbMark Wagner 253f114492537753bc68640d4a0d403861387296bcbMark Wagner return y; 254f114492537753bc68640d4a0d403861387296bcbMark Wagner } 255f114492537753bc68640d4a0d403861387296bcbMark Wagner 256f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean moveToPosition(int position) { 257f114492537753bc68640d4a0d403861387296bcbMark Wagner if (position >= 0 && position < mRows.size()) { 258f114492537753bc68640d4a0d403861387296bcbMark Wagner mCurrentRow = position; 259f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.moveToPosition(mRows.get(position).mRowNumber); 260f114492537753bc68640d4a0d403861387296bcbMark Wagner return true; 261f114492537753bc68640d4a0d403861387296bcbMark Wagner } else { 262f114492537753bc68640d4a0d403861387296bcbMark Wagner return false; 263f114492537753bc68640d4a0d403861387296bcbMark Wagner } 264f114492537753bc68640d4a0d403861387296bcbMark Wagner } 265f114492537753bc68640d4a0d403861387296bcbMark Wagner 266f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean move(int offset) { 267f114492537753bc68640d4a0d403861387296bcbMark Wagner return moveToPosition(mCurrentRow + offset); 268f114492537753bc68640d4a0d403861387296bcbMark Wagner } 269f114492537753bc68640d4a0d403861387296bcbMark Wagner 270f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean moveToFirst() { 271f114492537753bc68640d4a0d403861387296bcbMark Wagner return moveToPosition(0); 272f114492537753bc68640d4a0d403861387296bcbMark Wagner } 273f114492537753bc68640d4a0d403861387296bcbMark Wagner 274f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean moveToLast() { 275f114492537753bc68640d4a0d403861387296bcbMark Wagner return moveToPosition(mRows.size() - 1); 276f114492537753bc68640d4a0d403861387296bcbMark Wagner } 277f114492537753bc68640d4a0d403861387296bcbMark Wagner 278f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean moveToNext() { 279f114492537753bc68640d4a0d403861387296bcbMark Wagner return moveToPosition(mCurrentRow + 1); 280f114492537753bc68640d4a0d403861387296bcbMark Wagner } 281f114492537753bc68640d4a0d403861387296bcbMark Wagner 282f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean moveToPrevious() { 283f114492537753bc68640d4a0d403861387296bcbMark Wagner return moveToPosition(mCurrentRow - 1); 284f114492537753bc68640d4a0d403861387296bcbMark Wagner } 285f114492537753bc68640d4a0d403861387296bcbMark Wagner 286f114492537753bc68640d4a0d403861387296bcbMark Wagner public String getString(int column) { 287c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner // if we're returning one of the columns in the underlying database column 288c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner // then do so here 289f114492537753bc68640d4a0d403861387296bcbMark Wagner if (column < mColumnCount) { 290f114492537753bc68640d4a0d403861387296bcbMark Wagner return mDatabaseCursor.getString(column); 291f114492537753bc68640d4a0d403861387296bcbMark Wagner } 292f114492537753bc68640d4a0d403861387296bcbMark Wagner 293c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner // otherwise we're returning one of the synthetic columns. 294c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner // the constants like INTENT_DATA_COLUMN are offsets relative to 295c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner // mColumnCount. 296f114492537753bc68640d4a0d403861387296bcbMark Wagner Row row = mRows.get(mCurrentRow); 297f114492537753bc68640d4a0d403861387296bcbMark Wagner switch (column - mColumnCount) { 298f114492537753bc68640d4a0d403861387296bcbMark Wagner case INTENT_DATA_COLUMN: 299c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner Uri.Builder b = Uri.parse("content://mms-sms/search").buildUpon(); 300c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner b = b.appendQueryParameter("pattern", row.getSnippet()); 301c27b5dc04d496dc4176bea034498bec4e68045faMark Wagner Uri u = b.build(); 302f114492537753bc68640d4a0d403861387296bcbMark Wagner return u.toString(); 303f114492537753bc68640d4a0d403861387296bcbMark Wagner case INTENT_ACTION_COLUMN: 304f114492537753bc68640d4a0d403861387296bcbMark Wagner return Intent.ACTION_SEARCH; 305f114492537753bc68640d4a0d403861387296bcbMark Wagner case INTENT_EXTRA_DATA_COLUMN: 306c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner return row.getSnippet(); 307f114492537753bc68640d4a0d403861387296bcbMark Wagner case INTENT_TEXT_COLUMN: 308c6ec8c45d3c414aca13a0298ccc5bfa6ee871aa1Mark Wagner return row.getSnippet(); 309f114492537753bc68640d4a0d403861387296bcbMark Wagner default: 310f114492537753bc68640d4a0d403861387296bcbMark Wagner return null; 311f114492537753bc68640d4a0d403861387296bcbMark Wagner } 312f114492537753bc68640d4a0d403861387296bcbMark Wagner } 313f114492537753bc68640d4a0d403861387296bcbMark Wagner 314f114492537753bc68640d4a0d403861387296bcbMark Wagner public void close() { 315f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.close(); 316f114492537753bc68640d4a0d403861387296bcbMark Wagner } 317f114492537753bc68640d4a0d403861387296bcbMark Wagner 318f114492537753bc68640d4a0d403861387296bcbMark Wagner public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) { 319f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.copyStringToBuffer(columnIndex, buffer); 320f114492537753bc68640d4a0d403861387296bcbMark Wagner } 321f114492537753bc68640d4a0d403861387296bcbMark Wagner 322f114492537753bc68640d4a0d403861387296bcbMark Wagner public void deactivate() { 323f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.deactivate(); 324f114492537753bc68640d4a0d403861387296bcbMark Wagner } 325f114492537753bc68640d4a0d403861387296bcbMark Wagner 326f114492537753bc68640d4a0d403861387296bcbMark Wagner public byte[] getBlob(int columnIndex) { 327f114492537753bc68640d4a0d403861387296bcbMark Wagner return null; 328f114492537753bc68640d4a0d403861387296bcbMark Wagner } 329f114492537753bc68640d4a0d403861387296bcbMark Wagner 330f114492537753bc68640d4a0d403861387296bcbMark Wagner public int getColumnIndexOrThrow(String columnName) 331f114492537753bc68640d4a0d403861387296bcbMark Wagner throws IllegalArgumentException { 332f114492537753bc68640d4a0d403861387296bcbMark Wagner return 0; 333f114492537753bc68640d4a0d403861387296bcbMark Wagner } 334f114492537753bc68640d4a0d403861387296bcbMark Wagner 335f114492537753bc68640d4a0d403861387296bcbMark Wagner public String getColumnName(int columnIndex) { 336f114492537753bc68640d4a0d403861387296bcbMark Wagner return null; 337f114492537753bc68640d4a0d403861387296bcbMark Wagner } 338f114492537753bc68640d4a0d403861387296bcbMark Wagner 339f114492537753bc68640d4a0d403861387296bcbMark Wagner public double getDouble(int columnIndex) { 340f114492537753bc68640d4a0d403861387296bcbMark Wagner return 0; 341f114492537753bc68640d4a0d403861387296bcbMark Wagner } 342f114492537753bc68640d4a0d403861387296bcbMark Wagner 343f114492537753bc68640d4a0d403861387296bcbMark Wagner public Bundle getExtras() { 344903d973ca7093ce0574feca4f58e114a0c11e099Mark Wagner return Bundle.EMPTY; 345f114492537753bc68640d4a0d403861387296bcbMark Wagner } 346f114492537753bc68640d4a0d403861387296bcbMark Wagner 347f114492537753bc68640d4a0d403861387296bcbMark Wagner public float getFloat(int columnIndex) { 348f114492537753bc68640d4a0d403861387296bcbMark Wagner return 0; 349f114492537753bc68640d4a0d403861387296bcbMark Wagner } 350f114492537753bc68640d4a0d403861387296bcbMark Wagner 351f114492537753bc68640d4a0d403861387296bcbMark Wagner public int getInt(int columnIndex) { 352f114492537753bc68640d4a0d403861387296bcbMark Wagner return 0; 353f114492537753bc68640d4a0d403861387296bcbMark Wagner } 354f114492537753bc68640d4a0d403861387296bcbMark Wagner 355f114492537753bc68640d4a0d403861387296bcbMark Wagner public long getLong(int columnIndex) { 356f114492537753bc68640d4a0d403861387296bcbMark Wagner return 0; 357f114492537753bc68640d4a0d403861387296bcbMark Wagner } 358f114492537753bc68640d4a0d403861387296bcbMark Wagner 359f114492537753bc68640d4a0d403861387296bcbMark Wagner public int getPosition() { 360f114492537753bc68640d4a0d403861387296bcbMark Wagner return mCurrentRow; 361f114492537753bc68640d4a0d403861387296bcbMark Wagner } 362f114492537753bc68640d4a0d403861387296bcbMark Wagner 363f114492537753bc68640d4a0d403861387296bcbMark Wagner public short getShort(int columnIndex) { 364f114492537753bc68640d4a0d403861387296bcbMark Wagner return 0; 365f114492537753bc68640d4a0d403861387296bcbMark Wagner } 366f114492537753bc68640d4a0d403861387296bcbMark Wagner 367f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean getWantsAllOnMoveCalls() { 368f114492537753bc68640d4a0d403861387296bcbMark Wagner return false; 369f114492537753bc68640d4a0d403861387296bcbMark Wagner } 370f114492537753bc68640d4a0d403861387296bcbMark Wagner 371f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean isAfterLast() { 372f114492537753bc68640d4a0d403861387296bcbMark Wagner return mCurrentRow >= mRows.size(); 373f114492537753bc68640d4a0d403861387296bcbMark Wagner } 374f114492537753bc68640d4a0d403861387296bcbMark Wagner 375f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean isBeforeFirst() { 376f114492537753bc68640d4a0d403861387296bcbMark Wagner return mCurrentRow < 0; 377f114492537753bc68640d4a0d403861387296bcbMark Wagner } 378f114492537753bc68640d4a0d403861387296bcbMark Wagner 379f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean isClosed() { 380f114492537753bc68640d4a0d403861387296bcbMark Wagner return mDatabaseCursor.isClosed(); 381f114492537753bc68640d4a0d403861387296bcbMark Wagner } 382f114492537753bc68640d4a0d403861387296bcbMark Wagner 383f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean isFirst() { 384f114492537753bc68640d4a0d403861387296bcbMark Wagner return mCurrentRow == 0; 385f114492537753bc68640d4a0d403861387296bcbMark Wagner } 386f114492537753bc68640d4a0d403861387296bcbMark Wagner 387f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean isLast() { 388f114492537753bc68640d4a0d403861387296bcbMark Wagner return mCurrentRow == mRows.size() - 1; 389f114492537753bc68640d4a0d403861387296bcbMark Wagner } 39002c982b20c915fe8488d6a78946523a42a705170Vasu Nori 39102c982b20c915fe8488d6a78946523a42a705170Vasu Nori public int getType(int columnIndex) { 39202c982b20c915fe8488d6a78946523a42a705170Vasu Nori throw new UnsupportedOperationException(); // TODO revisit 39302c982b20c915fe8488d6a78946523a42a705170Vasu Nori } 394f114492537753bc68640d4a0d403861387296bcbMark Wagner 395f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean isNull(int columnIndex) { 396f114492537753bc68640d4a0d403861387296bcbMark Wagner return false; // TODO revisit 397f114492537753bc68640d4a0d403861387296bcbMark Wagner } 398f114492537753bc68640d4a0d403861387296bcbMark Wagner 399f114492537753bc68640d4a0d403861387296bcbMark Wagner public void registerContentObserver(ContentObserver observer) { 400f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.registerContentObserver(observer); 401f114492537753bc68640d4a0d403861387296bcbMark Wagner } 402f114492537753bc68640d4a0d403861387296bcbMark Wagner 403f114492537753bc68640d4a0d403861387296bcbMark Wagner public void registerDataSetObserver(DataSetObserver observer) { 404f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.registerDataSetObserver(observer); 405f114492537753bc68640d4a0d403861387296bcbMark Wagner } 406f114492537753bc68640d4a0d403861387296bcbMark Wagner 407f114492537753bc68640d4a0d403861387296bcbMark Wagner public boolean requery() { 408f114492537753bc68640d4a0d403861387296bcbMark Wagner return false; 409f114492537753bc68640d4a0d403861387296bcbMark Wagner } 410f114492537753bc68640d4a0d403861387296bcbMark Wagner 411f114492537753bc68640d4a0d403861387296bcbMark Wagner public Bundle respond(Bundle extras) { 412f114492537753bc68640d4a0d403861387296bcbMark Wagner return mDatabaseCursor.respond(extras); 413f114492537753bc68640d4a0d403861387296bcbMark Wagner } 414f114492537753bc68640d4a0d403861387296bcbMark Wagner 415f114492537753bc68640d4a0d403861387296bcbMark Wagner public void setNotificationUri(ContentResolver cr, Uri uri) { 416f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.setNotificationUri(cr, uri); 417f114492537753bc68640d4a0d403861387296bcbMark Wagner } 418f114492537753bc68640d4a0d403861387296bcbMark Wagner 419469a45a0a453140087516b6fe32753ae19a194cbDianne Hackborn public Uri getNotificationUri() { 420469a45a0a453140087516b6fe32753ae19a194cbDianne Hackborn return mDatabaseCursor.getNotificationUri(); 421469a45a0a453140087516b6fe32753ae19a194cbDianne Hackborn } 422469a45a0a453140087516b6fe32753ae19a194cbDianne Hackborn 423f114492537753bc68640d4a0d403861387296bcbMark Wagner public void unregisterContentObserver(ContentObserver observer) { 424f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.unregisterContentObserver(observer); 425f114492537753bc68640d4a0d403861387296bcbMark Wagner } 426f114492537753bc68640d4a0d403861387296bcbMark Wagner 427f114492537753bc68640d4a0d403861387296bcbMark Wagner public void unregisterDataSetObserver(DataSetObserver observer) { 428f114492537753bc68640d4a0d403861387296bcbMark Wagner mDatabaseCursor.unregisterDataSetObserver(observer); 429f114492537753bc68640d4a0d403861387296bcbMark Wagner } 430c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang } 431c0c4420878eff51ce95cda9062cb3a1da6b671c8Wei Huang} 432