All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gate.creole.annic.apache.lucene.search.BooleanQuery Maven / Gradle / Ivy

package gate.creole.annic.apache.lucene.search;

/**
 * Copyright 2004 The Apache Software Foundation
 *
 * 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.
 */

import java.io.IOException;
import java.util.Vector;
import gate.creole.annic.apache.lucene.index.IndexReader;

/** A Query that matches documents matching boolean combinations of other
  queries, typically {@link TermQuery}s or {@link PhraseQuery}s.
  */
@SuppressWarnings({"serial","rawtypes","unchecked"})
public class BooleanQuery extends Query {

  /**
   * Default value is 1024.  Use gate.creole.annic.apache.lucene.maxClauseCount
   * system property to override.
   */
  public static int maxClauseCount =
    Integer.parseInt(System.getProperty("gate.creole.annic.apache.lucene.maxClauseCount",
      "1024"));

  /** Thrown when an attempt is made to add more than {@link
   * #getMaxClauseCount()} clauses. */
  public static class TooManyClauses extends RuntimeException {}

  /** Return the maximum number of clauses permitted, 1024 by default.
   * Attempts to add more than the permitted number of clauses cause {@link
   * TooManyClauses} to be thrown.*/
  public static int getMaxClauseCount() { return maxClauseCount; }

  /** Set the maximum number of clauses permitted. */
  public static void setMaxClauseCount(int maxClauseCount) {
    BooleanQuery.maxClauseCount = maxClauseCount;
  }

  private Vector clauses = new Vector();

  /** Constructs an empty boolean query. */
  public BooleanQuery() {}

