blob: 490f8ec6d6b35a3706cc45916efacf6891a05dd3 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quicksearchbox;
import com.android.quicksearchbox.util.CachedLater;
import com.android.quicksearchbox.util.Consumer;
import android.database.DataSetObserver;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
/**
* A corpus ranker that uses corpus scores from the shortcut repository to rank
* corpora.
*/
public class DefaultCorpusRanker implements CorpusRanker {
private static final boolean DBG = false;
private static final String TAG = "QSB.DefaultCorpusRanker";
private final ShortcutRepository mShortcuts;
private final Corpora mCorpora;
// Cached list of ranked corpora.
private final RankedCorporaCache mRankedCorpora;
/**
* Creates a new default corpus ranker.
*
* @param corpora Corpora to rank.
* @param shortcuts Shortcut repository for getting corpus scores.
*/
public DefaultCorpusRanker(Corpora corpora, ShortcutRepository shortcuts) {
mCorpora = corpora;
mCorpora.registerDataSetObserver(new CorporaObserver());
mShortcuts = shortcuts;
mRankedCorpora = new RankedCorporaCache();
}
public void getCorporaInAll(Consumer<List<Corpus>> consumer) {
mRankedCorpora.getLater(consumer);
}
public void clear() {
mRankedCorpora.clear();
}
private class CorporaObserver extends DataSetObserver {
@Override
public void onChanged() {
clear();
}
}
private class RankedCorporaCache extends CachedLater<List<Corpus>> {
@Override
protected void create() {
mShortcuts.getCorpusScores(new Consumer<Map<String,Integer>>(){
public boolean consume(Map<String, Integer> clickScores) {
Collection<Corpus> enabledCorpora = mCorpora.getCorporaInAll();
if (DBG) Log.d(TAG, "Ranking: " + enabledCorpora);
ArrayList<Corpus> ordered = new ArrayList<Corpus>(enabledCorpora);
Collections.sort(ordered, new CorpusComparator(clickScores));
if (DBG) Log.d(TAG, "Click scores: " + clickScores);
if (DBG) Log.d(TAG, "Ordered: " + ordered);
store(ordered);
return true;
}
});
}
}
private static class CorpusComparator implements Comparator<Corpus> {
private final Map<String,Integer> mClickScores;
public CorpusComparator(Map<String,Integer> clickScores) {
mClickScores = clickScores;
}
public int compare(Corpus corpus1, Corpus corpus2) {
boolean corpus1IsDefault = corpus1.isCorpusDefaultEnabled();
boolean corpus2IsDefault = corpus2.isCorpusDefaultEnabled();
if (corpus1IsDefault != corpus2IsDefault) {
// Default corpora always come before non-default
return corpus1IsDefault ? -1 : 1;
}
// Then by descending score
int scoreDiff = getCorpusScore(corpus2) - getCorpusScore(corpus1);
if (scoreDiff != 0) {
return scoreDiff;
}
// Finally by name
return corpus1.getLabel().toString().compareTo(corpus2.getLabel().toString());
}
/**
* Scores a corpus. Higher score is better.
*/
private int getCorpusScore(Corpus corpus) {
// Web corpus always comes first
if (corpus.isWebCorpus()) {
return Integer.MAX_VALUE;
}
// Then use click score
return getClickScore(corpus);
}
private int getClickScore(Corpus corpus) {
if (mClickScores == null) return 0;
Integer clickScore = mClickScores.get(corpus.getName());
return clickScore == null ? 0 : clickScore;
}
}
}