MultiSourceCorpus.java revision f95ce100dcbc77794b79b0187c566bb58b5978d3
1/* 2 * Copyright (C) 2010 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 17package com.android.quicksearchbox; 18 19 20import com.android.quicksearchbox.util.BarrierConsumer; 21 22import android.content.Context; 23import android.os.SystemClock; 24 25import java.util.ArrayList; 26import java.util.Collection; 27import java.util.List; 28import java.util.concurrent.Executor; 29 30/** 31 * Base class for corpora backed by multiple sources. 32 */ 33public abstract class MultiSourceCorpus extends AbstractCorpus { 34 35 private final Context mContext; 36 37 private final Executor mExecutor; 38 39 private final ArrayList<Source> mSources; 40 41 public MultiSourceCorpus(Context context, Executor executor, Source... sources) { 42 mContext = context; 43 mExecutor = executor; 44 45 mSources = new ArrayList<Source>(); 46 for (Source source : sources) { 47 if (source != null) { 48 mSources.add(source); 49 } 50 } 51 } 52 53 protected Context getContext() { 54 return mContext; 55 } 56 57 public Collection<Source> getSources() { 58 return mSources; 59 } 60 61 /** 62 * Creates a corpus result object for a set of source results. 63 * This method should not call {@link Result#fill}. 64 * 65 * @param query The query text. 66 * @param results The results of the queries. 67 * @param latency Latency in milliseconds of the suggestion queries. 68 * @return An instance of {@link Result} or a subclass of it. 69 */ 70 protected Result createResult(String query, ArrayList<SourceResult> results, int latency) { 71 return new Result(query, results, latency); 72 } 73 74 /** 75 * Gets the sources to query for the given input. 76 * 77 * @param query The current input. 78 * @return The sources to query. 79 */ 80 protected List<Source> getSourcesToQuery(String query) { 81 return mSources; 82 } 83 84 public CorpusResult getSuggestions(String query, int queryLimit) { 85 LatencyTracker latencyTracker = new LatencyTracker(); 86 List<Source> sources = getSourcesToQuery(query); 87 BarrierConsumer<SourceResult> consumer = 88 new BarrierConsumer<SourceResult>(sources.size()); 89 for (Source source : sources) { 90 QueryTask<SourceResult> task = new QueryTask<SourceResult>(query, queryLimit, 91 source, null, consumer); 92 mExecutor.execute(task); 93 } 94 ArrayList<SourceResult> results = consumer.getValues(); 95 int latency = latencyTracker.getLatency(); 96 Result result = createResult(query, results, latency); 97 result.fill(); 98 return result; 99 } 100 101 /** 102 * Base class for results returned by {@link MultiSourceCorpus#getSuggestions}. 103 * Subclasses of {@link MultiSourceCorpus} should override 104 * {@link MultiSourceCorpus#createResult} and return an instance of this class or a 105 * subclass. 106 */ 107 protected class Result extends ListSuggestionCursor implements CorpusResult { 108 109 private final ArrayList<SourceResult> mResults; 110 111 private final int mLatency; 112 113 public Result(String userQuery, ArrayList<SourceResult> results, int latency) { 114 super(userQuery); 115 mResults = results; 116 mLatency = latency; 117 } 118 119 protected ArrayList<SourceResult> getResults() { 120 return mResults; 121 } 122 123 /** 124 * Fills the list of suggestions using the list of results. 125 * The default implementation concatenates the results. 126 */ 127 public void fill() { 128 for (SourceResult result : getResults()) { 129 int count = result.getCount(); 130 for (int i = 0; i < count; i++) { 131 result.moveTo(i); 132 add(new SuggestionPosition(result)); 133 } 134 } 135 } 136 137 public Corpus getCorpus() { 138 return MultiSourceCorpus.this; 139 } 140 141 public int getLatency() { 142 return mLatency; 143 } 144 145 @Override 146 public void close() { 147 super.close(); 148 for (SourceResult result : mResults) { 149 result.close(); 150 } 151 } 152 153 @Override 154 public String toString() { 155 return getCorpus() + "[" + getUserQuery() + "]"; 156 } 157 } 158 159} 160