package org.apache.lucene.search; /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.HashSet; import java.util.Iterator; import java.util.Set; import org.apache.lucene.index.IndexReader; /** The abstract base class for queries.

Instantiable subclasses are:

A parser for queries is contained in:

*/ public abstract class Query implements java.io.Serializable, Cloneable { private float boost = 1.0f; // query boost factor /** Sets the boost for this query clause to b. Documents * matching this clause will (in addition to the normal weightings) have * their score multiplied by b. */ public void setBoost(float b) { boost = b; } /** Gets the boost for this clause. Documents matching * this clause will (in addition to the normal weightings) have their score * multiplied by b. The boost is 1.0 by default. */ public float getBoost() { return boost; } /** Prints a query to a string, with field assumed to be the * default field and omitted. *

The representation used is one that is supposed to be readable * by {@link org.apache.lucene.queryParser.QueryParser QueryParser}. However, * there are the following limitations: *

*/ public abstract String toString(String field); /** Prints a query to a string. */ public String toString() { return toString(""); } /** Expert: Constructs an appropriate Weight implementation for this query. * *

Only implemented by primitive queries, which re-write to themselves. */ protected Weight createWeight(Searcher searcher) throws IOException { throw new UnsupportedOperationException(); } /** Expert: Constructs and initializes a Weight for a top-level query. */ public Weight weight(Searcher searcher) throws IOException { Query query = searcher.rewrite(this); Weight weight = query.createWeight(searcher); float sum = weight.sumOfSquaredWeights(); float norm = getSimilarity(searcher).queryNorm(sum); weight.normalize(norm); return weight; } /** Expert: called to re-write queries into primitive queries. For example, * a PrefixQuery will be rewritten into a BooleanQuery that consists * of TermQuerys. */ public Query rewrite(IndexReader reader) throws IOException { return this; } /** Expert: called when re-writing queries under MultiSearcher. * * Create a single query suitable for use by all subsearchers (in 1-1 * correspondence with queries). This is an optimization of the OR of * all queries. We handle the common optimization cases of equal * queries and overlapping clauses of boolean OR queries (as generated * by MultiTermQuery.rewrite() and RangeQuery.rewrite()). * Be careful overriding this method as queries[0] determines which * method will be called and is not necessarily of the same type as * the other queries. */ public Query combine(Query[] queries) { HashSet uniques = new HashSet(); for (int i = 0; i < queries.length; i++) { Query query = queries[i]; BooleanClause[] clauses = null; // check if we can split the query into clauses boolean splittable = (query instanceof BooleanQuery); if(splittable){ BooleanQuery bq = (BooleanQuery) query; splittable = bq.isCoordDisabled(); clauses = bq.getClauses(); for (int j = 0; splittable && j < clauses.length; j++) { splittable = (clauses[j].getOccur() == BooleanClause.Occur.SHOULD); } } if(splittable){ for (int j = 0; j < clauses.length; j++) { uniques.add(clauses[j].getQuery()); } } else { uniques.add(query); } } // optimization: if we have just one query, just return it if(uniques.size() == 1){ return (Query)uniques.iterator().next(); } Iterator it = uniques.iterator(); BooleanQuery result = new BooleanQuery(true); while (it.hasNext()) result.add((Query) it.next(), BooleanClause.Occur.SHOULD); return result; } /** * Expert: adds all terms occuring in this query to the terms set. Only * works if this query is in its {@link #rewrite rewritten} form. * * @throws UnsupportedOperationException if this query is not yet rewritten */ public void extractTerms(Set terms) { // needs to be implemented by query subclasses throw new UnsupportedOperationException(); } /** Expert: merges the clauses of a set of BooleanQuery's into a single * BooleanQuery. * *

A utility for use by {@link #combine(Query[])} implementations. */ public static Query mergeBooleanQueries(Query[] queries) { HashSet allClauses = new HashSet(); for (int i = 0; i < queries.length; i++) { BooleanClause[] clauses = ((BooleanQuery)queries[i]).getClauses(); for (int j = 0; j < clauses.length; j++) { allClauses.add(clauses[j]); } } boolean coordDisabled = queries.length==0? false : ((BooleanQuery)queries[0]).isCoordDisabled(); BooleanQuery result = new BooleanQuery(coordDisabled); Iterator i = allClauses.iterator(); while (i.hasNext()) { result.add((BooleanClause)i.next()); } return result; } /** Expert: Returns the Similarity implementation to be used for this query. * Subclasses may override this method to specify their own Similarity * implementation, perhaps one that delegates through that of the Searcher. * By default the Searcher's Similarity implementation is returned.*/ public Similarity getSimilarity(Searcher searcher) { return searcher.getSimilarity(); } /** Returns a clone of this query. */ public Object clone() { try { return (Query)super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException("Clone not supported: " + e.getMessage()); } } }