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.Util;
21 
22 namespace Lucene.Net.Index
23 {
24 
25 	/// <summary> Allows you to iterate over the <see cref="TermPositions" /> for multiple <see cref="Term" />s as
26 	/// a single <see cref="TermPositions" />.
27 	///
28 	/// </summary>
29 	public class MultipleTermPositions : TermPositions
30 	{
31 		private sealed class TermPositionsQueue : PriorityQueue<TermPositions>
32 		{
TermPositionsQueue(LinkedList<TermPositions> termPositions)33 			internal TermPositionsQueue(LinkedList<TermPositions> termPositions)
34 			{
35 				Initialize(termPositions.Count);
36 
37 				foreach(TermPositions tp in termPositions)
38 					if (tp.Next())
39 						Add(tp);
40 			}
41 
Peek()42 			internal TermPositions Peek()
43 			{
44 				return Top();
45 			}
46 
LessThan(TermPositions a, TermPositions b)47 			public override bool LessThan(TermPositions a, TermPositions b)
48 			{
49 				return a.Doc < b.Doc;
50 			}
51 		}
52 
53 		private sealed class IntQueue
54 		{
IntQueue()55 			public IntQueue()
56 			{
57 				InitBlock();
58 			}
InitBlock()59 			private void  InitBlock()
60 			{
61 				_array = new int[_arraySize];
62 			}
63 			private int _arraySize = 16;
64 			private int _index = 0;
65 			private int _lastIndex = 0;
66 			private int[] _array;
67 
add(int i)68 			internal void  add(int i)
69 			{
70 				if (_lastIndex == _arraySize)
71 					growArray();
72 
73 				_array[_lastIndex++] = i;
74 			}
75 
next()76 			internal int next()
77 			{
78 				return _array[_index++];
79 			}
80 
sort()81 			internal void  sort()
82 			{
83 				System.Array.Sort(_array, _index, _lastIndex - _index);
84 			}
85 
clear()86 			internal void  clear()
87 			{
88 				_index = 0;
89 				_lastIndex = 0;
90 			}
91 
size()92 			internal int size()
93 			{
94 				return (_lastIndex - _index);
95 			}
96 
growArray()97 			private void  growArray()
98 			{
99 				int[] newArray = new int[_arraySize * 2];
100 				Array.Copy(_array, 0, newArray, 0, _arraySize);
101 				_array = newArray;
102 				_arraySize *= 2;
103 			}
104 		}
105 
106 		private int _doc;
107 		private int _freq;
108 		private TermPositionsQueue _termPositionsQueue;
109 		private IntQueue _posList;
110 
111 	    private bool isDisposed;
112 		/// <summary> Creates a new <c>MultipleTermPositions</c> instance.
113 		///
114 		/// </summary>
115 		/// <exception cref="System.IO.IOException">
116 		/// </exception>
MultipleTermPositions(IndexReader indexReader, Term[] terms)117 		public MultipleTermPositions(IndexReader indexReader, Term[] terms)
118 		{
119 			var termPositions = new System.Collections.Generic.LinkedList<TermPositions>();
120 
121 			for (int i = 0; i < terms.Length; i++)
122 				termPositions.AddLast(indexReader.TermPositions(terms[i]));
123 
124 			_termPositionsQueue = new TermPositionsQueue(termPositions);
125 			_posList = new IntQueue();
126 		}
127 
Next()128 		public bool Next()
129 		{
130 			if (_termPositionsQueue.Size() == 0)
131 				return false;
132 
133 			_posList.clear();
134 			_doc = _termPositionsQueue.Peek().Doc;
135 
136 			TermPositions tp;
137 			do
138 			{
139 				tp = _termPositionsQueue.Peek();
140 
141 				for (int i = 0; i < tp.Freq; i++)
142 					_posList.add(tp.NextPosition());
143 
144 				if (tp.Next())
145 					_termPositionsQueue.UpdateTop();
146 				else
147 				{
148 					_termPositionsQueue.Pop();
149 					tp.Close();
150 				}
151 			}
152 			while (_termPositionsQueue.Size() > 0 && _termPositionsQueue.Peek().Doc == _doc);
153 
154 			_posList.sort();
155 			_freq = _posList.size();
156 
157 			return true;
158 		}
159 
NextPosition()160 		public int NextPosition()
161 		{
162 			return _posList.next();
163 		}
164 
SkipTo(int target)165 		public bool SkipTo(int target)
166 		{
167 			while (_termPositionsQueue.Peek() != null && target > _termPositionsQueue.Peek().Doc)
168 			{
169 				TermPositions tp = _termPositionsQueue.Pop();
170 				if (tp.SkipTo(target))
171 					_termPositionsQueue.Add(tp);
172 				else
173 					tp.Close();
174 			}
175 			return Next();
176 		}
177 
178 	    public int Doc
179 	    {
180 	        get { return _doc; }
181 	    }
182 
183 	    public int Freq
184 	    {
185 	        get { return _freq; }
186 	    }
187 
188 	    [Obsolete("Use Dispose() instead")]
Close()189 		public void  Close()
190 		{
191 		    Dispose();
192 		}
193 
Dispose()194         public void Dispose()
195         {
196             Dispose(true);
197         }
198 
Dispose(bool disposing)199         protected virtual void Dispose(bool disposing)
200         {
201             if (isDisposed) return;
202 
203             if (disposing)
204             {
205                 while (_termPositionsQueue.Size() > 0)
206                     _termPositionsQueue.Pop().Close();
207             }
208 
209             isDisposed = true;
210         }
211 
212 		/// <summary> Not implemented.</summary>
213 		/// <throws>  UnsupportedOperationException </throws>
Seek(Term arg0)214 		public virtual void Seek(Term arg0)
215 		{
216 			throw new System.NotSupportedException();
217 		}
218 
219 		/// <summary> Not implemented.</summary>
220 		/// <throws>  UnsupportedOperationException </throws>
Seek(TermEnum termEnum)221 		public virtual void Seek(TermEnum termEnum)
222 		{
223 			throw new System.NotSupportedException();
224 		}
225 
226 		/// <summary> Not implemented.</summary>
227 		/// <throws>  UnsupportedOperationException </throws>
Read(int[] arg0, int[] arg1)228 		public virtual int Read(int[] arg0, int[] arg1)
229 		{
230 			throw new System.NotSupportedException();
231 		}
232 
233 
234 	    /// <summary> Not implemented.</summary>
235 	    /// <throws>  UnsupportedOperationException </throws>
236 	    public virtual int PayloadLength
237 	    {
238 	        get { throw new System.NotSupportedException(); }
239 	    }
240 
241 	    /// <summary> Not implemented.</summary>
242 		/// <throws>  UnsupportedOperationException </throws>
GetPayload(byte[] data, int offset)243 		public virtual byte[] GetPayload(byte[] data, int offset)
244 		{
245 			throw new System.NotSupportedException();
246 		}
247 
248 	    /// <summary> </summary>
249 	    /// <value> false </value>
250 // TODO: Remove warning after API has been finalized
251 	    public virtual bool IsPayloadAvailable
252 	    {
253 	        get { return false; }
254 	    }
255 	}
256 }