2 * Copyright 2004 The Apache Software Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using IndexReader
= Lucene
.Net
.Index
.IndexReader
;
19 using Query
= Lucene
.Net
.Search
.Query
;
20 using PriorityQueue
= Lucene
.Net
.Util
.PriorityQueue
;
21 using ToStringUtils
= Lucene
.Net
.Util
.ToStringUtils
;
23 namespace Lucene
.Net
.Search
.Spans
26 /// <summary>Matches the union of its clauses.</summary>
28 public class SpanOrQuery
: SpanQuery
30 private class AnonymousClassSpans
: Spans
32 public AnonymousClassSpans(Lucene
.Net
.Index
.IndexReader reader
, SpanOrQuery enclosingInstance
)
34 InitBlock(reader
, enclosingInstance
);
36 private void InitBlock(Lucene
.Net
.Index
.IndexReader reader
, SpanOrQuery enclosingInstance
)
39 this.enclosingInstance
= enclosingInstance
;
40 all
= new System
.Collections
.ArrayList(Enclosing_Instance
.clauses
.Count
);
41 queue
= new SpanQueue(enclosingInstance
, Enclosing_Instance
.clauses
.Count
);
42 System
.Collections
.IEnumerator i
= Enclosing_Instance
.clauses
.GetEnumerator();
46 all
.Add(((SpanQuery
) i
.Current
).GetSpans(reader
));
49 private Lucene
.Net
.Index
.IndexReader reader
;
50 private SpanOrQuery enclosingInstance
;
51 public SpanOrQuery Enclosing_Instance
55 return enclosingInstance
;
59 private System
.Collections
.IList all
;
60 private SpanQueue queue
;
62 private bool firstTime
= true;
64 public virtual bool Next()
68 // first time -- initialize
69 for (int i
= 0; i
< all
.Count
; i
++)
71 Spans spans
= (Spans
) all
[i
];
74 // move to first entry
75 queue
.Put(spans
); // build queue
83 return queue
.Size() != 0;
86 if (queue
.Size() == 0)
99 all
.Remove(queue
.Pop()); // exhausted a clause
101 return queue
.Size() != 0;
106 return (Spans
) queue
.Top();
109 public virtual bool SkipTo(int target
)
113 for (int i
= 0; i
< all
.Count
; i
++)
115 Spans spans
= (Spans
) all
[i
];
116 if (spans
.SkipTo(target
))
118 // skip each spans in all
119 queue
.Put(spans
); // build queue
130 while (queue
.Size() != 0 && Top().Doc() < target
)
132 if (Top().SkipTo(target
))
138 all
.Remove(queue
.Pop());
143 return queue
.Size() != 0;
146 public virtual int Doc()
150 public virtual int Start()
152 return Top().Start();
154 public virtual int End()
159 public override System
.String
ToString()
161 return "spans(" + Enclosing_Instance
+ ")@" + (firstTime
?"START":(queue
.Size() > 0?(Doc() + ":" + Start() + "-" + End()):"END"));
164 private System
.Collections
.ArrayList clauses
;
165 private System
.String field
;
167 /// <summary>Construct a SpanOrQuery merging the provided clauses. </summary>
168 public SpanOrQuery(SpanQuery
[] clauses
)
171 // copy clauses array into an ArrayList
172 this.clauses
= new System
.Collections
.ArrayList(clauses
.Length
);
173 for (int i
= 0; i
< clauses
.Length
; i
++)
175 SpanQuery clause
= clauses
[i
];
179 field
= clause
.GetField();
181 else if (!clause
.GetField().Equals(field
))
183 throw new System
.ArgumentException("Clauses must have same field.");
185 this.clauses
.Add(clause
);
189 /// <summary>Return the clauses whose spans are matched. </summary>
190 public virtual SpanQuery
[] GetClauses()
192 return (SpanQuery
[]) clauses
.ToArray(typeof(SpanQuery
[]));
195 public override System
.String
GetField()
200 public override System
.Collections
.ICollection
GetTerms()
202 System
.Collections
.ArrayList terms
= new System
.Collections
.ArrayList();
203 System
.Collections
.IEnumerator i
= clauses
.GetEnumerator();
206 SpanQuery clause
= (SpanQuery
) i
.Current
;
207 terms
.AddRange(clause
.GetTerms());
212 public override Query
Rewrite(IndexReader reader
)
214 SpanOrQuery clone
= null;
215 for (int i
= 0; i
< clauses
.Count
; i
++)
217 SpanQuery c
= (SpanQuery
) clauses
[i
];
218 SpanQuery query
= (SpanQuery
) c
.Rewrite(reader
);
221 // clause rewrote: must clone
223 clone
= (SpanOrQuery
) this.Clone();
224 clone
.clauses
[i
] = query
;
229 return clone
; // some clauses rewrote
233 return this; // no clauses rewrote
237 public override System
.String
ToString(System
.String field
)
239 System
.Text
.StringBuilder buffer
= new System
.Text
.StringBuilder();
240 buffer
.Append("spanOr([");
241 System
.Collections
.IEnumerator i
= clauses
.GetEnumerator();
244 SpanQuery clause
= (SpanQuery
) i
.Current
;
245 buffer
.Append(clause
.ToString(field
));
252 buffer
.Append(ToStringUtils
.Boost(GetBoost()));
253 return buffer
.ToString();
256 public override bool Equals(System
.Object o
)
260 if (o
== null || GetType() != o
.GetType())
263 SpanOrQuery that
= (SpanOrQuery
) o
;
265 if (!clauses
.Equals(that
.clauses
))
267 if (!field
.Equals(that
.field
))
270 return GetBoost() == that
.GetBoost();
273 public override int GetHashCode()
276 result
= clauses
.GetHashCode();
277 result
= 29 * result
+ field
.GetHashCode();
281 private class SpanQueue
: PriorityQueue
283 private void InitBlock(SpanOrQuery enclosingInstance
)
285 this.enclosingInstance
= enclosingInstance
;
287 private SpanOrQuery enclosingInstance
;
288 public SpanOrQuery Enclosing_Instance
292 return enclosingInstance
;
296 public SpanQueue(SpanOrQuery enclosingInstance
, int size
)
298 InitBlock(enclosingInstance
);
302 public override bool LessThan(System
.Object o1
, System
.Object o2
)
304 Spans spans1
= (Spans
) o1
;
305 Spans spans2
= (Spans
) o2
;
306 if (spans1
.Doc() == spans2
.Doc())
308 if (spans1
.Start() == spans2
.Start())
310 return spans1
.End() < spans2
.End();
314 return spans1
.Start() < spans2
.Start();
319 return spans1
.Doc() < spans2
.Doc();
325 public override Spans
GetSpans(IndexReader reader
)
327 if (clauses
.Count
== 1)
328 // optimize 1-clause case
329 return ((SpanQuery
) clauses
[0]).GetSpans(reader
);
331 return new AnonymousClassSpans(reader
, this);