| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 System.Collections.Generic; |
| using Lucene.Net.Util; |
| |
| namespace Lucene.Net.Index |
| { |
| |
| /// <summary> Allows you to iterate over the <see cref="TermPositions" /> for multiple <see cref="Term" />s as |
| /// a single <see cref="TermPositions" />. |
| /// |
| /// </summary> |
| public class MultipleTermPositions : TermPositions |
| { |
| private sealed class TermPositionsQueue : PriorityQueue<TermPositions> |
| { |
| internal TermPositionsQueue(LinkedList<TermPositions> termPositions) |
| { |
| Initialize(termPositions.Count); |
| |
| foreach(TermPositions tp in termPositions) |
| if (tp.Next()) |
| Add(tp); |
| } |
| |
| internal TermPositions Peek() |
| { |
| return Top(); |
| } |
| |
| public override bool LessThan(TermPositions a, TermPositions b) |
| { |
| return a.Doc < b.Doc; |
| } |
| } |
| |
| private sealed class IntQueue |
| { |
| public IntQueue() |
| { |
| InitBlock(); |
| } |
| private void InitBlock() |
| { |
| _array = new int[_arraySize]; |
| } |
| private int _arraySize = 16; |
| private int _index = 0; |
| private int _lastIndex = 0; |
| private int[] _array; |
| |
| internal void add(int i) |
| { |
| if (_lastIndex == _arraySize) |
| growArray(); |
| |
| _array[_lastIndex++] = i; |
| } |
| |
| internal int next() |
| { |
| return _array[_index++]; |
| } |
| |
| internal void sort() |
| { |
| System.Array.Sort(_array, _index, _lastIndex - _index); |
| } |
| |
| internal void clear() |
| { |
| _index = 0; |
| _lastIndex = 0; |
| } |
| |
| internal int size() |
| { |
| return (_lastIndex - _index); |
| } |
| |
| private void growArray() |
| { |
| int[] newArray = new int[_arraySize * 2]; |
| Array.Copy(_array, 0, newArray, 0, _arraySize); |
| _array = newArray; |
| _arraySize *= 2; |
| } |
| } |
| |
| private int _doc; |
| private int _freq; |
| private TermPositionsQueue _termPositionsQueue; |
| private IntQueue _posList; |
| |
| private bool isDisposed; |
| /// <summary> Creates a new <c>MultipleTermPositions</c> instance. |
| /// |
| /// </summary> |
| /// <exception cref="System.IO.IOException"> |
| /// </exception> |
| public MultipleTermPositions(IndexReader indexReader, Term[] terms) |
| { |
| var termPositions = new System.Collections.Generic.LinkedList<TermPositions>(); |
| |
| for (int i = 0; i < terms.Length; i++) |
| termPositions.AddLast(indexReader.TermPositions(terms[i])); |
| |
| _termPositionsQueue = new TermPositionsQueue(termPositions); |
| _posList = new IntQueue(); |
| } |
| |
| public bool Next() |
| { |
| if (_termPositionsQueue.Size() == 0) |
| return false; |
| |
| _posList.clear(); |
| _doc = _termPositionsQueue.Peek().Doc; |
| |
| TermPositions tp; |
| do |
| { |
| tp = _termPositionsQueue.Peek(); |
| |
| for (int i = 0; i < tp.Freq; i++) |
| _posList.add(tp.NextPosition()); |
| |
| if (tp.Next()) |
| _termPositionsQueue.UpdateTop(); |
| else |
| { |
| _termPositionsQueue.Pop(); |
| tp.Close(); |
| } |
| } |
| while (_termPositionsQueue.Size() > 0 && _termPositionsQueue.Peek().Doc == _doc); |
| |
| _posList.sort(); |
| _freq = _posList.size(); |
| |
| return true; |
| } |
| |
| public int NextPosition() |
| { |
| return _posList.next(); |
| } |
| |
| public bool SkipTo(int target) |
| { |
| while (_termPositionsQueue.Peek() != null && target > _termPositionsQueue.Peek().Doc) |
| { |
| TermPositions tp = _termPositionsQueue.Pop(); |
| if (tp.SkipTo(target)) |
| _termPositionsQueue.Add(tp); |
| else |
| tp.Close(); |
| } |
| return Next(); |
| } |
| |
| public int Doc |
| { |
| get { return _doc; } |
| } |
| |
| public int Freq |
| { |
| get { return _freq; } |
| } |
| |
| [Obsolete("Use Dispose() instead")] |
| public void Close() |
| { |
| Dispose(); |
| } |
| |
| public void Dispose() |
| { |
| Dispose(true); |
| } |
| |
| protected virtual void Dispose(bool disposing) |
| { |
| if (isDisposed) return; |
| |
| if (disposing) |
| { |
| while (_termPositionsQueue.Size() > 0) |
| _termPositionsQueue.Pop().Close(); |
| } |
| |
| isDisposed = true; |
| } |
| |
| /// <summary> Not implemented.</summary> |
| /// <throws> UnsupportedOperationException </throws> |
| public virtual void Seek(Term arg0) |
| { |
| throw new System.NotSupportedException(); |
| } |
| |
| /// <summary> Not implemented.</summary> |
| /// <throws> UnsupportedOperationException </throws> |
| public virtual void Seek(TermEnum termEnum) |
| { |
| throw new System.NotSupportedException(); |
| } |
| |
| /// <summary> Not implemented.</summary> |
| /// <throws> UnsupportedOperationException </throws> |
| public virtual int Read(int[] arg0, int[] arg1) |
| { |
| throw new System.NotSupportedException(); |
| } |
| |
| |
| /// <summary> Not implemented.</summary> |
| /// <throws> UnsupportedOperationException </throws> |
| public virtual int PayloadLength |
| { |
| get { throw new System.NotSupportedException(); } |
| } |
| |
| /// <summary> Not implemented.</summary> |
| /// <throws> UnsupportedOperationException </throws> |
| public virtual byte[] GetPayload(byte[] data, int offset) |
| { |
| throw new System.NotSupportedException(); |
| } |
| |
| /// <summary> </summary> |
| /// <value> false </value> |
| // TODO: Remove warning after API has been finalized |
| public virtual bool IsPayloadAvailable |
| { |
| get { return false; } |
| } |
| } |
| } |