/* * 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; 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.cs,v 1.2 2005/10/06 19:29:57 dsd Exp $ /// /// /// [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(Lucene.Net.Search.Scorer scorer, System.Collections.BitArray bitset, AnonymousClassWeight enclosingInstance) { this.scorer = scorer; this.bitset = bitset; this.enclosingInstance = enclosingInstance; } private Lucene.Net.Search.Scorer scorer; private System.Collections.BitArray bitset; private AnonymousClassWeight enclosingInstance; public AnonymousClassWeight Enclosing_Instance { get { return enclosingInstance; } } internal AnonymousClassScorer(Lucene.Net.Search.Scorer scorer, System.Collections.BitArray bitset, AnonymousClassWeight enclosingInstance, Lucene.Net.Search.Similarity Param1) : base(Param1) { InitBlock(scorer, bitset, enclosingInstance); } // pass these methods through to the enclosed scorer public override bool Next() { return scorer.Next(); } public override int Doc() { return scorer.Doc(); } public override bool SkipTo(int i) { return scorer.SkipTo(i); } // if the document has been filtered out, set score to 0.0 public override float Score() { return (bitset.Get(scorer.Doc()))?scorer.Score():0.0f; } // 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; virtual public Query GetQuery() { return Enclosing_Instance; } 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) { return weight.Explain(ir, i); } // return a scorer that overrides the enclosed query's score if // the given hit has been filtered out. public virtual Scorer Scorer(IndexReader indexReader) { Scorer scorer = weight.Scorer(indexReader); System.Collections.BitArray bitset = Enclosing_Instance.filter.Bits(indexReader); return new AnonymousClassScorer(scorer, bitset, 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; } // 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) { return "filtered(" + query.ToString(s) + ")->" + filter; } /// 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)); } return false; } /// Returns a hash code value for this object. public override int GetHashCode() { return query.GetHashCode() ^ filter.GetHashCode(); } } }