SearchableCorpora.java revision bd92263c4f8df5e68e9d806167534e7067a5e5ed
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 17package com.android.quicksearchbox; 18 19import android.content.ComponentName; 20import android.content.Context; 21import android.content.SharedPreferences; 22import android.database.DataSetObserver; 23import android.os.Handler; 24import android.text.TextUtils; 25import android.util.Log; 26 27import java.util.ArrayList; 28import java.util.Collection; 29import java.util.Collections; 30import java.util.HashMap; 31import java.util.List; 32 33/** 34 * Maintains the list of all suggestion sources. 35 */ 36public class SearchableCorpora implements Corpora { 37 38 // set to true to enable the more verbose debug logging for this file 39 private static final boolean DBG = true; 40 private static final String TAG = "QSB.DefaultCorpora"; 41 42 private final Context mContext; 43 private final Config mConfig; 44 private final SharedPreferences mPreferences; 45 46 private boolean mLoaded = false; 47 48 private SearchableSources mSources; 49 // Maps corpus names to corpora 50 private HashMap<String,Corpus> mCorporaByName; 51 // Maps sources to the corpus that contains them 52 private HashMap<Source,Corpus> mCorporaBySource; 53 // Enabled corpora 54 private List<Corpus> mEnabledCorpora; 55 private Corpus mWebCorpus; 56 57 /** 58 * 59 * @param context Used for looking up source information etc. 60 */ 61 public SearchableCorpora(Context context, Config config, Handler uiThread) { 62 mContext = context; 63 mConfig = config; 64 mPreferences = SearchSettings.getSearchPreferences(context); 65 66 mSources = new SearchableSources(context, uiThread); 67 } 68 69 private void checkLoaded() { 70 if (!mLoaded) { 71 throw new IllegalStateException("corpora not loaded."); 72 } 73 } 74 75 public Collection<Corpus> getAllCorpora() { 76 checkLoaded(); 77 return Collections.unmodifiableCollection(mCorporaByName.values()); 78 } 79 80 public Collection<Corpus> getEnabledCorpora() { 81 checkLoaded(); 82 return mEnabledCorpora; 83 } 84 85 public Corpus getCorpus(String name) { 86 checkLoaded(); 87 return mCorporaByName.get(name); 88 } 89 90 public Corpus getCorpusForSource(Source source) { 91 checkLoaded(); 92 return mCorporaBySource.get(source); 93 } 94 95 public Source getSource(ComponentName name) { 96 checkLoaded(); 97 return mSources.getSource(name); 98 } 99 100 /** 101 * After calling, clients must call {@link #close()} when done with this object. 102 */ 103 public void load() { 104 if (mLoaded) { 105 throw new IllegalStateException("load(): Already loaded."); 106 } 107 108 mSources.registerDataSetObserver(new DataSetObserver() { 109 @Override 110 public void onChanged() { 111 updateCorpora(); 112 } 113 }); 114 115 // will cause a callback to updateCorpora() 116 mSources.load(); 117 mLoaded = true; 118 } 119 120 /** 121 * Releases all resources used by this object. It is possible to call 122 * {@link #load()} again after calling this method. 123 */ 124 public void close() { 125 checkLoaded(); 126 127 mSources.close(); 128 mSources = null; 129 mLoaded = false; 130 } 131 132 private void updateCorpora() { 133 mCorporaByName = new HashMap<String,Corpus>(); 134 mCorporaBySource = new HashMap<Source,Corpus>(); 135 mEnabledCorpora = new ArrayList<Corpus>(); 136 137 Source webSource = mSources.getWebSearchSource(); 138 Source browserSource = mSources.getSource(getBrowserSearchComponent()); 139 mWebCorpus = new WebCorpus(mContext, webSource, browserSource); 140 addCorpus(mWebCorpus); 141 mCorporaBySource.put(webSource, mWebCorpus); 142 mCorporaBySource.put(browserSource, mWebCorpus); 143 144 // Create corpora for all unclaimed sources 145 for (Source source : mSources.getSources()) { 146 if (!mCorporaBySource.containsKey(source)) { 147 Corpus corpus = new SingleSourceCorpus(source); 148 addCorpus(corpus); 149 mCorporaBySource.put(source, corpus); 150 } 151 } 152 153 if (DBG) Log.d(TAG, "Updated corpora: " + mCorporaBySource.values()); 154 155 mEnabledCorpora = Collections.unmodifiableList(mEnabledCorpora); 156 } 157 158 private void addCorpus(Corpus corpus) { 159 mCorporaByName.put(corpus.getName(), corpus); 160 if (isCorpusEnabled(corpus)) { 161 mEnabledCorpora.add(corpus); 162 } 163 } 164 165 private ComponentName getBrowserSearchComponent() { 166 String name = mContext.getString(R.string.browser_search_component); 167 return TextUtils.isEmpty(name) ? null : ComponentName.unflattenFromString(name); 168 } 169 170 public boolean isCorpusEnabled(Corpus corpus) { 171 if (corpus == null) return false; 172 boolean defaultEnabled = isCorpusDefaultEnabled(corpus); 173 String sourceEnabledPref = SearchSettings.getCorpusEnabledPreference(corpus); 174 return mPreferences.getBoolean(sourceEnabledPref, defaultEnabled); 175 } 176 177 public boolean isCorpusDefaultEnabled(Corpus corpus) { 178 String name = corpus.getName(); 179 return mConfig.isCorpusEnabledByDefault(name); 180 } 181 182} 183