CursorBackedSuggestionCursor.java revision bf61e445cbe423cc2554b722b6dd38675015c36d
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;
203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.database.Cursor;
21fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.database.DataSetObserver;
223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.net.Uri;
233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.util.Log;
243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
25fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertpublic abstract class CursorBackedSuggestionCursor extends AbstractSuggestionCursor {
263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
27cef2c4c9d54f513babd74801dbed5cbf709b9b79Bjorn Bringert    private static final boolean DBG = false;
283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected static final String TAG = "QSB.CursorBackedSuggestionCursor";
293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
30883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    public static final String SUGGEST_COLUMN_LOG_TYPE = "suggest_log_type";
31883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert
323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /** The suggestions, or {@code null} if the suggestions query failed. */
333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected final Cursor mCursor;
343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
35fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_FORMAT} in @{link mCursor}. */
363e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mFormatCol;
373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
38fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_TEXT_1} in @{link mCursor}. */
393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mText1Col;
403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
41fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_TEXT_2} in @{link mCursor}. */
423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mText2Col;
433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
44965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_TEXT_2_URL} in @{link mCursor}. */
45965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert    private final int mText2UrlCol;
46965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert
47fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_ICON_1} in @{link mCursor}. */
483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mIcon1Col;
493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
50fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_ICON_1} in @{link mCursor}. */
513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private final int mIcon2Col;
523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
53fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /** Column index of {@link SearchManager#SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING}
5494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney     * in @{link mCursor}.
5594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney     **/
5694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    private final int mRefreshSpinnerCol;
5794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney
583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /** True if this result has been closed. */
593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private boolean mClosed = false;
603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public CursorBackedSuggestionCursor(String userQuery, Cursor cursor) {
623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        super(userQuery);
633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mCursor = cursor;
643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mFormatCol = getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mText1Col = getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mText2Col = getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
67965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert        mText2UrlCol = getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL);
683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mIcon1Col = getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mIcon2Col = getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
7094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney        mRefreshSpinnerCol = getColumnIndex(SearchManager.SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING);
713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
73fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public abstract Source getSuggestionSource();
743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
75fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public String getSuggestionLogType() {
76883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert        return getStringOrNull(SUGGEST_COLUMN_LOG_TYPE);
773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public void close() {
80185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert        if (DBG) Log.d(TAG, "close()");
813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mClosed) {
82185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert            throw new IllegalStateException("Double close()");
833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        mClosed = true;
853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mCursor != null) {
867a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            try {
877a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert                mCursor.close();
887a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            } catch (RuntimeException ex) {
897a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert                // all operations on cross-process cursors can throw random exceptions
907a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert                Log.e(TAG, "close() failed, ", ex);
917a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            }
923e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    @Override
963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected void finalize() {
973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (!mClosed) {
983e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            Log.e(TAG, "LEAK! Finalized without being closed: " + toString());
993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1023e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public int getCount() {
1033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mClosed) {
1043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            throw new IllegalStateException("getCount() after close()");
1053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mCursor == null) return 0;
1077a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        try {
1087a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return mCursor.getCount();
1097a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
1107a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
1117a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "getCount() failed, ", ex);
1127a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return 0;
1137a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        }
1143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public void moveTo(int pos) {
1173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mClosed) {
1183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            throw new IllegalStateException("moveTo(" + pos + ") after close()");
1193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1207a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        try {
1217a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            if (!mCursor.moveToPosition(pos)) {
1227a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert                Log.e(TAG, "moveToPosition(" + pos + ") failed, count=" + getCount());
1237a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            }
1247a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
1257a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
1267a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "moveToPosition() failed, ", ex);
1273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
13087e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert    public boolean moveToNext() {
13187e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        if (mClosed) {
13287e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            throw new IllegalStateException("moveToNext() after close()");
13387e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        }
13487e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        try {
13587e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            return mCursor.moveToNext();
13687e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        } catch (RuntimeException ex) {
13787e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
13887e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            Log.e(TAG, "moveToNext() failed, ", ex);
13987e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert            return false;
14087e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert        }
14187e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert    }
14287e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert
1433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public int getPosition() {
1443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mClosed) {
1453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            throw new IllegalStateException("getPosition after close()");
1463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1477a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        try {
1487a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return mCursor.getPosition();
1497a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
1507a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
1517a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "getPosition() failed, ", ex);
1527a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return -1;
1537a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        }
1543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getShortcutId() {
1573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID);
1583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionFormat() {
1613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mFormatCol);
1623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionText1() {
1653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mText1Col);
1663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionText2() {
1693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mText2Col);
1703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
172965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert    public String getSuggestionText2Url() {
173965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert        return getStringOrNull(mText2UrlCol);
174965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert    }
175965d98377ddfdc52b772c2444d840000b665e000Bjorn Bringert
1763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionIcon1() {
1773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mIcon1Col);
1783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1803e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionIcon2() {
1813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(mIcon2Col);
1823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
18494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    public boolean isSpinnerWhileRefreshing() {
18594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney        return "true".equals(getStringOrNull(mRefreshSpinnerCol));
18694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    }
18794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney
1883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
1893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * Gets the intent action for the current suggestion.
1903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
191fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public String getSuggestionIntentAction() {
19204a180b52fb4100a2f3747e795fb5d26e3207a4aBjorn Bringert        return getStringOrNull(SearchManager.SUGGEST_COLUMN_INTENT_ACTION);
1933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
1963e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * Gets the query for the current suggestion.
1973e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
198fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public String getSuggestionQuery() {
1993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(SearchManager.SUGGEST_COLUMN_QUERY);
2003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2021e938ea2f5edefab446b9562b316bc5dc72adebbBryan Mawhinney    public String getSuggestionIntentDataString() {
2033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         // use specific data if supplied, or default data if supplied
2043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         String data = getStringOrNull(SearchManager.SUGGEST_COLUMN_INTENT_DATA);
2053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         if (data == null) {
206fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert             data = getSuggestionSource().getDefaultIntentData();
2073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         }
2083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         // then, if an ID was provided, append it.
2093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         if (data != null) {
2103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert             String id = getStringOrNull(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
2113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert             if (id != null) {
2123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                 data = data + "/" + Uri.encode(id);
2133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert             }
2143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         }
2153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert         return data;
2163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     }
2173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
2193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * Gets the intent extra data for the current suggestion.
2203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
22194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    public String getSuggestionIntentExtraData() {
2223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);
2233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
226fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the index of a column in {@link #mCursor} by name.
2273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     *
2283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @return The index, or {@code -1} if the column was not found.
2293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
2303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected int getColumnIndex(String colName) {
2313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mCursor == null) return -1;
2327a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        try {
2337a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return mCursor.getColumnIndex(colName);
2347a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
2357a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
2367a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "getColumnIndex() failed, ", ex);
2377a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            return -1;
2387a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        }
2393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
242fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the string value of a column in {@link #mCursor} by column index.
2433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     *
2443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @param col Column index.
2453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @return The string value, or {@code null}.
2463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
2473e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected String getStringOrNull(int col) {
2483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mCursor == null) return null;
2493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (col == -1) {
2503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            return null;
2513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
2523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        try {
2533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            return mCursor.getString(col);
2547a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert        } catch (RuntimeException ex) {
2557a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            // all operations on cross-process cursors can throw random exceptions
2567a1f40b4189a7435fe7177e759fde9fd2d032574Bjorn Bringert            Log.e(TAG, "getString() failed, ", ex);
2573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            return null;
2583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
2593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    /**
262fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the string value of a column in {@link #mCursor} by column name.
2633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     *
2643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @param colName Column name.
2653e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     * @return The string value, or {@code null}.
2663e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert     */
2673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected String getStringOrNull(String colName) {
2683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        int col = getColumnIndex(colName);
2693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return getStringOrNull(col);
2703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private String makeKeyComponent(String str) {
2733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return str == null ? "" : str;
2743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
2763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public String getSuggestionKey() {
2773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        String action = makeKeyComponent(getSuggestionIntentAction());
2783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        String data = makeKeyComponent(getSuggestionIntentDataString());
2793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        String query = makeKeyComponent(getSuggestionQuery());
2803e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        // calculating accurate size of string builder avoids an allocation vs starting with
2813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        // the default size and having to expand.
2823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        int size = action.length() + 2 + data.length() + query.length();
2833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return new StringBuilder(size)
2843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                .append(action)
2853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                .append('#')
2863e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                .append(data)
2873e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                .append('#')
2883e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                .append(query)
2893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                .toString();
2903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
291fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
292fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public void registerDataSetObserver(DataSetObserver observer) {
293fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        // We don't watch Cursor-backed SuggestionCursors for changes
294fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
295fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
296fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public void unregisterDataSetObserver(DataSetObserver observer) {
297fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        // We don't watch Cursor-backed SuggestionCursors for changes
298fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
299bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert
3003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert}
301