package mtas.search.spans; import java.io.IOException; import org.apache.lucene.search.TwoPhaseIterator; import org.apache.lucene.search.spans.SpanCollector; import mtas.search.spans.MtasSpanIntersectingQuery.MtasSpanIntersectingQuerySpans; import mtas.search.spans.util.MtasSpans; /** * The Class MtasSpanIntersectingSpans. */ public class MtasSpanIntersectingSpans extends MtasSpans { /** The query. */ private MtasSpanIntersectingQuery query; /** The spans 1. */ private MtasSpanIntersectingQuerySpans spans1; /** The spans 2. */ private MtasSpanIntersectingQuerySpans spans2; /** The called next start position. */ private boolean calledNextStartPosition; /** The no more positions. */ private boolean noMorePositions; /** The last spans 2 start position. */ private int lastSpans2StartPosition; /** The last spans 2 end position. */ private int lastSpans2EndPosition; /** The doc id. */ private int docId; /** * Instantiates a new mtas span intersecting spans. * * @param query the query * @param spans1 the spans 1 * @param spans2 the spans 2 */ public MtasSpanIntersectingSpans(MtasSpanIntersectingQuery query, MtasSpanIntersectingQuerySpans spans1, MtasSpanIntersectingQuerySpans spans2) { super(); docId = -1; this.query = query; this.spans1 = spans1; this.spans2 = spans2; } /* * (non-Javadoc) * * @see org.apache.lucene.search.spans.Spans#nextStartPosition() */ @Override public int nextStartPosition() throws IOException { // no document if (docId == -1 || docId == NO_MORE_DOCS) { throw new IOException("no document"); // finished } else if (noMorePositions) { return NO_MORE_POSITIONS; // littleSpans already at start match, because of check for matching // document } else if (!calledNextStartPosition) { calledNextStartPosition = true; return spans1.spans.startPosition(); // compute next match } else { if (goToNextStartPosition()) { // match found return spans1.spans.startPosition(); } else { // no more matches: document finished return NO_MORE_POSITIONS; } } } /* * (non-Javadoc) * * @see org.apache.lucene.search.spans.Spans#startPosition() */ @Override public int startPosition() { return calledNextStartPosition ? (noMorePositions ? NO_MORE_POSITIONS : spans1.spans.startPosition()) : -1; } /* * (non-Javadoc) * * @see org.apache.lucene.search.spans.Spans#endPosition() */ @Override public int endPosition() { return calledNextStartPosition ? (noMorePositions ? NO_MORE_POSITIONS : spans1.spans.endPosition()) : -1; } /* * (non-Javadoc) * * @see org.apache.lucene.search.spans.Spans#width() */ @Override public int width() { return calledNextStartPosition ? (noMorePositions ? 0 : spans1.spans.endPosition() - spans1.spans.startPosition()) : 0; } /* * (non-Javadoc) * * @see * org.apache.lucene.search.spans.Spans#collect(org.apache.lucene.search.spans * .SpanCollector) */ @Override public void collect(SpanCollector collector) throws IOException { spans1.spans.collect(collector); spans2.spans.collect(collector); } /* * (non-Javadoc) * * @see org.apache.lucene.search.spans.Spans#positionsCost() */ @Override public float positionsCost() { return 0; } /* * (non-Javadoc) * * @see org.apache.lucene.search.DocIdSetIterator#docID() */ @Override public int docID() { return docId; } /* * (non-Javadoc) * * @see org.apache.lucene.search.DocIdSetIterator#nextDoc() */ @Override public int nextDoc() throws IOException { reset(); while (!goToNextDoc()) ; return docId; } /* * (non-Javadoc) * * @see org.apache.lucene.search.DocIdSetIterator#advance(int) */ @Override public int advance(int target) throws IOException { reset(); if (docId == NO_MORE_DOCS) { return docId; } else if (target < docId) { // should not happen docId = NO_MORE_DOCS; return docId; } else { // advance 1 int spans1DocId = spans1.spans.docID(); int newTarget = target; if (spans1DocId < newTarget) { spans1DocId = spans1.spans.advance(newTarget); if (spans1DocId == NO_MORE_DOCS) { docId = NO_MORE_DOCS; return docId; } newTarget = Math.max(newTarget, spans1DocId); } int spans2DocId = spans2.spans.docID(); // advance 2 if (spans2DocId < newTarget) { spans2DocId = spans2.spans.advance(newTarget); if (spans2DocId == NO_MORE_DOCS) { docId = NO_MORE_DOCS; return docId; } } // check equal docId, otherwise next if (spans1DocId == spans2DocId) { docId = spans1DocId; // check match if (goToNextStartPosition()) { return docId; } else { return nextDoc(); } } else { return nextDoc(); } } } /** * Go to next doc. * * @return true, if successful * @throws IOException Signals that an I/O exception has occurred. */ private boolean goToNextDoc() throws IOException { if (docId == NO_MORE_DOCS) { return true; } else { int spans1DocId = spans1.spans.nextDoc(); int spans2DocId = spans2.spans.docID(); docId = Math.max(spans1DocId, spans2DocId); while (spans1DocId != spans2DocId && docId != NO_MORE_DOCS) { if (spans1DocId < spans2DocId) { spans1DocId = spans1.spans.advance(spans2DocId); docId = spans1DocId; } else { spans2DocId = spans2.spans.advance(spans1DocId); docId = spans2DocId; } } if (docId != NO_MORE_DOCS) { if (!goToNextStartPosition()) { reset(); return false; } } return true; } } /** * Go to next start position. * * @return true, if successful * @throws IOException Signals that an I/O exception has occurred. */ private boolean goToNextStartPosition() throws IOException { int nextSpans1StartPosition; int nextSpans1EndPosition; int nextSpans2StartPosition; int nextSpans2EndPosition; while ((nextSpans1StartPosition = spans1.spans .nextStartPosition()) != NO_MORE_POSITIONS) { nextSpans1EndPosition = spans1.spans.endPosition(); if (nextSpans1StartPosition <= lastSpans2EndPosition && nextSpans1EndPosition >= lastSpans2StartPosition) { return true; } else { while (lastSpans2StartPosition <= nextSpans1EndPosition) { nextSpans2StartPosition = spans2.spans.nextStartPosition(); if (nextSpans2StartPosition == NO_MORE_POSITIONS) { noMorePositions = true; return false; } else { nextSpans2EndPosition = spans2.spans.endPosition(); if (nextSpans2StartPosition > lastSpans2StartPosition || nextSpans2EndPosition > lastSpans2EndPosition) { if (nextSpans2EndPosition > lastSpans2EndPosition) { lastSpans2StartPosition = nextSpans2StartPosition; lastSpans2EndPosition = nextSpans2EndPosition; if (nextSpans1StartPosition <= lastSpans2EndPosition && nextSpans1EndPosition >= lastSpans2StartPosition) { return true; } } } } } } } noMorePositions = true; return false; } /** * Reset. */ private void reset() { calledNextStartPosition = false; noMorePositions = false; lastSpans2StartPosition = -1; lastSpans2EndPosition = -1; } /* * (non-Javadoc) * * @see org.apache.lucene.search.DocIdSetIterator#cost() */ @Override public long cost() { return 0; } /* * (non-Javadoc) * * @see mtas.search.spans.util.MtasSpans#asTwoPhaseIterator() */ @Override public TwoPhaseIterator asTwoPhaseIterator() { if (spans1 == null || spans2 == null || !query.twoPhaseIteratorAllowed()) { return null; } else { // TODO return null; } } }