Package org.sindice.siren.search.node

Source Code of org.sindice.siren.search.node.NodeReqExclScorer

/**
* Copyright 2014 National University of Ireland, Galway.
*
* This file is part of the SIREn project. Project and contact information:
*
*  https://github.com/rdelbru/SIREn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sindice.siren.search.node;

import java.io.IOException;

import org.apache.lucene.util.IntsRef;
import org.sindice.siren.util.NodeUtils;

/**
* A {@link NodeScorer} for queries within a node with a required subscorer
* and an excluding (prohibited) subscorer.
*
* <p>
*
* Only nodes matching the required subscorer and not matching the prohibited
* subscorer are kept.
*
* <p>
*
* Code taken from {@link ReqExclScorer} and adapted for the Siren use
* case.
*/
class NodeReqExclScorer extends NodeScorer {

  /**
   * The required and excluded primitive Siren scorers.
   */
  private final NodeScorer reqScorer;
  private NodeScorer exclScorer;

  /**
   * Construct a {@link NodeReqExclScorer}.
   *
   * @param reqScorer
   *          The scorer that must match, except where
   * @param exclScorer
   *          indicates exclusion.
   */
  public NodeReqExclScorer(final NodeScorer reqScorer,
                           final NodeScorer exclScorer) {
    super(reqScorer.getWeight());
    this.reqScorer = reqScorer;
    this.exclScorer = exclScorer;
  }

  @Override
  public boolean nextCandidateDocument() throws IOException {
    if (!reqScorer.nextCandidateDocument()) {
      return false;
    }

    if (exclScorer == null) {
      return true; // reqScorer.nextCandidateDocument() already returned true
    }

    return this.toNonExcludedCandidateDocument();
  }

  /**
   * Advance to non excluded candidate document. <br>
   * On entry:
   * <ul>
   * <li>reqScorer != null,
   * <li>exclScorer != null,
   * <li>reqScorer was advanced once via {@link #nextCandidateDocument()} or
   * {@link #skipToCandidate(int)} and reqScorer.doc() may still be excluded.
   * </ul>
   * Advances reqScorer a non excluded candidate document, if any.
   * <p>
   * If reqScorer.doc() is equal to exclScorer.doc(), reqScorer.doc() cannot
   * be excluded immediately, i.e., it is a valid candidate document. We have to
   * check the exclusion of reqScorer.node().
   *
   * @return true iff there is a non excluded candidate document.
   */
  private boolean toNonExcludedCandidateDocument() throws IOException {
    do {
      int exclDoc = exclScorer.doc();
      final int reqDoc = reqScorer.doc(); // may be excluded

      if (reqDoc <= exclDoc) {
        return true; // reqScorer advanced to or before exclScorer, not excluded
      }
      else if (reqDoc > exclDoc) {
        if (!exclScorer.skipToCandidate(reqDoc)) {
          exclScorer = null; // exhausted, no more exclusions
          return true;
        }
        exclDoc = exclScorer.doc();
        if (exclDoc >= reqDoc) {
          return true; // exclScorer advanced to or before reqScorer, not excluded
        }
      }
    } while (reqScorer.nextCandidateDocument());

    return false;
  }

  @Override
  public boolean nextNode() throws IOException {
    if (!reqScorer.nextNode()) { // Move to the next matching node
      return false; // exhausted, nothing left
    }

    if (exclScorer == null || exclScorer.doc() != reqScorer.doc()) {
      return true; // reqScorer.nextNode() already returned true
    }

    // reqScorer and exclScorer are positioned on the same candidate document
    return this.toNonExcludedNode();
  }

  /**
   * Advance to an excluded cell. <br>
   * On entry:
   * <ul>
   * <li>reqScorer != null,
   * <li>exclScorer != null,
   * <li>reqScorer and exclScorer were advanced once via
   * {@link #nextCandidateDocument()} or {@link #skipToCandidate(int)} and were
   * positioned on the same candidate document number
   * <li> reqScorer.doc() and reqScorer.node() may still be excluded.
   * </ul>
   * Advances reqScorer to the next non excluded required node, if any.
   *
   * @return true iff the current candidate document has a non excluded required
   * node.
   */
  private boolean toNonExcludedNode() throws IOException {
    IntsRef reqNode = reqScorer.node(); // may be excluded
    IntsRef exclNode = exclScorer.node();

    int comparison;
    while ((comparison = NodeUtils.compare(reqNode, exclNode)) >= 0) {
      // if node equal, advance to next node in reqScorer
      if (comparison == 0 && !reqScorer.nextNode()) {
        return false;
      }

      // if node equal or excluded node ancestor, advance to next node
      if (!exclScorer.nextNode()) {
        return true;
      }

      reqNode = reqScorer.node();
      exclNode = exclScorer.node();
    }
    return true;
  }

  @Override
  public int doc() {
    return reqScorer.doc(); // reqScorer may be null when next() or skipTo()
                            // already return false
  }

  @Override
  public IntsRef node() {
    return reqScorer.node();
  }

  @Override
  public float freqInNode() throws IOException {
    return reqScorer.freqInNode();
  }

  @Override
  public float scoreInNode()
  throws IOException {
    return reqScorer.scoreInNode(); // reqScorer may be null when next() or skipTo()
                                    // already return false
  }

  @Override
  public boolean skipToCandidate(final int target) throws IOException {
    if (exclScorer == null) {
      return reqScorer.skipToCandidate(target);
    }

    if (!reqScorer.skipToCandidate(target)) {
      return false;
    }

    return this.toNonExcludedCandidateDocument();
  }

  @Override
  public String toString() {
    return "NodeReqExclScorer(" + weight + "," + this.doc() + "," +
      this.node() + ")";
  }

}
TOP

Related Classes of org.sindice.siren.search.node.NodeReqExclScorer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.