package querqy.lucene.rewrite; import org.apache.lucene.index.*; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.TermQuery; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * Created by rene on 10/09/2016. */ public abstract class AbstractDocumentFrequencyAndTermContextProvider implements DocumentFrequencyAndTermContextProvider { final List<Term> terms = new ArrayList<>(16); enum Status { USER_QUERY, OTHER_QUERY } protected final List<Integer> clauseOffsets = new ArrayList<>(); TermStats termStats = null; protected int endUserQuery = -1; protected Status status = Status.USER_QUERY; protected int maxInClause = -1; protected int maxInUserQuery = -1; int termIndex = -1; protected abstract TermStats doCalculateTermContexts(IndexSearcher searcher) throws IOException; /* (non-Javadoc) * @see querqy.lucene.rewrite.DocumentFrequencyAndTermContextProvider#prepareTerm(org.apache.lucene.index.Term) */ @Override public void prepareTerm(Term term) { terms.add(term); } @Override public int termIndex() { if (termIndex < terms.size() - 1) { termIndex++; return termIndex; } else { throw new IllegalStateException("termIndex already at last position: " + termIndex); } } /* (non-Javadoc) * @see querqy.lucene.rewrite.DocumentFrequencyAndTermContextProvider#getDocumentFrequencyAndTermContext(int, org.apache.lucene.search.IndexSearcher) */ @Override public DocumentFrequencyAndTermContext getDocumentFrequencyAndTermContext(int tqIndex, IndexSearcher searcher) throws IOException { TermStats ts = termStats; if (ts == null || ts.topReaderContext != searcher.getTopReaderContext()) { ts = calculateTermContexts(searcher); } return new DocumentFrequencyAndTermContext(ts.documentFrequencies[tqIndex], ts.termContexts[tqIndex]); } protected TermStats calculateTermContexts(IndexSearcher searcher) throws IOException { return setTermStats(doCalculateTermContexts(searcher)); } private synchronized TermStats setTermStats(final TermStats ts) { this.termStats = ts; return this.termStats; } @Override public void newClause() { if (status == Status.USER_QUERY) { maxInUserQuery = Math.max(maxInClause, maxInUserQuery); } maxInClause = -1; clauseOffsets.add(terms.size()); } public void finishedUserQuery() { status = Status.OTHER_QUERY; maxInUserQuery = Math.max(maxInClause, maxInUserQuery); endUserQuery = terms.size(); } @Override public int hashCode() { final int prime = 31; int result = prime + ((clauseOffsets == null) ? 0 : clauseOffsets.hashCode()); for (final Term term: terms) { result = prime * result + term.hashCode(); } return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; AbstractDocumentFrequencyAndTermContextProvider other = (AbstractDocumentFrequencyAndTermContextProvider) obj; if (clauseOffsets == null) { if (other.clauseOffsets != null) return false; } else if (!clauseOffsets.equals(other.clauseOffsets)) return false; if (terms == null) { if (other.terms != null) return false; } else if (terms.size() != other.terms.size()) return false; for (int i = 0, len = terms.size(); i < len; i++) { if (!terms.get(i).equals(other.terms.get(i))) { return false; } } return true; } public static class TermStats { final int[] documentFrequencies; final TermContext[] termContexts; final IndexReaderContext topReaderContext; public TermStats(int[] documentFrequencies, TermContext[] termContexts, IndexReaderContext topReaderContext) { this.documentFrequencies = documentFrequencies; this.termContexts = termContexts; this.topReaderContext = topReaderContext; } } }