--- /dev/null
+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.Set;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+
+/** The abstract base class for queries.
+ <p>Instantiable subclasses are:
+ <ul>
+ <li> {@link TermQuery}
+ <li> {@link MultiTermQuery}
+ <li> {@link BooleanQuery}
+ <li> {@link WildcardQuery}
+ <li> {@link PhraseQuery}
+ <li> {@link PrefixQuery}
+ <li> {@link MultiPhraseQuery}
+ <li> {@link FuzzyQuery}
+ <li> {@link TermRangeQuery}
+ <li> {@link NumericRangeQuery}
+ <li> {@link org.apache.lucene.search.spans.SpanQuery}
+ </ul>
+ <p>A parser for queries is contained in:
+ <ul>
+ <li>{@link org.apache.lucene.queryParser.QueryParser QueryParser}
+ </ul>
+*/
+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 <code>b</code>. Documents
+ * matching this clause will (in addition to the normal weightings) have
+ * their score multiplied by <code>b</code>.
+ */
+ 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 <code>b</code>. The boost is 1.0 by default.
+ */
+ public float getBoost() { return boost; }
+
+ /** Prints a query to a string, with <code>field</code> assumed to be the
+ * default field and omitted.
+ * <p>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:
+ * <ul>
+ * <li>If the query was created by the parser, the printed
+ * representation may not be exactly what was parsed. For example,
+ * characters that need to be escaped will be represented without
+ * the required backslash.</li>
+ * <li>Some of the more complicated queries (e.g. span queries)
+ * don't have a representation that can be parsed by QueryParser.</li>
+ * </ul>
+ */
+ public abstract String toString(String field);
+
+ /** Prints a query to a string. */
+ @Override
+ public String toString() {
+ return toString("");
+ }
+
+ /**
+ * Expert: Constructs an appropriate Weight implementation for this query.
+ *
+ * <p>
+ * Only implemented by primitive queries, which re-write to themselves.
+ */
+ public Weight createWeight(Searcher searcher) throws IOException {
+ throw new UnsupportedOperationException("Query " + this + " does not implement createWeight");
+ }
+
+ /**
+ * Expert: Constructs and initializes a Weight for a <b>top-level</b> query.
+ * @deprecated never ever use this method in {@link Weight} implementations.
+ * Subclasses of {@code Query} should use {@link #createWeight}, instead.
+ */
+ @Deprecated
+ public final Weight weight(Searcher searcher) throws IOException {
+ return searcher.createNormalizedWeight(this);
+ }
+
+
+ /** 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()).
+ * 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<Query> uniques = new HashSet<Query>();
+ 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 uniques.iterator().next();
+ }
+ BooleanQuery result = new BooleanQuery(true);
+ for (final Query query : uniques)
+ result.add(query, BooleanClause.Occur.SHOULD);
+ return result;
+ }
+
+
+ /**
+ * Expert: adds all terms occurring 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<Term> 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.
+ *
+ *<p>A utility for use by {@link #combine(Query[])} implementations.
+ */
+ public static Query mergeBooleanQueries(BooleanQuery... queries) {
+ HashSet<BooleanClause> allClauses = new HashSet<BooleanClause>();
+ for (BooleanQuery booleanQuery : queries) {
+ for (BooleanClause clause : booleanQuery) {
+ allClauses.add(clause);
+ }
+ }
+
+ boolean coordDisabled =
+ queries.length==0? false : queries[0].isCoordDisabled();
+ BooleanQuery result = new BooleanQuery(coordDisabled);
+ for(BooleanClause clause2 : allClauses) {
+ result.add(clause2);
+ }
+ 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.
+ * @deprecated Instead of using "runtime" subclassing/delegation, subclass the Weight instead.
+ */
+ @Deprecated
+ public Similarity getSimilarity(Searcher searcher) {
+ return searcher.getSimilarity();
+ }
+
+ /** Returns a clone of this query. */
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException("Clone not supported: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Float.floatToIntBits(boost);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Query other = (Query) obj;
+ if (Float.floatToIntBits(boost) != Float.floatToIntBits(other.boost))
+ return false;
+ return true;
+ }
+}