/* * 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. */ using System; using IndexReader = Lucene.Net.Index.IndexReader; using Term = Lucene.Net.Index.Term; using TermEnum = Lucene.Net.Index.TermEnum; namespace Lucene.Net.Search { /// A Query that matches documents within an exclusive range. /// /// /// $Id: RangeQuery.cs,v 1.3 2005/10/06 19:29:57 dsd Exp $ /// [Serializable] public class RangeQuery:Query { private Term lowerTerm; private Term upperTerm; private bool inclusive; /// Constructs a query selecting all terms greater than /// lowerTerm but less than upperTerm. /// There must be at least one term and either term may be null, /// in which case there is no bound on that side, but if there are /// two terms, both terms must be for the same Field. /// public RangeQuery(Term lowerTerm, Term upperTerm, bool inclusive) { if (lowerTerm == null && upperTerm == null) { throw new System.ArgumentException("At least one term must be non-null"); } if (lowerTerm != null && upperTerm != null && (System.Object) lowerTerm.Field() != (System.Object) upperTerm.Field()) { throw new System.ArgumentException("Both terms must be for the same Field"); } // if we have a lowerTerm, start there. otherwise, start at beginning if (lowerTerm != null) { this.lowerTerm = lowerTerm; } else { this.lowerTerm = new Term(upperTerm.Field(), ""); } this.upperTerm = upperTerm; this.inclusive = inclusive; } public override Query Rewrite(IndexReader reader) { BooleanQuery query = new BooleanQuery(true); TermEnum enumerator = reader.Terms(lowerTerm); try { bool checkLower = false; if (!inclusive) // make adjustments to set to exclusive checkLower = true; System.String testField = GetField(); do { Term term = enumerator.Term(); if (term != null && (System.Object) term.Field() == (System.Object) testField) { if (!checkLower || String.CompareOrdinal(term.Text(), lowerTerm.Text()) > 0) { checkLower = false; if (upperTerm != null) { int compare = String.CompareOrdinal(upperTerm.Text(), term.Text()); /* if beyond the upper term, or is exclusive and * this is equal to the upper term, break out */ if ((compare < 0) || (!inclusive && compare == 0)) break; } TermQuery tq = new TermQuery(term); // found a match tq.SetBoost(GetBoost()); // set the boost query.Add(tq, BooleanClause.Occur.SHOULD); // add to query } } else { break; } } while (enumerator.Next()); } finally { enumerator.Close(); } return query; } public override Query Combine(Query[] queries) { return Query.MergeBooleanQueries(queries); } /// Returns the Field name for this query public virtual System.String GetField() { return (lowerTerm != null?lowerTerm.Field():upperTerm.Field()); } /// Returns the lower term of this range query public virtual Term GetLowerTerm() { return lowerTerm; } /// Returns the upper term of this range query public virtual Term GetUpperTerm() { return upperTerm; } /// Returns true if the range query is inclusive public virtual bool IsInclusive() { return inclusive; } /// Prints a user-readable version of this query. public override System.String ToString(System.String field) { System.Text.StringBuilder buffer = new System.Text.StringBuilder(); if (!GetField().Equals(field)) { buffer.Append(GetField()); buffer.Append(":"); } buffer.Append(inclusive?"[":"{"); buffer.Append(lowerTerm != null?lowerTerm.Text():"null"); buffer.Append(" TO "); buffer.Append(upperTerm != null?upperTerm.Text():"null"); buffer.Append(inclusive?"]":"}"); if (GetBoost() != 1.0f) { System.Globalization.NumberFormatInfo nfi = new System.Globalization.CultureInfo("en-US", false).NumberFormat; nfi.NumberDecimalDigits = 1; buffer.Append("^"); buffer.Append(GetBoost().ToString("N", nfi)); } return buffer.ToString(); } /// Returns true iff o is equal to this. public override bool Equals(System.Object o) { if (this == o) return true; if (!(o is RangeQuery)) return false; RangeQuery other = (RangeQuery) o; if (this.GetBoost() != other.GetBoost()) return false; if (this.inclusive != other.inclusive) return false; // one of lowerTerm and upperTerm can be null if (this.lowerTerm != null ? !this.lowerTerm.Equals(other.lowerTerm) : other.lowerTerm != null) return false; if (this.upperTerm != null ? !this.upperTerm.Equals(other.upperTerm) : other.upperTerm != null) return false; return true; } /// Returns a hash code value for this object. public override int GetHashCode() { return BitConverter.ToInt32(BitConverter.GetBytes(GetBoost()), 0) ^ (lowerTerm != null ? lowerTerm.GetHashCode() : 0) ^ (upperTerm != null ? upperTerm.GetHashCode() : 0) ^ (this.inclusive ? 1 : 0); } } }