private boolean synchronize() throws IOException { while (more && spans.doc() != docIdSetIter.docID()) { if (spans.doc() < docIdSetIter.docID()) { more = spans.skipTo(docIdSetIter.docID()); } else if (docIdSetIter.advance(spans.doc()) == DocIdSetIterator.NO_MORE_DOCS) { more = false; } } return more; }
/** * Skip to the specified document (or the first document after it containing hits) * * @param doc the doc number to skip to (or past) * @return true if we're still pointing to a valid hit, false if we're done * @throws IOException */ @Override public boolean skipTo(int doc) throws IOException { // Skip both to doc stillValidContainers = producer.skipTo(doc); // Find first matching container from here return synchronize(); }
/** * Go to next span. * * @return true if we're at the next span, false if we're done * @throws IOException */ @Override public boolean next() throws IOException { // Are we done yet? if (!stillValidContainers || !stillValidSearch) return false; // Advance container stillValidContainers = producer.next(); if (!stillValidContainers) return false; // no more containers; we're done. // Find first matching container from here return synchronize(); }
@Override public boolean hitsAreUnique() { return spans.hitsAreUnique(); }
@Override public void getCapturedGroups(Span[] capturedGroups) { if (!childClausesCaptureGroups) return; producer.getCapturedGroups(capturedGroups); filter.getCapturedGroups(filterIndex, capturedGroups); }
@Override public int hitsLength() { return spans.hitsLength(); }
@Override public boolean hitsHaveUniqueEnd() { return spans.hitsHaveUniqueEnd(); }
/** @return start of current span */ @Override public int start() { return producer.start(); }
@Override public boolean hitsAllSameLength() { return spans.hitsAllSameLength(); }
@Override public int doc() { return spans.doc(); }
@Override public int start() { return spans.start(); }
@Override public void passHitQueryContextToClauses(HitQueryContext context) { producer.setHitQueryContext(context); filter.setHitQueryContext(context); }
@Override public boolean next() throws IOException { if (!more) return false; more = spans.next(); return synchronize(); }
@Override public boolean hitsAreUnique() { return producer.hitsAreUnique(); }
@Override public boolean hitsHaveUniqueEnd() { return producer.hitsHaveUniqueEnd(); }
@Override public int hitsLength() { return producer.hitsLength(); }
@Override public boolean hitsAllSameLength() { return producer.hitsAllSameLength(); }
@Override public boolean hitsEndPointSorted() { return producer.hitsEndPointSorted(); }
@Override public boolean skipTo(int target) throws IOException { if (!more) return false; more = spans.skipTo(target); return synchronize(); }
/** @return the Lucene document id of the current hit */ @Override public int doc() { return producer.doc(); }
@Override public int end() { return spans.end(); }
/** @return end position of current hit */ @Override public int end() { return producer.end(); }
@Override public boolean hitsStartPointSorted() { return spans.hitsStartPointSorted(); }
/** * Find a container with search hits in it, starting from the current container. * * @return true if found, false if no such container exists (i.e. we're done) * @throws IOException */ private boolean synchronize() throws IOException { // Find the next "valid" container, if there is one. while (true) { // Are search and container in the same document? if (filter.doc() < producer.doc()) { // No, advance search to be in the same document as the container stillValidSearch = filter.skipTo(producer.doc()); if (!stillValidSearch) return false; // No more search results, we're done. } // Are there search results in this document? if (filter.doc() == producer.doc()) { // Yes. See if the current container contains any of the search results. // List<Hit> filterHits = filter.getHits(); switch (op) { case CONTAINING: // Looking for producer hits with a filter hit inside for (int i = 0; i < filter.bucketSize(); i++) { if (filter.start(i) >= producer.start() && filter.end(i) <= producer.end()) { // Yes, this filter hit is contained in the current producer hit. filterIndex = i; // remember for captured groups return true; } } break; case WITHIN: // Looking for producer hits contained by a filter hit for (int i = 0; i < filter.bucketSize(); i++) { if (filter.start(i) <= producer.start() && filter.end(i) >= producer.end()) { // Yes, this filter hit contains the current producer hit. filterIndex = i; // remember for captured groups return true; } } break; case STARTS_AT: // Looking for producer hits starting at a filter hit for (int i = 0; i < filter.bucketSize(); i++) { if (filter.start(i) == producer.start()) { // Yes, this filter hit starts at the current producer hit. filterIndex = i; // remember for captured groups return true; } } break; case ENDS_AT: // Looking for producer hits ending at a filter hit for (int i = 0; i < filter.bucketSize(); i++) { if (filter.end(i) == producer.end()) { // Yes, this filter hit ends at the current producer hit. filterIndex = i; // remember for captured groups return true; } } break; default: throw new RuntimeException("Unknown filter operation " + op); } } // No search results found in the current container. // Advance to the next container. stillValidContainers = producer.next(); if (!stillValidContainers) return false; // no more containers; we're done. } }