13e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/*
23e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Copyright (C) 2009 The Android Open Source Project
33e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert *
43e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
53e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * you may not use this file except in compliance with the License.
63e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * You may obtain a copy of the License at
73e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert *
83e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert *      http://www.apache.org/licenses/LICENSE-2.0
93e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert *
103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * See the License for the specific language governing permissions and
143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * limitations under the License.
153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */
163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpackage com.android.quicksearchbox;
183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.app.SearchManager;
2038eb02e676db9e5a633e3c88a90beb8a477b1ca1Bjorn Bringertimport android.content.ComponentName;
2193bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringertimport android.content.Intent;
223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.database.Cursor;
23fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.database.DataSetObserver;
243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.net.Uri;
253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.util.Log;
263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2793bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringertpublic abstract class CursorBackedSuggestionCursor implements SuggestionCursor {
283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
29cef2c4c9d54f513babd74801dbed5cbf709b9b79Bjorn Bringert    private static final boolean DBG = false;
303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected static final String TAG = "QSB.CursorBackedSuggestionCursor";
313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
32883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    public static final String SUGGEST_COLUMN_LOG_TYPE = "suggest_log_type";
33883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert
3493bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert    private final String mUserQuery;
3593bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert
363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /** The suggestions, or {@code null} if the suggestions query failed. */
373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected final Cursor mCursor;
383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
39fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_FORMAT} in @{link mCursor}. */
403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mFormatCol;
413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
42fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_TEXT_1} in @{link mCursor}. */
433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mText1Col;
443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
45fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_TEXT_2} in @{link mCursor}. */
463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mText2Col;
473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
48965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_TEXT_2_URL} in @{link mCursor}. */
49965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert    private final int mText2UrlCol;
50965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert
51fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_ICON_1} in @{link mCursor}. */
523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mIcon1Col;
533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
54fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_ICON_1} in @{link mCursor}. */
553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mIcon2Col;
563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
57fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING}
5894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney     * in @{link mCursor}.
5994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney     **/
6094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    private final int mRefreshSpinnerCol;
6194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney
623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /** True if this result has been closed. */
633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private boolean mClosed = false;
643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public CursorBackedSuggestionCursor(String userQuery, Cursor cursor) {
6693bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert        mUserQuery = userQuery;
673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mCursor = cursor;
683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mFormatCol = getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mText1Col = getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mText2Col = getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
71965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert        mText2UrlCol = getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL);
723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mIcon1Col = getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mIcon2Col = getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
7494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney        mRefreshSpinnerCol = getColumnIndex(SearchManager.SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING);
753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
7793bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert    public String getUserQuery() {
7893bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert        return mUserQuery;
7993bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert    }
8093bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert
81fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public abstract Source getSuggestionSource();
823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
83fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public String getSuggestionLogType() {
84883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert        return getStringOrNull(SUGGEST_COLUMN_LOG_TYPE);
853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public void close() {
88185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert        if (DBG) Log.d(TAG, "close()");
893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mClosed) {
90185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert            throw new IllegalStateException("Double close()");
913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mClosed = true;
933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mCursor != null) {
947a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            try {
957a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert                mCursor.close();
967a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            } catch (RuntimeException ex) {
977a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert                // all operations on cross-process cursors can throw random exceptions
987a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert                Log.e(TAG, "close() failed, ", ex);
997a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            }
1003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1023e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    @Override
1043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected void finalize() {
1053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (!mClosed) {
1063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            Log.e(TAG, "LEAK! Finalized without being closed: " + toString());
1073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public int getCount() {
1113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mClosed) {
1123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            throw new IllegalStateException("getCount() after close()");
1133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mCursor == null) return 0;
1157a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        try {
1167a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return mCursor.getCount();
1177a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
1187a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
1197a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "getCount() failed, ", ex);
1207a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return 0;
1217a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        }
1223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public void moveTo(int pos) {
1253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mClosed) {
1263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            throw new IllegalStateException("moveTo(" + pos + ") after close()");
1273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1287a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        try {
1297a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            if (!mCursor.moveToPosition(pos)) {
1307a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert                Log.e(TAG, "moveToPosition(" + pos + ") failed, count=" + getCount());
1317a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            }
1327a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
1337a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
1347a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "moveToPosition() failed, ", ex);
1353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
13887e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert    public boolean moveToNext() {
13987e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        if (mClosed) {
14087e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            throw new IllegalStateException("moveToNext() after close()");
14187e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        }
14287e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        try {
14387e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            return mCursor.moveToNext();
14487e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        } catch (RuntimeException ex) {
14587e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
14687e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            Log.e(TAG, "moveToNext() failed, ", ex);
14787e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            return false;
14887e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        }
14987e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert    }
15087e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert
1513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public int getPosition() {
1523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mClosed) {
1533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            throw new IllegalStateException("getPosition after close()");
1543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1557a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        try {
1567a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return mCursor.getPosition();
1577a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
1587a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
1597a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "getPosition() failed, ", ex);
1607a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return -1;
1617a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        }
1623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getShortcutId() {
1653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID);
1663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionFormat() {
1693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mFormatCol);
1703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionText1() {
1733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mText1Col);
1743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionText2() {
1773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mText2Col);
1783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
180965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert    public String getSuggestionText2Url() {
181965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert        return getStringOrNull(mText2UrlCol);
182965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert    }
183965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert
1843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionIcon1() {
1853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mIcon1Col);
1863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionIcon2() {
1893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mIcon2Col);
1903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
19294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    public boolean isSpinnerWhileRefreshing() {
19394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney        return "true".equals(getStringOrNull(mRefreshSpinnerCol));
19494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    }
19594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney
1963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
1973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * Gets the intent action for the current suggestion.
1983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
199fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public String getSuggestionIntentAction() {
20093bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert        String action = getStringOrNull(SearchManager.SUGGEST_COLUMN_INTENT_ACTION);
20193bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert        if (action != null) return action;
20293bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert        return getSuggestionSource().getDefaultIntentAction();
2033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
20538eb02e676db9e5a633e3c88a90beb8a477b1ca1Bjorn Bringert    public abstract ComponentName getSuggestionIntentComponent();
20638eb02e676db9e5a633e3c88a90beb8a477b1ca1Bjorn Bringert
2073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
2083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * Gets the query for the current suggestion.
2093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
210fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public String getSuggestionQuery() {
2113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(SearchManager.SUGGEST_COLUMN_QUERY);
2123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2141e938ea2f5edefab446b9562b316bc5dc72adebbBryan Mawhinney    public String getSuggestionIntentDataString() {
2153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         // use specific data if supplied, or default data if supplied
2163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         String data = getStringOrNull(SearchManager.SUGGEST_COLUMN_INTENT_DATA);
2173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         if (data == null) {
218fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert             data = getSuggestionSource().getDefaultIntentData();
2193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         }
2203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         // then, if an ID was provided, append it.
2213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         if (data != null) {
2223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert             String id = getStringOrNull(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
2233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert             if (id != null) {
2243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                 data = data + "/" + Uri.encode(id);
2253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert             }
2263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         }
2273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         return data;
2283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     }
2293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
2313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * Gets the intent extra data for the current suggestion.
2323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
23394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    public String getSuggestionIntentExtraData() {
2343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);
2353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
23793bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert    public boolean isWebSearchSuggestion() {
23893bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert        return Intent.ACTION_WEB_SEARCH.equals(getSuggestionIntentAction());
23993bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert    }
24093bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert
2413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
242fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the index of a column in {@link #mCursor} by name.
2433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     *
2443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @return The index, or {@code -1} if the column was not found.
2453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
2463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected int getColumnIndex(String colName) {
2473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mCursor == null) return -1;
2487a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        try {
2497a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return mCursor.getColumnIndex(colName);
2507a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
2517a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
2527a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "getColumnIndex() failed, ", ex);
2537a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return -1;
2547a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        }
2553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
258fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the string value of a column in {@link #mCursor} by column index.
2593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     *
2603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @param col Column index.
2613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @return The string value, or {@code null}.
2623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
2633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected String getStringOrNull(int col) {
2643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mCursor == null) return null;
2653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (col == -1) {
2663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            return null;
2673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
2683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        try {
2693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            return mCursor.getString(col);
2707a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
2717a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
2727a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "getString() failed, ", ex);
2733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            return null;
2743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
2753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
278fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the string value of a column in {@link #mCursor} by column name.
2793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     *
2803e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @param colName Column name.
2813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @return The string value, or {@code null}.
2823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
2833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected String getStringOrNull(String colName) {
2843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        int col = getColumnIndex(colName);
2853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(col);
2863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
288fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public void registerDataSetObserver(DataSetObserver observer) {
289fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        // We don't watch Cursor-backed SuggestionCursors for changes
290fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
291fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
292fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public void unregisterDataSetObserver(DataSetObserver observer) {
293fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        // We don't watch Cursor-backed SuggestionCursors for changes
294fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
295bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert
2969038d65a5a8ebcfada1ec3067f81a26f05622088Mathew Inwood    @Override
2979038d65a5a8ebcfada1ec3067f81a26f05622088Mathew Inwood    public String toString() {
2989038d65a5a8ebcfada1ec3067f81a26f05622088Mathew Inwood        return getClass().getSimpleName() + "[" + mUserQuery + "]";
2999038d65a5a8ebcfada1ec3067f81a26f05622088Mathew Inwood    }
3009038d65a5a8ebcfada1ec3067f81a26f05622088Mathew Inwood
3013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert}
302