package mtas.search.spans; import java.io.IOException; import java.util.Map; import java.util.Set; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermContext; import org.apache.lucene.index.Terms; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.spans.SpanWeight; import org.apache.lucene.search.spans.Spans; import mtas.search.spans.util.MtasSpanQuery; import mtas.search.spans.util.MtasSpanWeight; import mtas.search.spans.util.MtasSpans; /** * The Class MtasSpanRecurrenceQuery. */ public class MtasSpanRecurrenceQuery extends MtasSpanQuery { /** The query. */ private MtasSpanQuery query; /** The minimum recurrence. */ private int minimumRecurrence; /** The maximum recurrence. */ private int maximumRecurrence; /** The ignore query. */ private MtasSpanQuery ignoreQuery; /** The maximum ignore length. */ private Integer maximumIgnoreLength; /** The field. */ private String field; /** * Instantiates a new mtas span recurrence query. * * @param query the query * @param minimumRecurrence the minimum recurrence * @param maximumRecurrence the maximum recurrence * @param ignoreQuery the ignore query * @param maximumIgnoreLength the maximum ignore length */ public MtasSpanRecurrenceQuery(MtasSpanQuery query, int minimumRecurrence, int maximumRecurrence, MtasSpanQuery ignoreQuery, Integer maximumIgnoreLength) { super(null, null); field = query.getField(); this.query = query; if (field != null && ignoreQuery != null) { if (ignoreQuery.getField() == null || field.equals(ignoreQuery.getField())) { this.ignoreQuery = ignoreQuery; if (maximumIgnoreLength == null) { this.maximumIgnoreLength = 1; } else { this.maximumIgnoreLength = maximumIgnoreLength; } } else { throw new IllegalArgumentException( "ignore must have same field as clauses"); } } else { this.ignoreQuery = null; this.maximumIgnoreLength = null; } setRecurrence(minimumRecurrence, maximumRecurrence); } /** * Gets the query. * * @return the query */ public MtasSpanQuery getQuery() { return query; } /** * Gets the ignore query. * * @return the ignore query */ public MtasSpanQuery getIgnoreQuery() { return ignoreQuery; } /** * Gets the maximum ignore length. * * @return the maximum ignore length */ public Integer getMaximumIgnoreLength() { return maximumIgnoreLength; } /** * Gets the minimum recurrence. * * @return the minimum recurrence */ public int getMinimumRecurrence() { return minimumRecurrence; } /** * Gets the maximum recurrence. * * @return the maximum recurrence */ public int getMaximumRecurrence() { return maximumRecurrence; } /** * Sets the recurrence. * * @param minimumRecurrence the minimum recurrence * @param maximumRecurrence the maximum recurrence */ public void setRecurrence(int minimumRecurrence, int maximumRecurrence) { if (minimumRecurrence > maximumRecurrence) { throw new IllegalArgumentException( "minimumRecurrence > maximumRecurrence"); } else if (minimumRecurrence < 1) { throw new IllegalArgumentException("minimumRecurrence < 1 not supported"); } else if (query == null) { throw new IllegalArgumentException("no clause"); } this.minimumRecurrence = minimumRecurrence; this.maximumRecurrence = maximumRecurrence; // set minimum/maximum Integer minimum = null; Integer maximum = null; if (query.getMinimumWidth() != null) { minimum = minimumRecurrence * query.getMinimumWidth(); } if (query.getMaximumWidth() != null) { maximum = maximumRecurrence * query.getMaximumWidth(); if (ignoreQuery != null && maximumIgnoreLength != null) { if (ignoreQuery.getMaximumWidth() != null) { maximum += (maximumRecurrence - 1) * maximumIgnoreLength * ignoreQuery.getMaximumWidth(); } else { maximum = null; } } } setWidth(minimum, maximum); } /* * (non-Javadoc) * * @see org.apache.lucene.search.spans.SpanQuery#getField() */ @Override public String getField() { return field; } /* * (non-Javadoc) * * @see * org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */ @Override public MtasSpanQuery rewrite(IndexReader reader) throws IOException { MtasSpanQuery newQuery = query.rewrite(reader); if (maximumRecurrence == 1) { return newQuery; } else { MtasSpanQuery newIgnoreQuery = (ignoreQuery != null) ? ignoreQuery.rewrite(reader) : null; if (newQuery instanceof MtasSpanRecurrenceQuery) { // for now too difficult, possibly merge later } if (!newQuery.equals(query) || (newIgnoreQuery != null && !newIgnoreQuery.equals(ignoreQuery))) { return new MtasSpanRecurrenceQuery(newQuery, minimumRecurrence, maximumRecurrence, newIgnoreQuery, maximumIgnoreLength) .rewrite(reader); } else { return super.rewrite(reader); } } } /* * (non-Javadoc) * * @see org.apache.lucene.search.Query#toString(java.lang.String) */ @Override public String toString(String field) { StringBuilder buffer = new StringBuilder(); buffer.append(this.getClass().getSimpleName() + "(["); buffer.append(query.toString(query.getField())); buffer.append("," + minimumRecurrence + "," + maximumRecurrence); buffer.append(", "); buffer.append(ignoreQuery); buffer.append("])"); return buffer.toString(); } /* * (non-Javadoc) * * @see org.apache.lucene.search.Query#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final MtasSpanRecurrenceQuery other = (MtasSpanRecurrenceQuery) obj; boolean result; result = query.equals(other.query); result &= minimumRecurrence == other.minimumRecurrence; result &= maximumRecurrence == other.maximumRecurrence; if (result) { boolean subResult; subResult = ignoreQuery == null && other.ignoreQuery == null; subResult |= ignoreQuery != null && other.ignoreQuery != null && ignoreQuery.equals(other.ignoreQuery); return subResult; } else { return false; } } /* * (non-Javadoc) * * @see org.apache.lucene.search.Query#hashCode() */ @Override public int hashCode() { int h = this.getClass().getSimpleName().hashCode(); h = (h * 7) ^ query.hashCode(); h = (h * 11) ^ minimumRecurrence; h = (h * 13) ^ maximumRecurrence; return h; } /* * (non-Javadoc) * * @see * org.apache.lucene.search.spans.SpanQuery#createWeight(org.apache.lucene. * search.IndexSearcher, boolean) */ @Override public MtasSpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException { SpanWeight subWeight = query.createWeight(searcher, false, boost); SpanWeight ignoreWeight = null; if (ignoreQuery != null) { ignoreWeight = ignoreQuery.createWeight(searcher, false, boost); } return new SpanRecurrenceWeight(subWeight, ignoreWeight, maximumIgnoreLength, searcher, needsScores ? getTermContexts(subWeight) : null, boost); } /* * (non-Javadoc) * * @see mtas.search.spans.util.MtasSpanQuery#disableTwoPhaseIterator() */ @Override public void disableTwoPhaseIterator() { super.disableTwoPhaseIterator(); query.disableTwoPhaseIterator(); if (ignoreQuery != null) { ignoreQuery.disableTwoPhaseIterator(); } } /** * The Class SpanRecurrenceWeight. */ protected class SpanRecurrenceWeight extends MtasSpanWeight { /** The sub weight. */ final SpanWeight subWeight; /** The ignore weight. */ final SpanWeight ignoreWeight; /** The maximum ignore length. */ final Integer maximumIgnoreLength; /** * Instantiates a new span recurrence weight. * * @param subWeight the sub weight * @param ignoreWeight the ignore weight * @param maximumIgnoreLength the maximum ignore length * @param searcher the searcher * @param terms the terms * @throws IOException Signals that an I/O exception has occurred. */ public SpanRecurrenceWeight(SpanWeight subWeight, SpanWeight ignoreWeight, Integer maximumIgnoreLength, IndexSearcher searcher, Map<Term, TermContext> terms, float boost) throws IOException { super(MtasSpanRecurrenceQuery.this, searcher, terms, boost); this.subWeight = subWeight; this.ignoreWeight = ignoreWeight; this.maximumIgnoreLength = maximumIgnoreLength; } /* * (non-Javadoc) * * @see * org.apache.lucene.search.spans.SpanWeight#extractTermContexts(java.util. * Map) */ @Override public void extractTermContexts(Map<Term, TermContext> contexts) { subWeight.extractTermContexts(contexts); } /* * (non-Javadoc) * * @see * org.apache.lucene.search.spans.SpanWeight#getSpans(org.apache.lucene. * index.LeafReaderContext, * org.apache.lucene.search.spans.SpanWeight.Postings) */ @Override public MtasSpans getSpans(LeafReaderContext context, Postings requiredPostings) throws IOException { if (field == null) { return null; } else { Terms terms = context.reader().terms(field); if (terms == null) { return null; // field does not exist } Spans subSpans = subWeight.getSpans(context, requiredPostings); if (subSpans == null) { return null; } else { Spans ignoreSpans = null; if (ignoreWeight != null) { ignoreSpans = ignoreWeight.getSpans(context, requiredPostings); } return new MtasSpanRecurrenceSpans(MtasSpanRecurrenceQuery.this, subSpans, minimumRecurrence, maximumRecurrence, ignoreSpans, maximumIgnoreLength); } } } /* * (non-Javadoc) * * @see org.apache.lucene.search.Weight#extractTerms(java.util.Set) */ @Override public void extractTerms(Set<Term> terms) { subWeight.extractTerms(terms); } // @Override // public boolean isCacheable(LeafReaderContext arg0) { // return subWeight.isCacheable(arg0) && (ignoreWeight==null || ignoreWeight.isCacheable(arg0)); // } } @Override public boolean isMatchAllPositionsQuery() { return false; } }