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