[monkeydoc] Merge/add monkeydoc to master.
[mono.git] / mcs / tools / monkeydoc / Lucene.Net / Lucene.Net / Search / FilteredQuery.cs
1 /* 
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  * 
9  * http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 using System;
19
20 using IndexReader = Mono.Lucene.Net.Index.IndexReader;
21 using ToStringUtils = Mono.Lucene.Net.Util.ToStringUtils;
22
23 namespace Mono.Lucene.Net.Search
24 {
25         
26         
27         /// <summary> A query that applies a filter to the results of another query.
28         /// 
29         /// <p/>Note: the bits are retrieved from the filter each time this
30         /// query is used in a search - use a CachingWrapperFilter to avoid
31         /// regenerating the bits every time.
32         /// 
33         /// <p/>Created: Apr 20, 2004 8:58:29 AM
34         /// 
35         /// </summary>
36         /// <since>   1.4
37         /// </since>
38         /// <version>  $Id: FilteredQuery.java 807821 2009-08-25 21:55:49Z mikemccand $
39         /// </version>
40         /// <seealso cref="CachingWrapperFilter">
41         /// </seealso>
42         [Serializable]
43         public class FilteredQuery:Query
44         {
45                 [Serializable]
46                 private class AnonymousClassWeight:Weight
47                 {
48                         public AnonymousClassWeight(Mono.Lucene.Net.Search.Weight weight, Mono.Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance)
49                         {
50                                 InitBlock(weight, similarity, enclosingInstance);
51                         }
52                         private class AnonymousClassScorer:Scorer
53                         {
54                                 private void  InitBlock(Mono.Lucene.Net.Search.Scorer scorer, Mono.Lucene.Net.Search.DocIdSetIterator docIdSetIterator, AnonymousClassWeight enclosingInstance)
55                                 {
56                                         this.scorer = scorer;
57                                         this.docIdSetIterator = docIdSetIterator;
58                                         this.enclosingInstance = enclosingInstance;
59                                 }
60                                 private Mono.Lucene.Net.Search.Scorer scorer;
61                                 private Mono.Lucene.Net.Search.DocIdSetIterator docIdSetIterator;
62                                 private AnonymousClassWeight enclosingInstance;
63                                 public AnonymousClassWeight Enclosing_Instance
64                                 {
65                                         get
66                                         {
67                                                 return enclosingInstance;
68                                         }
69                                         
70                                 }
71                                 internal AnonymousClassScorer(Mono.Lucene.Net.Search.Scorer scorer, Mono.Lucene.Net.Search.DocIdSetIterator docIdSetIterator, AnonymousClassWeight enclosingInstance, Mono.Lucene.Net.Search.Similarity Param1):base(Param1)
72                                 {
73                                         InitBlock(scorer, docIdSetIterator, enclosingInstance);
74                                 }
75                                 
76                                 private int doc = - 1;
77                                 
78                                 private int AdvanceToCommon(int scorerDoc, int disiDoc)
79                                 {
80                                         while (scorerDoc != disiDoc)
81                                         {
82                                                 if (scorerDoc < disiDoc)
83                                                 {
84                                                         scorerDoc = scorer.Advance(disiDoc);
85                                                 }
86                                                 else
87                                                 {
88                                                         disiDoc = docIdSetIterator.Advance(scorerDoc);
89                                                 }
90                                         }
91                                         return scorerDoc;
92                                 }
93                                 
94                                 /// <deprecated> use {@link #NextDoc()} instead. 
95                                 /// </deprecated>
96                 [Obsolete("use NextDoc() instead. ")]
97                                 public override bool Next()
98                                 {
99                                         return NextDoc() != NO_MORE_DOCS;
100                                 }
101                                 
102                                 public override int NextDoc()
103                                 {
104                                         int scorerDoc, disiDoc;
105                                         return doc = (disiDoc = docIdSetIterator.NextDoc()) != NO_MORE_DOCS && (scorerDoc = scorer.NextDoc()) != NO_MORE_DOCS && AdvanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS?scorer.DocID():NO_MORE_DOCS;
106                                 }
107                                 
108                                 /// <deprecated> use {@link #DocID()} instead. 
109                                 /// </deprecated>
110                 [Obsolete("use DocID() instead.")]
111                                 public override int Doc()
112                                 {
113                                         return scorer.Doc();
114                                 }
115                                 public override int DocID()
116                                 {
117                                         return doc;
118                                 }
119                                 
120                                 /// <deprecated> use {@link #Advance(int)} instead. 
121                                 /// </deprecated>
122                 [Obsolete("use Advance(int) instead.")]
123                                 public override bool SkipTo(int i)
124                                 {
125                                         return Advance(i) != NO_MORE_DOCS;
126                                 }
127                                 
128                                 public override int Advance(int target)
129                                 {
130                                         int disiDoc, scorerDoc;
131                                         return doc = (disiDoc = docIdSetIterator.Advance(target)) != NO_MORE_DOCS && (scorerDoc = scorer.Advance(disiDoc)) != NO_MORE_DOCS && AdvanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS?scorer.DocID():NO_MORE_DOCS;
132                                 }
133                                 
134                                 public override float Score()
135                                 {
136                                         return Enclosing_Instance.Enclosing_Instance.GetBoost() * scorer.Score();
137                                 }
138                                 
139                                 // add an explanation about whether the document was filtered
140                                 public override Explanation Explain(int i)
141                                 {
142                                         Explanation exp = scorer.Explain(i);
143                                         
144                                         if (docIdSetIterator.Advance(i) == i)
145                                         {
146                                                 exp.SetDescription("allowed by filter: " + exp.GetDescription());
147                                                 exp.SetValue(Enclosing_Instance.Enclosing_Instance.GetBoost() * exp.GetValue());
148                                         }
149                                         else
150                                         {
151                                                 exp.SetDescription("removed by filter: " + exp.GetDescription());
152                                                 exp.SetValue(0.0f);
153                                         }
154                                         return exp;
155                                 }
156                         }
157                         private void  InitBlock(Mono.Lucene.Net.Search.Weight weight, Mono.Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance)
158                         {
159                                 this.weight = weight;
160                                 this.similarity = similarity;
161                                 this.enclosingInstance = enclosingInstance;
162                         }
163                         private Mono.Lucene.Net.Search.Weight weight;
164                         private Mono.Lucene.Net.Search.Similarity similarity;
165                         private FilteredQuery enclosingInstance;
166                         public FilteredQuery Enclosing_Instance
167                         {
168                                 get
169                                 {
170                                         return enclosingInstance;
171                                 }
172                                 
173                         }
174                         private float value_Renamed;
175                         
176                         // pass these methods through to enclosed query's weight
177                         public override float GetValue()
178                         {
179                                 return value_Renamed;
180                         }
181                         public override float SumOfSquaredWeights()
182                         {
183                                 return weight.SumOfSquaredWeights() * Enclosing_Instance.GetBoost() * Enclosing_Instance.GetBoost();
184                         }
185                         public override void  Normalize(float v)
186                         {
187                                 weight.Normalize(v);
188                                 value_Renamed = weight.GetValue() * Enclosing_Instance.GetBoost();
189                         }
190                         public override Explanation Explain(IndexReader ir, int i)
191                         {
192                                 Explanation inner = weight.Explain(ir, i);
193                                 if (Enclosing_Instance.GetBoost() != 1)
194                                 {
195                                         Explanation preBoost = inner;
196                                         inner = new Explanation(inner.GetValue() * Enclosing_Instance.GetBoost(), "product of:");
197                                         inner.AddDetail(new Explanation(Enclosing_Instance.GetBoost(), "boost"));
198                                         inner.AddDetail(preBoost);
199                                 }
200                                 Filter f = Enclosing_Instance.filter;
201                                 DocIdSet docIdSet = f.GetDocIdSet(ir);
202                                 DocIdSetIterator docIdSetIterator = docIdSet == null?DocIdSet.EMPTY_DOCIDSET.Iterator():docIdSet.Iterator();
203                                 if (docIdSetIterator == null)
204                                 {
205                                         docIdSetIterator = DocIdSet.EMPTY_DOCIDSET.Iterator();
206                                 }
207                                 if (docIdSetIterator.Advance(i) == i)
208                                 {
209                                         return inner;
210                                 }
211                                 else
212                                 {
213                                         Explanation result = new Explanation(0.0f, "failure to match filter: " + f.ToString());
214                                         result.AddDetail(inner);
215                                         return result;
216                                 }
217                         }
218                         
219                         // return this query
220                         public override Query GetQuery()
221                         {
222                                 return Enclosing_Instance;
223                         }
224                         
225                         // return a filtering scorer
226                         public override Scorer Scorer(IndexReader indexReader, bool scoreDocsInOrder, bool topScorer)
227                         {
228                                 Scorer scorer = weight.Scorer(indexReader, true, false);
229                                 if (scorer == null)
230                                 {
231                                         return null;
232                                 }
233                                 DocIdSet docIdSet = Enclosing_Instance.filter.GetDocIdSet(indexReader);
234                                 if (docIdSet == null)
235                                 {
236                                         return null;
237                                 }
238                                 DocIdSetIterator docIdSetIterator = docIdSet.Iterator();
239                                 if (docIdSetIterator == null)
240                                 {
241                                         return null;
242                                 }
243                                 
244                                 return new AnonymousClassScorer(scorer, docIdSetIterator, this, similarity);
245                         }
246                 }
247                 
248                 internal Query query;
249                 internal Filter filter;
250                 
251                 /// <summary> Constructs a new query which applies a filter to the results of the original query.
252                 /// Filter.getDocIdSet() will be called every time this query is used in a search.
253                 /// </summary>
254                 /// <param name="query"> Query to be filtered, cannot be <code>null</code>.
255                 /// </param>
256                 /// <param name="filter">Filter to apply to query results, cannot be <code>null</code>.
257                 /// </param>
258                 public FilteredQuery(Query query, Filter filter)
259                 {
260                         this.query = query;
261                         this.filter = filter;
262                 }
263                 
264                 /// <summary> Returns a Weight that applies the filter to the enclosed query's Weight.
265                 /// This is accomplished by overriding the Scorer returned by the Weight.
266                 /// </summary>
267                 public override Weight CreateWeight(Searcher searcher)
268                 {
269                         Weight weight = query.CreateWeight(searcher);
270                         Similarity similarity = query.GetSimilarity(searcher);
271                         return new AnonymousClassWeight(weight, similarity, this);
272                 }
273                 
274                 /// <summary>Rewrites the wrapped query. </summary>
275                 public override Query Rewrite(IndexReader reader)
276                 {
277                         Query rewritten = query.Rewrite(reader);
278                         if (rewritten != query)
279                         {
280                                 FilteredQuery clone = (FilteredQuery) this.Clone();
281                                 clone.query = rewritten;
282                                 return clone;
283                         }
284                         else
285                         {
286                                 return this;
287                         }
288                 }
289                 
290                 public virtual Query GetQuery()
291                 {
292                         return query;
293                 }
294                 
295                 public virtual Filter GetFilter()
296                 {
297                         return filter;
298                 }
299                 
300                 // inherit javadoc
301                 public override void  ExtractTerms(System.Collections.Hashtable terms)
302                 {
303                         GetQuery().ExtractTerms(terms);
304                 }
305                 
306                 /// <summary>Prints a user-readable version of this query. </summary>
307                 public override System.String ToString(System.String s)
308                 {
309                         System.Text.StringBuilder buffer = new System.Text.StringBuilder();
310                         buffer.Append("filtered(");
311                         buffer.Append(query.ToString(s));
312                         buffer.Append(")->");
313                         buffer.Append(filter);
314                         buffer.Append(ToStringUtils.Boost(GetBoost()));
315                         return buffer.ToString();
316                 }
317                 
318                 /// <summary>Returns true iff <code>o</code> is equal to this. </summary>
319                 public  override bool Equals(System.Object o)
320                 {
321                         if (o is FilteredQuery)
322                         {
323                                 FilteredQuery fq = (FilteredQuery) o;
324                                 return (query.Equals(fq.query) && filter.Equals(fq.filter) && GetBoost() == fq.GetBoost());
325                         }
326                         return false;
327                 }
328                 
329                 /// <summary>Returns a hash code value for this object. </summary>
330                 public override int GetHashCode()
331                 {
332                         return query.GetHashCode() ^ filter.GetHashCode() + System.Convert.ToInt32(GetBoost());
333                 }
334         }
335 }