diff --git a/src/java/org/apache/lucene/search/BooleanClause.java b/src/java/org/apache/lucene/search/BooleanClause.java index 71add59ebac..846725ff093 100644 --- a/src/java/org/apache/lucene/search/BooleanClause.java +++ b/src/java/org/apache/lucene/search/BooleanClause.java @@ -18,23 +18,117 @@ package org.apache.lucene.search; /** A clause in a BooleanQuery. */ public class BooleanClause implements java.io.Serializable { - /** The query whose matching documents are combined by the boolean query. */ - public Query query; - /** If true, documents documents which do not - match this sub-query will not match the boolean query. */ - public boolean required = false; - /** If true, documents documents which do - match this sub-query will not match the boolean query. */ - public boolean prohibited = false; + public static final class Occur { + + private String name; + + private Occur() { + // typesafe enum pattern, no public constructor + } + + private Occur(String name) { + // typesafe enum pattern, no public constructor + this.name = name; + } + + public String toString() { + return name; + } + + /** Use this operator for terms that must appear in the matching documents. */ + public static final Occur MUST = new Occur("MUST"); + /** Use this operator for terms of which should appear in the + * matching documents. For a BooleanQuery with two SHOULD + * subqueries, at least one of the queries must appear in the matching documents. */ + public static final Occur SHOULD = new Occur("SHOULD"); + /** Use this operator for terms that must not appear in the matching documents. + * Note that it is not possible to search for queries that only consist + * of a MUST_NOT query. */ + public static final Occur MUST_NOT = new Occur("MUST_NOT"); + + } + + /** The query whose matching documents are combined by the boolean query. + * @deprecated use {@link #setQuery(Query)} instead */ + public Query query; // TODO: decrease visibility for Lucene 2.0 + + /** If true, documents documents which do not + match this sub-query will not match the boolean query. + @deprecated use {@link #setOccur(BooleanClause.Occur)} instead */ + public boolean required = false; // TODO: decrease visibility for Lucene 2.0 + + /** If true, documents documents which do + match this sub-query will not match the boolean query. + @deprecated use {@link #setOccur(BooleanClause.Occur)} instead */ + public boolean prohibited = false; // TODO: decrease visibility for Lucene 2.0 + + private Occur occur; + /** Constructs a BooleanClause with query q, required - r and prohibited p. */ + * r and prohibited p. + * @deprecated use BooleanClause(Query, Occur) instead + * + */ public BooleanClause(Query q, boolean r, boolean p) { + // TODO: remove for Lucene 2.0 query = q; required = r; prohibited = p; } + /** Constructs a BooleanClause. + */ + public BooleanClause(Query query, Occur occur) { + this.query = query; + this.occur = occur; + setFields(occur); + } + + public Occur getOccur() { + return occur; + } + + public void setOccur(Occur occur) { + this.occur = occur; + setFields(occur); + } + + public Query getQuery() { + return query; + } + + public void setQuery(Query query) { + this.query = query; + } + + public boolean isProhibited() { + return prohibited; + } + + public boolean isRequired() { + return required; + } + + private void setFields(Occur occur) { + if (occur == Occur.MUST) { + required = true; + prohibited = false; + } else if (occur == Occur.SHOULD) { + required = false; + prohibited = false; + } else if (occur == Occur.MUST_NOT) { + required = false; + prohibited = true; + } else { + throw new IllegalArgumentException("Unknown operator " + occur); + } + } + /** Returns true iff o is equal to this. */ public boolean equals(Object o) { if (!(o instanceof BooleanClause)) diff --git a/src/java/org/apache/lucene/search/BooleanQuery.java b/src/java/org/apache/lucene/search/BooleanQuery.java index 654e5f2e386..6cca7384798 100644 --- a/src/java/org/apache/lucene/search/BooleanQuery.java +++ b/src/java/org/apache/lucene/search/BooleanQuery.java @@ -24,7 +24,7 @@ import org.apache.lucene.index.IndexReader; queries, typically {@link TermQuery}s or {@link PhraseQuery}s. */ public class BooleanQuery extends Query { - + /** * Default value is 1024. Use org.apache.lucene.maxClauseCount * system property to override. @@ -65,14 +65,29 @@ public class BooleanQuery extends Query { * It is an error to specify a clause as both required and * prohibited. * - * @see #getMaxClauseCount() + * @deprecated use {@link #add(Query, BooleanClause.Occur)} instead: + * */ public void add(Query query, boolean required, boolean prohibited) { add(new BooleanClause(query, required, prohibited)); } /** Adds a clause to a boolean query. - * @see #getMaxClauseCount() + * + * @throws TooManyClauses if the new number of clauses exceeds the maximum clause number + * @see #getMaxClauseCount() + */ + public void add(Query query, BooleanClause.Occur occur) { + add(new BooleanClause(query, occur)); + } + + /** Adds a clause to a boolean query. + * @throws TooManyClauses if the new number of clauses exceeds the maximum clause number + * @see #getMaxClauseCount() */ public void add(BooleanClause clause) { if (clauses.size() >= maxClauseCount) @@ -94,7 +109,7 @@ public class BooleanQuery extends Query { this.searcher = searcher; for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); - weights.add(c.query.createWeight(searcher)); + weights.add(c.getQuery().createWeight(searcher)); } } @@ -106,7 +121,7 @@ public class BooleanQuery extends Query { for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); - if (!c.prohibited) + if (!c.isProhibited()) sum += w.sumOfSquaredWeights(); // sum sub weights } @@ -121,7 +136,7 @@ public class BooleanQuery extends Query { for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); - if (!c.prohibited) + if (!c.isProhibited()) w.normalize(norm); } } @@ -137,9 +152,9 @@ public class BooleanQuery extends Query { boolean noneBoolean = true; for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); - if (!c.required) + if (!c.isRequired()) allRequired = false; - if (c.query instanceof BooleanQuery) + if (c.getQuery() instanceof BooleanQuery) noneBoolean = false; } @@ -164,8 +179,8 @@ public class BooleanQuery extends Query { Weight w = (Weight)weights.elementAt(i); Scorer subScorer = w.scorer(reader); if (subScorer != null) - result.add(subScorer, c.required, c.prohibited); - else if (c.required) + result.add(subScorer, c.isRequired(), c.isProhibited()); + else if (c.isRequired()) return null; } @@ -183,16 +198,16 @@ public class BooleanQuery extends Query { BooleanClause c = (BooleanClause)clauses.elementAt(i); Weight w = (Weight)weights.elementAt(i); Explanation e = w.explain(reader, doc); - if (!c.prohibited) maxCoord++; + if (!c.isProhibited()) maxCoord++; if (e.getValue() > 0) { - if (!c.prohibited) { + if (!c.isProhibited()) { sumExpl.addDetail(e); sum += e.getValue(); coord++; } else { return new Explanation(0.0f, "match prohibited"); } - } else if (c.required) { + } else if (c.isRequired()) { return new Explanation(0.0f, "match required"); } } @@ -223,12 +238,12 @@ public class BooleanQuery extends Query { 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 + if (!c.isProhibited()) { // just return clause - Query query = c.query.rewrite(reader); // rewrite first + Query query = c.getQuery().rewrite(reader); // rewrite first if (getBoost() != 1.0f) { // incorporate boost - if (query == c.query) // if rewrite was no-op + if (query == c.getQuery()) // if rewrite was no-op query = (Query)query.clone(); // then clone before boost query.setBoost(getBoost() * query.getBoost()); } @@ -240,12 +255,12 @@ public class BooleanQuery extends 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 + Query query = c.getQuery().rewrite(reader); + if (query != c.getQuery()) { // clause rewrote: must clone if (clone == null) clone = (BooleanQuery)this.clone(); clone.clauses.setElementAt - (new BooleanClause(query, c.required, c.prohibited), i); + (new BooleanClause(query, c.getOccur()), i); } } if (clone != null) { @@ -270,18 +285,18 @@ public class BooleanQuery extends Query { for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); - if (c.prohibited) + if (c.isProhibited()) buffer.append("-"); - else if (c.required) + else if (c.isRequired()) buffer.append("+"); - Query subQuery = c.query; + Query subQuery = c.getQuery(); if (subQuery instanceof BooleanQuery) { // wrap sub-bools in parens buffer.append("("); - buffer.append(c.query.toString(field)); + buffer.append(c.getQuery().toString(field)); buffer.append(")"); } else - buffer.append(c.query.toString(field)); + buffer.append(c.getQuery().toString(field)); if (i != clauses.size()-1) buffer.append(" ");