/* * 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. */ using System; using IndexReader = Lucene.Net.Index.IndexReader; using ToStringUtils = Lucene.Net.Util.ToStringUtils; namespace Lucene.Net.Search { /// A query that applies a filter to the results of another query. /// ///

Note: the bits are retrieved from the filter each time this /// query is used in a search - use a CachingWrapperFilter to avoid /// regenerating the bits every time. /// ///

Created: Apr 20, 2004 8:58:29 AM /// ///

/// Tim Jones /// /// 1.4 /// /// $Id: FilteredQuery.java 472959 2006-11-09 16:21:50Z yonik $ /// /// /// [Serializable] public class FilteredQuery : Query { [Serializable] private class AnonymousClassWeight : Weight { public AnonymousClassWeight(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance) { InitBlock(weight, similarity, enclosingInstance); } private class AnonymousClassScorer : Scorer { private void InitBlock(System.Collections.BitArray bitset, Lucene.Net.Search.Scorer scorer, AnonymousClassWeight enclosingInstance) { this.bitset = bitset; this.scorer = scorer; this.enclosingInstance = enclosingInstance; } private System.Collections.BitArray bitset; private Lucene.Net.Search.Scorer scorer; private AnonymousClassWeight enclosingInstance; public AnonymousClassWeight Enclosing_Instance { get { return enclosingInstance; } } internal AnonymousClassScorer(System.Collections.BitArray bitset, Lucene.Net.Search.Scorer scorer, AnonymousClassWeight enclosingInstance, Lucene.Net.Search.Similarity Param1):base(Param1) { InitBlock(bitset, scorer, enclosingInstance); } public override bool Next() { do { if (!scorer.Next()) { return false; } } while (!bitset.Get(scorer.Doc())); /* When skipTo() is allowed on scorer it should be used here * in combination with bitset.nextSetBit(...) * See the while loop in skipTo() below. */ return true; } public override int Doc() { return scorer.Doc(); } public override bool SkipTo(int i) { if (!scorer.SkipTo(i)) { return false; } while (!bitset.Get(scorer.Doc())) { int nextFiltered = SupportClass.Number.NextSetBit(bitset, scorer.Doc() + 1); if (nextFiltered == - 1) { return false; } else if (!scorer.SkipTo(nextFiltered)) { return false; } } return true; } public override float Score() { return scorer.Score(); } // add an explanation about whether the document was filtered public override Explanation Explain(int i) { Explanation exp = scorer.Explain(i); if (bitset.Get(i)) exp.SetDescription("allowed by filter: " + exp.GetDescription()); else exp.SetDescription("removed by filter: " + exp.GetDescription()); return exp; } } private void InitBlock(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance) { this.weight = weight; this.similarity = similarity; this.enclosingInstance = enclosingInstance; } private Lucene.Net.Search.Weight weight; private Lucene.Net.Search.Similarity similarity; private FilteredQuery enclosingInstance; public FilteredQuery Enclosing_Instance { get { return enclosingInstance; } } // pass these methods through to enclosed query's weight public virtual float GetValue() { return weight.GetValue(); } public virtual float SumOfSquaredWeights() { return weight.SumOfSquaredWeights(); } public virtual void Normalize(float v) { weight.Normalize(v); } public virtual Explanation Explain(IndexReader ir, int i) { Explanation inner = weight.Explain(ir, i); Filter f = Enclosing_Instance.filter; System.Collections.BitArray matches = f.Bits(ir); if (matches.Get(i)) return inner; Explanation result = new Explanation(0.0f, "failure to match filter: " + f.ToString()); result.AddDetail(inner); return result; } // return this query public virtual Query GetQuery() { return Enclosing_Instance; } // return a filtering scorer public virtual Scorer Scorer(IndexReader indexReader) { Scorer scorer = weight.Scorer(indexReader); System.Collections.BitArray bitset = Enclosing_Instance.filter.Bits(indexReader); return new AnonymousClassScorer(bitset, scorer, this, similarity); } } internal Query query; internal Filter filter; /// Constructs a new query which applies a filter to the results of the original query. /// Filter.bits() will be called every time this query is used in a search. /// /// Query to be filtered, cannot be null. /// /// Filter to apply to query results, cannot be null. /// public FilteredQuery(Query query, Filter filter) { this.query = query; this.filter = filter; } /// Returns a Weight that applies the filter to the enclosed query's Weight. /// This is accomplished by overriding the Scorer returned by the Weight. /// protected internal override Weight CreateWeight(Searcher searcher) { Weight weight = query.CreateWeight(searcher); Similarity similarity = query.GetSimilarity(searcher); return new AnonymousClassWeight(weight, similarity, this); } /// Rewrites the wrapped query. public override Query Rewrite(IndexReader reader) { Query rewritten = query.Rewrite(reader); if (rewritten != query) { FilteredQuery clone = (FilteredQuery) this.Clone(); clone.query = rewritten; return clone; } else { return this; } } public virtual Query GetQuery() { return query; } public virtual Filter GetFilter() { return filter; } // inherit javadoc public override void ExtractTerms(System.Collections.Hashtable terms) { GetQuery().ExtractTerms(terms); } /// Prints a user-readable version of this query. public override System.String ToString(System.String s) { System.Text.StringBuilder buffer = new System.Text.StringBuilder(); buffer.Append("filtered("); buffer.Append(query.ToString(s)); buffer.Append(")->"); buffer.Append(filter); buffer.Append(ToStringUtils.Boost(GetBoost())); return buffer.ToString(); } /// Returns true iff o is equal to this. public override bool Equals(System.Object o) { if (o is FilteredQuery) { FilteredQuery fq = (FilteredQuery) o; return (query.Equals(fq.query) && filter.Equals(fq.filter) && GetBoost() == fq.GetBoost()); } return false; } /// Returns a hash code value for this object. public override int GetHashCode() { return query.GetHashCode() ^ filter.GetHashCode() + System.Convert.ToInt32(GetBoost()); } override public System.Object Clone() { // {{Aroush-2.0}} is this Clone() OK? FilteredQuery clone = (FilteredQuery) base.Clone(); clone.filter = this.filter; clone.query = this.query; return clone; } } }