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