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