  /** Adds a clause to a boolean query.  Clauses may be:
   * 
    *
  • required which means that documents which do not * match this sub-query will not match the boolean query; *
  • prohibited which means that documents which do * match this sub-query will not match the boolean query; or *
  • neither, in which case matched documents are neither prohibited from * nor required to match the sub-query. However, a document must match at * least 1 sub-query to match the boolean query. *
* It is an error to specify a clause as both required and * prohibited. * * @see #getMaxClauseCount() */ public void add(Query query, boolean required, boolean prohibited) { add(new BooleanClause(query, required, prohibited)); } /** Adds a clause to a boolean query. * @see #getMaxClauseCount() */ public void add(BooleanClause clause) { if (clauses.size() >= maxClauseCount) throw new TooManyClauses(); clauses.addElement(clause); } /** Returns the set of clauses in this query. */ public BooleanClause[] getClauses() { return (BooleanClause[])clauses.toArray(new BooleanClause[0]); } private class BooleanWeight implements Weight { private Searcher searcher; private Vector weights = new Vector(); public BooleanWeight(Searcher searcher) { this.searcher = searcher; for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); weights.add(c.query.createWeight(searcher)); } } @Override public Query getQuery() { return BooleanQuery.this; } @Override public float getValue() { return getBoost(); } @Override public float sumOfSquaredWeights() throws IOException { float sum = 0.0f; for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); if (!c.prohibited) sum += w.sumOfSquaredWeights(); // sum sub weights } sum *= getBoost() * getBoost(); // boost each sub-weight return sum ; } @Override public void normalize(float norm) { norm *= getBoost(); // incorporate boost for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); if (!c.prohibited) w.normalize(norm); } } @Override public Scorer scorer(IndexReader reader, Searcher searcher) throws IOException { this.searcher = searcher; // First see if the (faster) ConjunctionScorer will work. This can be // used when all clauses are required. Also, at this point a // BooleanScorer cannot be embedded in a ConjunctionScorer, as the hits // from a BooleanScorer are not always sorted by document number (sigh) // and hence BooleanScorer cannot implement skipTo() correctly, which is // required by ConjunctionScorer. boolean allRequired = true; boolean noneBoolean = true; for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); if (!c.required) allRequired = false; if (c.query instanceof BooleanQuery) noneBoolean = false; } if (allRequired && noneBoolean) { // ConjunctionScorer is okay ConjunctionScorer result = new ConjunctionScorer(getSimilarity(searcher)); for (int i = 0 ; i < weights.size(); i++) { Weight w = (Weight)weights.elementAt(i); Scorer subScorer = w.scorer(reader, searcher); if (subScorer == null) return null; result.add(subScorer); } return result; } // Use good-old BooleanScorer instead. BooleanScorer result = new BooleanScorer(getSimilarity(searcher)); for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); Scorer subScorer = w.scorer(reader, searcher); if (subScorer != null) result.add(subScorer, c.required, c.prohibited); else if (c.required) return null; } return result; } @Override public Explanation explain(IndexReader reader, int doc) throws IOException { Explanation sumExpl = new Explanation(); sumExpl.setDescription("sum of:"); int coord = 0; int maxCoord = 0; float sum = 0.0f; for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); Explanation e = w.explain(reader, doc); if (!c.prohibited) maxCoord++; if (e.getValue() > 0) { if (!c.prohibited) { sumExpl.addDetail(e); sum += e.getValue(); coord++; } else { return new Explanation(0.0f, "match prohibited"); } } else if (c.required) { return new Explanation(0.0f, "match required"); } } sumExpl.setValue(sum); if (coord == 1) // only one clause matched sumExpl = sumExpl.getDetails()[0]; // eliminate wrapper float coordFactor = getSimilarity(searcher).coord(coord, maxCoord); if (coordFactor == 1.0f) // coord is no-op return sumExpl; // eliminate wrapper else { Explanation result = new Explanation(); result.setDescription("product of:"); result.addDetail(sumExpl); result.addDetail(new Explanation(coordFactor, "coord("+coord+"/"+maxCoord+")")); result.setValue(sum*coordFactor); return result; } } } @Override protected Weight createWeight(Searcher searcher) { return new BooleanWeight(searcher); } @Override public Query rewrite(IndexReader reader) throws IOException { if (clauses.size() == 1) { // optimize 1-clause queries BooleanClause c = (BooleanClause)clauses.elementAt(0); if (!c.prohibited) { // just return clause Query query = c.query.rewrite(reader); // rewrite first if (getBoost() != 1.0f) { // incorporate boost if (query == c.query) // if rewrite was no-op query = (Query)query.clone(); // then clone before boost query.setBoost(getBoost() * query.getBoost()); } return query; } } BooleanQuery clone = null; // recursively rewrite for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Query query = c.query.rewrite(reader); if (query != c.query) { // clause rewrote: must clone if (clone == null) clone = (BooleanQuery)this.clone(); clone.clauses.setElementAt (new BooleanClause(query, c.required, c.prohibited), i); } } if (clone != null) { return clone; // some clauses rewrote } else return this; // no clauses rewrote } @Override public Object clone() { BooleanQuery clone = (BooleanQuery)super.clone(); clone.clauses = (Vector)this.clauses.clone(); return clone; } /** Prints a user-readable version of this query. */ @Override public String toString(String field) { StringBuffer buffer = new StringBuffer(); if (getBoost() != 1.0) { buffer.append("("); } for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); if (c.prohibited) buffer.append("-"); else if (c.required) buffer.append("+"); Query subQuery = c.query; if (subQuery instanceof BooleanQuery) { // wrap sub-bools in parens buffer.append("("); buffer.append(c.query.toString(field)); buffer.append(")"); } else buffer.append(c.query.toString(field)); if (i != clauses.size()-1) buffer.append(" "); } if (getBoost() != 1.0) { buffer.append(")^"); buffer.append(getBoost()); } return buffer.toString(); } /** Returns true iff o is equal to this. */ @Override public boolean equals(Object o) { if (!(o instanceof BooleanQuery)) return false; BooleanQuery other = (BooleanQuery)o; return (this.getBoost() == other.getBoost()) && this.clauses.equals(other.clauses); } /** Returns a hash code value for this object.*/ @Override public int hashCode() { return Float.floatToIntBits(getBoost()) ^ clauses.hashCode(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy