package org.exist.indexing.lucene; import java.io.IOException; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.FuzzyQuery; import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.PhraseQuery; import org.apache.lucene.search.PrefixQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.WildcardQuery; import org.apache.lucene.search.regex.RegexQuery; public class LuceneUtil { /** * Extract all terms which would be matched by a given query. * The terms are put into a map with the term as key and the * corresponding query object as value. * * This method is used by {@link LuceneMatchListener} * to highlight matches in the search results. * * @param query * @param terms * @throws IOException in case of an error */ public static void extractTerms(Query query, Map<String, Query> terms, IndexReader reader) throws IOException { if (query instanceof BooleanQuery) extractTermsFromBoolean((BooleanQuery)query, terms, reader); else if (query instanceof TermQuery) extractTermsFromTerm((TermQuery) query, terms); else if (query instanceof WildcardQuery) extractTermsFromWildcard((WildcardQuery) query,terms, reader); else if (query instanceof RegexQuery) extractTermsFromRegex((RegexQuery) query, terms, reader); else if (query instanceof FuzzyQuery) extractTermsFromFuzzy((FuzzyQuery) query, terms, reader); else if (query instanceof PrefixQuery) extractTermsFromPrefix((PrefixQuery) query, terms, reader); else if (query instanceof PhraseQuery) extractTermsFromPhrase((PhraseQuery) query, terms); else { // fallback to Lucene's Query.extractTerms if none of the // above matches Set<Term> tempSet = new TreeSet<Term>(); query.extractTerms(tempSet); for (Term t : tempSet) { terms.put(t.text(), query); } } } private static void extractTermsFromBoolean(BooleanQuery query, Map<String, Query> terms, IndexReader reader) throws IOException { BooleanClause clauses[] = query.getClauses(); for (int i = 0; i < clauses.length; i++) { extractTerms(clauses[i].getQuery(), terms, reader); } } private static void extractTermsFromTerm(TermQuery query, Map<String, Query> terms) { terms.put(query.getTerm().text(), query); } private static void extractTermsFromWildcard(WildcardQuery query, Map<String, Query> terms, IndexReader reader) throws IOException { extractTerms(rewrite(query, reader), terms, reader); } private static void extractTermsFromRegex(RegexQuery query, Map<String, Query> terms, IndexReader reader) throws IOException { extractTerms(rewrite(query, reader), terms, reader); } private static void extractTermsFromFuzzy(FuzzyQuery query, Map<String, Query> terms, IndexReader reader) throws IOException { extractTerms(query.rewrite(reader), terms, reader); } private static void extractTermsFromPrefix(PrefixQuery query, Map<String, Query> terms, IndexReader reader) throws IOException { extractTerms(rewrite(query, reader), terms, reader); } private static void extractTermsFromPhrase(PhraseQuery query, Map<String, Query> terms) { Term[] t = query.getTerms(); for (int i = 0; i < t.length; i++) { terms.put(t[i].text(), query); } } private static Query rewrite(MultiTermQuery query, IndexReader reader) throws IOException { query.setRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE); return query.rewrite(reader); } }