Index: lucene/core/src/java/org/apache/lucene/util/fst/Util.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/fst/Util.java (revision 1402188) +++ lucene/core/src/java/org/apache/lucene/util/fst/Util.java (working copy) @@ -259,6 +259,28 @@ } } + public interface Predicate { + public boolean eval(IntsRef input, T output); + } + + public static class TopNSearcherWithPredicate extends TopNSearcher { + + protected final Predicate theTest; + + public TopNSearcherWithPredicate(FST fst, int topN, int maxQueueDepth, Comparator comparator, Predicate t) { + super(fst, topN, maxQueueDepth, comparator); + this.theTest = t; + } + + @Override + protected boolean acceptResult(IntsRef input, T output) { + return (this.theTest == null) + ? super.acceptResult(input, output) + : this.theTest.eval(input, output); + } + + } + /** Utility class to find top N shortest paths from start * point(s). */ public static class TopNSearcher { Index: lucene/suggest/src/java/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggester.java =================================================================== --- lucene/suggest/src/java/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggester.java (revision 1402188) +++ lucene/suggest/src/java/org/apache/lucene/search/suggest/analyzing/AnalyzingSuggester.java (working copy) @@ -60,6 +60,7 @@ import org.apache.lucene.util.fst.PositiveIntOutputs; import org.apache.lucene.util.fst.Util.MinResult; import org.apache.lucene.util.fst.Util; +import org.apache.lucene.util.fst.Util.Predicate; /** * Suggester that first analyzes the surface form, adds the @@ -503,6 +504,11 @@ @Override public List lookup(final CharSequence key, boolean onlyMorePopular, int num) { + return lookup(key, onlyMorePopular, num, null); + } + + public List lookup(final CharSequence key, boolean onlyMorePopular, int num, Predicate> predicate) { + assert num > 0; if (onlyMorePopular) { @@ -563,7 +569,7 @@ // Searcher just to find the single exact only // match, if present: Util.TopNSearcher> searcher; - searcher = new Util.TopNSearcher>(fst, count * maxSurfaceFormsPerAnalyzedForm, count * maxSurfaceFormsPerAnalyzedForm, weightComparator); + searcher = new Util.TopNSearcherWithPredicate>(fst, count * maxSurfaceFormsPerAnalyzedForm, count * maxSurfaceFormsPerAnalyzedForm, weightComparator, predicate); // NOTE: we could almost get away with only using // the first start node. The only catch is if @@ -608,15 +614,18 @@ } Util.TopNSearcher> searcher; - searcher = new Util.TopNSearcher>(fst, + searcher = new Util.TopNSearcherWithPredicate>(fst, num - results.size(), num * maxAnalyzedPathsForOneInput, - weightComparator) { + weightComparator, predicate) { private final Set seen = new HashSet(); @Override protected boolean acceptResult(IntsRef input, Pair output) { + if (!super.acceptResult(input, output)) + return false; + // Dedup: when the input analyzes to a graph we // can get duplicate surface forms: if (seen.contains(output.output2)) {