1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.quicksearchbox; 18 19 import com.google.common.annotations.VisibleForTesting; 20 21 import android.database.DataSetObservable; 22 import android.database.DataSetObserver; 23 24 import java.util.ArrayList; 25 import java.util.Collection; 26 import java.util.HashSet; 27 28 /** 29 * A SuggestionCursor that is backed by a list of Suggestions. 30 */ 31 public class ListSuggestionCursor extends AbstractSuggestionCursorWrapper { 32 33 private static final int DEFAULT_CAPACITY = 16; 34 35 private final DataSetObservable mDataSetObservable = new DataSetObservable(); 36 37 private final ArrayList<Entry> mSuggestions; 38 39 private HashSet<String> mExtraColumns; 40 41 private int mPos = 0; 42 ListSuggestionCursor(String userQuery)43 public ListSuggestionCursor(String userQuery) { 44 this(userQuery, DEFAULT_CAPACITY); 45 } 46 47 @VisibleForTesting ListSuggestionCursor(String userQuery, Suggestion...suggestions)48 public ListSuggestionCursor(String userQuery, Suggestion...suggestions) { 49 this(userQuery, suggestions.length); 50 for (Suggestion suggestion : suggestions) { 51 add(suggestion); 52 } 53 } 54 ListSuggestionCursor(String userQuery, int capacity)55 public ListSuggestionCursor(String userQuery, int capacity) { 56 super(userQuery); 57 mSuggestions = new ArrayList<Entry>(capacity); 58 } 59 60 /** 61 * Adds a suggestion from another suggestion cursor. 62 * 63 * @return {@code true} if the suggestion was added. 64 */ add(Suggestion suggestion)65 public boolean add(Suggestion suggestion) { 66 mSuggestions.add(new Entry(suggestion)); 67 return true; 68 } 69 close()70 public void close() { 71 mSuggestions.clear(); 72 } 73 getPosition()74 public int getPosition() { 75 return mPos; 76 } 77 moveTo(int pos)78 public void moveTo(int pos) { 79 mPos = pos; 80 } 81 moveToNext()82 public boolean moveToNext() { 83 int size = mSuggestions.size(); 84 if (mPos >= size) { 85 // Already past the end 86 return false; 87 } 88 mPos++; 89 return mPos < size; 90 } 91 removeRow()92 public void removeRow() { 93 mSuggestions.remove(mPos); 94 } 95 replaceRow(Suggestion suggestion)96 public void replaceRow(Suggestion suggestion) { 97 mSuggestions.set(mPos, new Entry(suggestion)); 98 } 99 getCount()100 public int getCount() { 101 return mSuggestions.size(); 102 } 103 104 @Override current()105 protected Suggestion current() { 106 return mSuggestions.get(mPos).get(); 107 } 108 109 @Override toString()110 public String toString() { 111 return getClass().getSimpleName() + "{[" + getUserQuery() + "] " + mSuggestions + "}"; 112 } 113 114 /** 115 * Register an observer that is called when changes happen to this data set. 116 * 117 * @param observer gets notified when the data set changes. 118 */ registerDataSetObserver(DataSetObserver observer)119 public void registerDataSetObserver(DataSetObserver observer) { 120 mDataSetObservable.registerObserver(observer); 121 } 122 123 /** 124 * Unregister an observer that has previously been registered with 125 * {@link #registerDataSetObserver(DataSetObserver)} 126 * 127 * @param observer the observer to unregister. 128 */ unregisterDataSetObserver(DataSetObserver observer)129 public void unregisterDataSetObserver(DataSetObserver observer) { 130 mDataSetObservable.unregisterObserver(observer); 131 } 132 notifyDataSetChanged()133 protected void notifyDataSetChanged() { 134 mDataSetObservable.notifyChanged(); 135 } 136 137 @Override getExtras()138 public SuggestionExtras getExtras() { 139 // override with caching to avoid re-parsing the extras 140 return mSuggestions.get(mPos).getExtras(); 141 } 142 getExtraColumns()143 public Collection<String> getExtraColumns() { 144 if (mExtraColumns == null) { 145 mExtraColumns = new HashSet<String>(); 146 for (Entry e : mSuggestions) { 147 SuggestionExtras extras = e.getExtras(); 148 Collection<String> extraColumns = extras == null ? null 149 : extras.getExtraColumnNames(); 150 if (extraColumns != null) { 151 for (String column : extras.getExtraColumnNames()) { 152 mExtraColumns.add(column); 153 } 154 } 155 } 156 } 157 return mExtraColumns.isEmpty() ? null : mExtraColumns; 158 } 159 160 /** 161 * This class exists purely to cache the suggestion extras. 162 */ 163 private static class Entry { 164 private final Suggestion mSuggestion; 165 private SuggestionExtras mExtras; Entry(Suggestion s)166 public Entry(Suggestion s) { 167 mSuggestion = s; 168 } get()169 public Suggestion get() { 170 return mSuggestion; 171 } getExtras()172 public SuggestionExtras getExtras() { 173 if (mExtras == null) { 174 mExtras = mSuggestion.getExtras(); 175 } 176 return mExtras; 177 } 178 } 179 180 } 181