1 package org.apache.lucene.search;
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 import java.io.IOException;
23 /** A Scorer for queries with a required subscorer
24 * and an excluding (prohibited) sub DocIdSetIterator.
26 * This <code>Scorer</code> implements {@link Scorer#skipTo(int)},
27 * and it uses the skipTo() on the given scorers.
29 class ReqExclScorer extends Scorer {
30 private Scorer reqScorer;
31 private DocIdSetIterator exclDisi;
34 /** Construct a <code>ReqExclScorer</code>.
35 * @param reqScorer The scorer that must match, except where
36 * @param exclDisi indicates exclusion.
38 public ReqExclScorer(Scorer reqScorer, DocIdSetIterator exclDisi) {
39 super(reqScorer.weight);
40 this.reqScorer = reqScorer;
41 this.exclDisi = exclDisi;
45 public int nextDoc() throws IOException {
46 if (reqScorer == null) {
49 doc = reqScorer.nextDoc();
50 if (doc == NO_MORE_DOCS) {
51 reqScorer = null; // exhausted, nothing left
54 if (exclDisi == null) {
57 return doc = toNonExcluded();
60 /** Advance to non excluded doc.
63 * <li>reqScorer != null,
64 * <li>exclScorer != null,
65 * <li>reqScorer was advanced once via next() or skipTo()
66 * and reqScorer.doc() may still be excluded.
68 * Advances reqScorer a non excluded required doc, if any.
69 * @return true iff there is a non excluded required doc.
71 private int toNonExcluded() throws IOException {
72 int exclDoc = exclDisi.docID();
73 int reqDoc = reqScorer.docID(); // may be excluded
75 if (reqDoc < exclDoc) {
76 return reqDoc; // reqScorer advanced to before exclScorer, ie. not excluded
77 } else if (reqDoc > exclDoc) {
78 exclDoc = exclDisi.advance(reqDoc);
79 if (exclDoc == NO_MORE_DOCS) {
80 exclDisi = null; // exhausted, no more exclusions
83 if (exclDoc > reqDoc) {
84 return reqDoc; // not excluded
87 } while ((reqDoc = reqScorer.nextDoc()) != NO_MORE_DOCS);
88 reqScorer = null; // exhausted, nothing left
97 /** Returns the score of the current document matching the query.
98 * Initially invalid, until {@link #nextDoc()} is called the first time.
99 * @return The score of the required scorer.
102 public float score() throws IOException {
103 return reqScorer.score(); // reqScorer may be null when next() or skipTo() already return false
107 public int advance(int target) throws IOException {
108 if (reqScorer == null) {
109 return doc = NO_MORE_DOCS;
111 if (exclDisi == null) {
112 return doc = reqScorer.advance(target);
114 if (reqScorer.advance(target) == NO_MORE_DOCS) {
116 return doc = NO_MORE_DOCS;
118 return doc = toNonExcluded();