DefaultCorpusRanker.java revision 22da5e41bec9a5d36388c1e6f99bca392c3ac63e
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 19import com.android.quicksearchbox.util.AsyncCache; 20import com.android.quicksearchbox.util.Consumer; 21 22import android.database.DataSetObserver; 23import android.util.Log; 24 25import java.util.ArrayList; 26import java.util.Collection; 27import java.util.Collections; 28import java.util.Comparator; 29import java.util.List; 30import java.util.Map; 31 32/** 33 * A corpus ranker that uses corpus scores from the shortcut repository to rank 34 * corpora. 35 */ 36public class DefaultCorpusRanker implements CorpusRanker { 37 38 private static final boolean DBG = false; 39 private static final String TAG = "QSB.DefaultCorpusRanker"; 40 41 private final ShortcutRepository mShortcuts; 42 43 private final Corpora mCorpora; 44 45 // Cached list of ranked corpora. 46 private final RankedCorporaCache mRankedCorpora; 47 48 /** 49 * Creates a new default corpus ranker. 50 * 51 * @param corpora Corpora to rank. 52 * @param shortcuts Shortcut repository for getting corpus scores. 53 */ 54 public DefaultCorpusRanker(Corpora corpora, ShortcutRepository shortcuts) { 55 mCorpora = corpora; 56 mCorpora.registerDataSetObserver(new CorporaObserver()); 57 mShortcuts = shortcuts; 58 mRankedCorpora = new RankedCorporaCache(); 59 } 60 61 public void getRankedCorpora(Consumer<List<Corpus>> consumer) { 62 mRankedCorpora.get(consumer); 63 } 64 65 public void clear() { 66 mRankedCorpora.clear(); 67 } 68 69 private class CorporaObserver extends DataSetObserver { 70 @Override 71 public void onChanged() { 72 clear(); 73 } 74 } 75 76 private class RankedCorporaCache extends AsyncCache<List<Corpus>> { 77 78 protected void create() { 79 mShortcuts.getCorpusScores(new Consumer<Map<String,Integer>>(){ 80 public boolean consume(Map<String, Integer> clickScores) { 81 Collection<Corpus> enabledCorpora = mCorpora.getEnabledCorpora(); 82 if (DBG) Log.d(TAG, "Ranking: " + enabledCorpora); 83 ArrayList<Corpus> ordered = new ArrayList<Corpus>(enabledCorpora); 84 Collections.sort(ordered, new CorpusComparator(clickScores)); 85 86 if (DBG) Log.d(TAG, "Click scores: " + clickScores); 87 if (DBG) Log.d(TAG, "Ordered: " + ordered); 88 89 store(ordered); 90 return true; 91 } 92 }); 93 } 94 95 } 96 97 private static class CorpusComparator implements Comparator<Corpus> { 98 private final Map<String,Integer> mClickScores; 99 100 public CorpusComparator(Map<String,Integer> clickScores) { 101 mClickScores = clickScores; 102 } 103 104 public int compare(Corpus corpus1, Corpus corpus2) { 105 boolean corpus1IsDefault = corpus1.isCorpusDefaultEnabled(); 106 boolean corpus2IsDefault = corpus2.isCorpusDefaultEnabled(); 107 108 if (corpus1IsDefault != corpus2IsDefault) { 109 // Default corpora always come before non-default 110 return corpus1IsDefault ? -1 : 1; 111 } 112 113 // Then by descending score 114 int scoreDiff = getCorpusScore(corpus2) - getCorpusScore(corpus1); 115 if (scoreDiff != 0) { 116 return scoreDiff; 117 } 118 119 // Finally by name 120 return corpus1.getLabel().toString().compareTo(corpus2.getLabel().toString()); 121 } 122 123 /** 124 * Scores a corpus. Higher score is better. 125 */ 126 private int getCorpusScore(Corpus corpus) { 127 // Web corpus always comes first 128 if (corpus.isWebCorpus()) { 129 return Integer.MAX_VALUE; 130 } 131 // Then use click score 132 return getClickScore(corpus); 133 } 134 135 private int getClickScore(Corpus corpus) { 136 if (mClickScores == null) return 0; 137 Integer clickScore = mClickScores.get(corpus.getName()); 138 return clickScore == null ? 0 : clickScore; 139 } 140 } 141 142} 143