package recommender.impl.meta;
import java.util.SortedSet;
import java.util.TreeSet;
import recommender.core.interfaces.model.RecommendationResult;
import recommender.core.util.RecommendationResultComparator;
/**
* Works like {@link MapBackedSet} but additionally keeps a set of the top
* number of results (according to {@link RecommendationResultComparator}).
* Thus, doesn't support the {@link #remove(Object)} method, since we could
* not 'refill' the top results after removal of one. Uses the results title to compare them.
*
* @author rja
*
* @param <E> the recommendation entity
* @param <R> the recommendation
*/
public class TopResultsMapBackedSet<R extends RecommendationResult> extends MapBackedSet<String, R> {
private final SortedSet<R> sortedResults;
private final int numberOfResults;
private final RecommendationResultComparator<R> comp;
/**
* @param numberOfResults - maximal number of top results to keep.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public TopResultsMapBackedSet(final int numberOfResults) {
super(new DefaultKeyExtractor());
this.sortedResults = new TreeSet<R>(new RecommendationResultComparator());
this.numberOfResults = numberOfResults;
this.comp = new RecommendationResultComparator();
}
@Override
public boolean add(R e) {
addToSortedSet(e);
return super.add(e);
}
/**
* Adds the result to the sorted set, if the sorted set is smaller than
* {@link #numberOfResults} or if the result is larger (according to
* {@link RecommendationResultComparator} than the last recommendation (which is then
* removed).
*
* @param e
*/
private void addToSortedSet(final R e) {
if (sortedResults.size() < numberOfResults) {
sortedResults.add(e);
} else if (this.comp.compare(e, sortedResults.last()) < 0) {
/*
* new result is better than last -> replace it!
*/
sortedResults.remove(sortedResults.last());
sortedResults.add(e);
}
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("remove() is not supported by this set.");
}
/**
* @return The top results sorted by {@link RecommendationResultComparator}.
*/
public SortedSet<R> getTopResults() {
return this.sortedResults;
}
/**
* Uses the name of a recommended recommendationResult as key for the map backed set.
* @author rja
*
*/
static class DefaultKeyExtractor<R extends RecommendationResult> implements MapBackedSet.KeyExtractor<String, R> {
@Override
public String getKey(R value) {
return value.getTitle();
}
}
}