Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
SpanOrQuery.cs
Go to the documentation of this file.
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 using System.Collections.Generic;
20 using Lucene.Net.Index;
21 using Lucene.Net.Support;
22 using Lucene.Net.Util;
23 using IndexReader = Lucene.Net.Index.IndexReader;
24 using ToStringUtils = Lucene.Net.Util.ToStringUtils;
25 using Query = Lucene.Net.Search.Query;
26 
27 namespace Lucene.Net.Search.Spans
28 {
29 
30  /// <summary>Matches the union of its clauses.</summary>
31  [Serializable]
32  public class SpanOrQuery : SpanQuery, System.ICloneable
33  {
34  private class AnonymousClassSpans : Spans
35  {
36  public AnonymousClassSpans(Lucene.Net.Index.IndexReader reader, SpanOrQuery enclosingInstance)
37  {
38  InitBlock(reader, enclosingInstance);
39  }
40  private void InitBlock(Lucene.Net.Index.IndexReader reader, SpanOrQuery enclosingInstance)
41  {
42  this.reader = reader;
43  this.enclosingInstance = enclosingInstance;
44  }
45  private Lucene.Net.Index.IndexReader reader;
46  private SpanOrQuery enclosingInstance;
47  public SpanOrQuery Enclosing_Instance
48  {
49  get
50  {
51  return enclosingInstance;
52  }
53 
54  }
55  private SpanQueue queue = null;
56 
57  private bool InitSpanQueue(int target)
58  {
59  queue = new SpanQueue(enclosingInstance, Enclosing_Instance.clauses.Count);
60  System.Collections.Generic.IEnumerator<SpanQuery> i = Enclosing_Instance.clauses.GetEnumerator();
61  while (i.MoveNext())
62  {
63  Spans spans = i.Current.GetSpans(reader);
64  if (((target == - 1) && spans.Next()) || ((target != - 1) && spans.SkipTo(target)))
65  {
66  queue.Add(spans);
67  }
68  }
69  return queue.Size() != 0;
70  }
71 
72  public override bool Next()
73  {
74  if (queue == null)
75  {
76  return InitSpanQueue(- 1);
77  }
78 
79  if (queue.Size() == 0)
80  {
81  // all done
82  return false;
83  }
84 
85  if (Top().Next())
86  {
87  // move to next
88  queue.UpdateTop();
89  return true;
90  }
91 
92  queue.Pop(); // exhausted a clause
93  return queue.Size() != 0;
94  }
95 
96  private Spans Top()
97  {
98  return queue.Top();
99  }
100 
101  public override bool SkipTo(int target)
102  {
103  if (queue == null)
104  {
105  return InitSpanQueue(target);
106  }
107 
108  bool skipCalled = false;
109  while (queue.Size() != 0 && Top().Doc() < target)
110  {
111  if (Top().SkipTo(target))
112  {
113  queue.UpdateTop();
114  }
115  else
116  {
117  queue.Pop();
118  }
119  skipCalled = true;
120  }
121 
122  if (skipCalled)
123  {
124  return queue.Size() != 0;
125  }
126  return Next();
127  }
128 
129  public override int Doc()
130  {
131  return Top().Doc();
132  }
133  public override int Start()
134  {
135  return Top().Start();
136  }
137  public override int End()
138  {
139  return Top().End();
140  }
141 
142  public override ICollection<byte[]> GetPayload()
143  {
144  System.Collections.Generic.ICollection<byte[]> result = null;
145  Spans theTop = Top();
146  if (theTop != null && theTop.IsPayloadAvailable())
147  {
148  result = theTop.GetPayload();
149  }
150  return result;
151  }
152 
153  public override bool IsPayloadAvailable()
154  {
155  Spans top = Top();
156  return top != null && top.IsPayloadAvailable();
157  }
158 
159  public override System.String ToString()
160  {
161  return "spans(" + Enclosing_Instance + ")@" + ((queue == null)?"START":(queue.Size() > 0?(Doc() + ":" + Start() + "-" + End()):"END"));
162  }
163  }
164 
165  private EquatableList<SpanQuery> clauses;
166  private System.String field;
167 
168  /// <summary>Construct a SpanOrQuery merging the provided clauses. </summary>
169  public SpanOrQuery(params SpanQuery[] clauses)
170  {
171 
172  // copy clauses array into an ArrayList
173  this.clauses = new EquatableList<SpanQuery>(clauses.Length);
174  for (int i = 0; i < clauses.Length; i++)
175  {
176  SpanQuery clause = clauses[i];
177  if (i == 0)
178  {
179  // check field
180  field = clause.Field;
181  }
182  else if (!clause.Field.Equals(field))
183  {
184  throw new System.ArgumentException("Clauses must have same field.");
185  }
186  this.clauses.Add(clause);
187  }
188  }
189 
190  /// <summary>Return the clauses whose spans are matched. </summary>
191  public virtual SpanQuery[] GetClauses()
192  {
193  return clauses.ToArray();
194  }
195 
196  public override string Field
197  {
198  get { return field; }
199  }
200 
201  public override void ExtractTerms(System.Collections.Generic.ISet<Term> terms)
202  {
203  foreach(SpanQuery clause in clauses)
204  {
205  clause.ExtractTerms(terms);
206  }
207  }
208 
209  public override System.Object Clone()
210  {
211  int sz = clauses.Count;
212  SpanQuery[] newClauses = new SpanQuery[sz];
213 
214  for (int i = 0; i < sz; i++)
215  {
216  newClauses[i] = (SpanQuery) clauses[i].Clone();
217  }
218  SpanOrQuery soq = new SpanOrQuery(newClauses);
219  soq.Boost = Boost;
220  return soq;
221  }
222 
223  public override Query Rewrite(IndexReader reader)
224  {
225  SpanOrQuery clone = null;
226  for (int i = 0; i < clauses.Count; i++)
227  {
228  SpanQuery c = clauses[i];
229  SpanQuery query = (SpanQuery) c.Rewrite(reader);
230  if (query != c)
231  {
232  // clause rewrote: must clone
233  if (clone == null)
234  clone = (SpanOrQuery) this.Clone();
235  clone.clauses[i] = query;
236  }
237  }
238  if (clone != null)
239  {
240  return clone; // some clauses rewrote
241  }
242  else
243  {
244  return this; // no clauses rewrote
245  }
246  }
247 
248  public override System.String ToString(System.String field)
249  {
250  System.Text.StringBuilder buffer = new System.Text.StringBuilder();
251  buffer.Append("spanOr([");
252  System.Collections.Generic.IEnumerator<SpanQuery> i = clauses.GetEnumerator();
253  int j = 0;
254  while (i.MoveNext())
255  {
256  j++;
257  SpanQuery clause = i.Current;
258  buffer.Append(clause.ToString(field));
259  if (j < clauses.Count)
260  {
261  buffer.Append(", ");
262  }
263  }
264  buffer.Append("])");
265  buffer.Append(ToStringUtils.Boost(Boost));
266  return buffer.ToString();
267  }
268 
269  public override bool Equals(System.Object o)
270  {
271  if (this == o)
272  return true;
273  if (o == null || GetType() != o.GetType())
274  return false;
275 
276  SpanOrQuery that = (SpanOrQuery) o;
277 
278  if (!clauses.Equals(that.clauses))
279  return false;
280  if (!(clauses.Count == 0) && !field.Equals(that.field))
281  return false;
282 
283  return Boost == that.Boost;
284  }
285 
286  public override int GetHashCode()
287  {
288  int h = clauses.GetHashCode();
289  h ^= ((h << 10) | (Number.URShift(h, 23)));
290  h ^= System.Convert.ToInt32(Boost);
291  return h;
292  }
293 
294 
295  private class SpanQueue : PriorityQueue<Spans>
296  {
297  private void InitBlock(SpanOrQuery enclosingInstance)
298  {
299  this.enclosingInstance = enclosingInstance;
300  }
301  private SpanOrQuery enclosingInstance;
302  public SpanOrQuery Enclosing_Instance
303  {
304  get
305  {
306  return enclosingInstance;
307  }
308 
309  }
310  public SpanQueue(SpanOrQuery enclosingInstance, int size)
311  {
312  InitBlock(enclosingInstance);
313  Initialize(size);
314  }
315 
316  public override bool LessThan(Spans spans1, Spans spans2)
317  {
318  if (spans1.Doc() == spans2.Doc())
319  {
320  if (spans1.Start() == spans2.Start())
321  {
322  return spans1.End() < spans2.End();
323  }
324  else
325  {
326  return spans1.Start() < spans2.Start();
327  }
328  }
329  else
330  {
331  return spans1.Doc() < spans2.Doc();
332  }
333  }
334  }
335 
336  public override Spans GetSpans(IndexReader reader)
337  {
338  if (clauses.Count == 1)
339  // optimize 1-clause case
340  return (clauses[0]).GetSpans(reader);
341 
342  return new AnonymousClassSpans(reader, this);
343  }
344  }
345 }