blob: 34f3d65f96f7efc043a32ed8102c2041e906e24d [file] [log] [blame]
/*
* 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; }
}
}
}