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 19120040ef31d79c1d69138b13ca7f256841f3298eMathew Inwoodimport com.google.common.annotations.VisibleForTesting; 20120040ef31d79c1d69138b13ca7f256841f3298eMathew Inwood 21fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.database.DataSetObservable; 22fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.database.DataSetObserver; 233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport java.util.ArrayList; 255229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwoodimport java.util.Collection; 265229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwoodimport java.util.HashSet; 273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/** 2993bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert * A SuggestionCursor that is backed by a list of Suggestions. 303e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 3104a180b52fb4100a2f3747e795fb5d26e3207a4aBjorn Bringertpublic class ListSuggestionCursor extends AbstractSuggestionCursorWrapper { 323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3308ff0a7cb6b99db79508fa3124730eb81411bc56Bjorn Bringert private static final int DEFAULT_CAPACITY = 16; 3408ff0a7cb6b99db79508fa3124730eb81411bc56Bjorn Bringert 35fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private final DataSetObservable mDataSetObservable = new DataSetObservable(); 36fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 375229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood private final ArrayList<Entry> mSuggestions; 385229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood 395229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood private HashSet<String> mExtraColumns; 403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4193bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert private int mPos = 0; 423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public ListSuggestionCursor(String userQuery) { 4408ff0a7cb6b99db79508fa3124730eb81411bc56Bjorn Bringert this(userQuery, DEFAULT_CAPACITY); 4593bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert } 4693bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert 47120040ef31d79c1d69138b13ca7f256841f3298eMathew Inwood @VisibleForTesting 4893bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert public ListSuggestionCursor(String userQuery, Suggestion...suggestions) { 4908ff0a7cb6b99db79508fa3124730eb81411bc56Bjorn Bringert this(userQuery, suggestions.length); 5093bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert for (Suggestion suggestion : suggestions) { 515229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood add(suggestion); 5293bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert } 533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 5508ff0a7cb6b99db79508fa3124730eb81411bc56Bjorn Bringert public ListSuggestionCursor(String userQuery, int capacity) { 5608ff0a7cb6b99db79508fa3124730eb81411bc56Bjorn Bringert super(userQuery); 575229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood mSuggestions = new ArrayList<Entry>(capacity); 5808ff0a7cb6b99db79508fa3124730eb81411bc56Bjorn Bringert } 5908ff0a7cb6b99db79508fa3124730eb81411bc56Bjorn Bringert 603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** 613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Adds a suggestion from another suggestion cursor. 623e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 633e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * @return {@code true} if the suggestion was added. 643e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 6593bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert public boolean add(Suggestion suggestion) { 665229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood mSuggestions.add(new Entry(suggestion)); 673e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return true; 683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 693e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void close() { 713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mSuggestions.clear(); 723e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public int getPosition() { 753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mPos; 763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void moveTo(int pos) { 793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert mPos = pos; 803e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 8287e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert public boolean moveToNext() { 8387e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert int size = mSuggestions.size(); 8487e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert if (mPos >= size) { 8587e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert // Already past the end 8687e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert return false; 8787e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert } 8887e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert mPos++; 8987e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert return mPos < size; 9087e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert } 9187e947cbd9f279a83337900ff8bbd5ab0a8dc455Bjorn Bringert 9294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney public void removeRow() { 9394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney mSuggestions.remove(mPos); 9494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 9594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 9693bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert public void replaceRow(Suggestion suggestion) { 975229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood mSuggestions.set(mPos, new Entry(suggestion)); 9894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney } 9994e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney 1003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public int getCount() { 1013e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert return mSuggestions.size(); 1023e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 10404a180b52fb4100a2f3747e795fb5d26e3207a4aBjorn Bringert @Override 10593bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert protected Suggestion current() { 1065229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood return mSuggestions.get(mPos).get(); 1073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 109bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert @Override 110bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert public String toString() { 1119038d65a5a8ebcfada1ec3067f81a26f05622088Mathew Inwood return getClass().getSimpleName() + "{[" + getUserQuery() + "] " + mSuggestions + "}"; 112bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert } 113bf61e445cbe423cc2554b722b6dd38675015c36dBjorn Bringert 114fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert /** 115fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * Register an observer that is called when changes happen to this data set. 116fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * 117fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * @param observer gets notified when the data set changes. 118fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert */ 119fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void registerDataSetObserver(DataSetObserver observer) { 120fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mDataSetObservable.registerObserver(observer); 121ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 122ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 123fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert /** 124fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * Unregister an observer that has previously been registered with 125fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * {@link #registerDataSetObserver(DataSetObserver)} 126fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * 127fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * @param observer the observer to unregister. 128fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert */ 129fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert public void unregisterDataSetObserver(DataSetObserver observer) { 130fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mDataSetObservable.unregisterObserver(observer); 1313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 133fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert protected void notifyDataSetChanged() { 134fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert mDataSetObservable.notifyChanged(); 1353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 1365229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood 1375229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood @Override 1385229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood public SuggestionExtras getExtras() { 1395229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood // override with caching to avoid re-parsing the extras 1405229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood return mSuggestions.get(mPos).getExtras(); 1415229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1425229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood 1435229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood public Collection<String> getExtraColumns() { 1445229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood if (mExtraColumns == null) { 1455229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood mExtraColumns = new HashSet<String>(); 1465229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood for (Entry e : mSuggestions) { 1475229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood SuggestionExtras extras = e.getExtras(); 1485229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood Collection<String> extraColumns = extras == null ? null 1495229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood : extras.getExtraColumnNames(); 1505229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood if (extraColumns != null) { 1515229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood for (String column : extras.getExtraColumnNames()) { 1525229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood mExtraColumns.add(column); 1535229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1545229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1555229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1565229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1575229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood return mExtraColumns.isEmpty() ? null : mExtraColumns; 1585229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1595229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood 1605229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood /** 1615229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood * This class exists purely to cache the suggestion extras. 1625229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood */ 1635229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood private static class Entry { 1645229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood private final Suggestion mSuggestion; 1655229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood private SuggestionExtras mExtras; 1665229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood public Entry(Suggestion s) { 1675229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood mSuggestion = s; 1685229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1695229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood public Suggestion get() { 1705229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood return mSuggestion; 1715229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1725229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood public SuggestionExtras getExtras() { 1735229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood if (mExtras == null) { 1745229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood mExtras = mSuggestion.getExtras(); 1755229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1765229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood return mExtras; 1775229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1785229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood } 1795229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood 1803e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert} 181