You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by sy...@apache.org on 2014/09/16 00:46:59 UTC
[01/11] git commit: Commenting this out for now to fix compilation
Repository: lucenenet
Updated Branches:
refs/heads/master 0ebac7269 -> 531b4af02
Commenting this out for now to fix compilation
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/895be41b
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/895be41b
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/895be41b
Branch: refs/heads/master
Commit: 895be41b1efd5b33704578f13ae1426f2511a590
Parents: 0ebac72
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Tue Sep 16 01:25:16 2014 +0300
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Tue Sep 16 01:25:16 2014 +0300
----------------------------------------------------------------------
src/Lucene.Net.Core/Util/OfflineSorter.cs | 1286 ++++++++++++------------
1 file changed, 643 insertions(+), 643 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/895be41b/src/Lucene.Net.Core/Util/OfflineSorter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/OfflineSorter.cs b/src/Lucene.Net.Core/Util/OfflineSorter.cs
index f966e77..4f72585 100644
--- a/src/Lucene.Net.Core/Util/OfflineSorter.cs
+++ b/src/Lucene.Net.Core/Util/OfflineSorter.cs
@@ -32,648 +32,648 @@ namespace Lucene.Net.Util
/// </summary>
public sealed class OfflineSorter
{
- private bool InstanceFieldsInitialized = false;
-
- private void InitializeInstanceFields()
- {
- Buffer = new BytesRefArray(BufferBytesUsed);
- }
-
- /// <summary>
- /// Convenience constant for megabytes </summary>
- public const long MB = 1024 * 1024;
- /// <summary>
- /// Convenience constant for gigabytes </summary>
- public static readonly long GB = MB * 1024;
-
- /// <summary>
- /// Minimum recommended buffer size for sorting.
- /// </summary>
- public const long MIN_BUFFER_SIZE_MB = 32;
-
- /// <summary>
- /// Absolute minimum required buffer size for sorting.
- /// </summary>
- public static readonly long ABSOLUTE_MIN_SORT_BUFFER_SIZE = MB / 2;
- private const string MIN_BUFFER_SIZE_MSG = "At least 0.5MB RAM buffer is needed";
-
- /// <summary>
- /// Maximum number of temporary files before doing an intermediate merge.
- /// </summary>
- public const int MAX_TEMPFILES = 128;
-
- /// <summary>
- /// A bit more descriptive unit for constructors.
- /// </summary>
- /// <seealso cref= #automatic() </seealso>
- /// <seealso cref= #megabytes(long) </seealso>
- public sealed class BufferSize
- {
- internal readonly int Bytes;
-
- internal BufferSize(long bytes)
- {
- if (bytes > int.MaxValue)
- {
- throw new System.ArgumentException("Buffer too large for Java (" + (int.MaxValue / MB) + "mb max): " + bytes);
- }
-
- if (bytes < ABSOLUTE_MIN_SORT_BUFFER_SIZE)
- {
- throw new System.ArgumentException(MIN_BUFFER_SIZE_MSG + ": " + bytes);
- }
-
- this.Bytes = (int)bytes;
- }
-
- /// <summary>
- /// Creates a <seealso cref="BufferSize"/> in MB. The given
- /// values must be > 0 and < 2048.
- /// </summary>
- public static BufferSize Megabytes(long mb)
- {
- return new BufferSize(mb * MB);
- }
-
- /// <summary>
- /// Approximately half of the currently available free heap, but no less
- /// than <seealso cref="#ABSOLUTE_MIN_SORT_BUFFER_SIZE"/>. However if current heap allocation
- /// is insufficient or if there is a large portion of unallocated heap-space available
- /// for sorting consult with max allowed heap size.
- /// </summary>
- public static BufferSize Automatic()
- {
- var proc = Process.GetCurrentProcess();
-
- // take sizes in "conservative" order
- long max = proc.PeakVirtualMemorySize64; // max allocated; java has it as Runtime.maxMemory();
- long total = proc.VirtualMemorySize64; // currently allocated; java has it as Runtime.totalMemory();
- long free = rt.freeMemory(); // unused portion of currently allocated
- long totalAvailableBytes = max - total + free;
-
- // by free mem (attempting to not grow the heap for this)
- long sortBufferByteSize = free / 2;
- const long minBufferSizeBytes = MIN_BUFFER_SIZE_MB * MB;
- if (sortBufferByteSize < minBufferSizeBytes || totalAvailableBytes > 10 * minBufferSizeBytes) // lets see if we need/should to grow the heap
- {
- if (totalAvailableBytes / 2 > minBufferSizeBytes) // there is enough mem for a reasonable buffer
- {
- sortBufferByteSize = totalAvailableBytes / 2; // grow the heap
- }
- else
- {
- //heap seems smallish lets be conservative fall back to the free/2
- sortBufferByteSize = Math.Max(ABSOLUTE_MIN_SORT_BUFFER_SIZE, sortBufferByteSize);
- }
- }
- return new BufferSize(Math.Min((long)int.MaxValue, sortBufferByteSize));
- }
- }
-
- /// <summary>
- /// Sort info (debugging mostly).
- /// </summary>
- public class SortInfo
- {
- internal bool InstanceFieldsInitialized = false;
-
- internal virtual void InitializeInstanceFields()
- {
- BufferSize = OuterInstance.RamBufferSize.Bytes;
- }
-
- private readonly OfflineSorter OuterInstance;
-
- /// <summary>
- /// number of temporary files created when merging partitions </summary>
- public int TempMergeFiles;
- /// <summary>
- /// number of partition merges </summary>
- public int MergeRounds;
- /// <summary>
- /// number of lines of data read </summary>
- public int Lines;
- /// <summary>
- /// time spent merging sorted partitions (in milliseconds) </summary>
- public long MergeTime;
- /// <summary>
- /// time spent sorting data (in milliseconds) </summary>
- public long SortTime;
- /// <summary>
- /// total time spent (in milliseconds) </summary>
- public long TotalTime;
- /// <summary>
- /// time spent in i/o read (in milliseconds) </summary>
- public long ReadTime;
- /// <summary>
- /// read buffer size (in bytes) </summary>
- public long BufferSize;
-
- /// <summary>
- /// create a new SortInfo (with empty statistics) for debugging </summary>
- public SortInfo(OfflineSorter outerInstance)
- {
- this.OuterInstance = outerInstance;
-
- if (!InstanceFieldsInitialized)
- {
- InitializeInstanceFields();
- InstanceFieldsInitialized = true;
- }
- }
-
- public override string ToString()
- {
- return string.Format("time=%.2f sec. total (%.2f reading, %.2f sorting, %.2f merging), lines=%d, temp files=%d, merges=%d, soft ram limit=%.2f MB", TotalTime / 1000.0d, ReadTime / 1000.0d, SortTime / 1000.0d, MergeTime / 1000.0d, Lines, TempMergeFiles, MergeRounds, (double)BufferSize / MB);
- }
- }
-
- private readonly BufferSize RamBufferSize;
-
- private readonly Counter BufferBytesUsed = Counter.NewCounter();
- private BytesRefArray Buffer;
- private SortInfo sortInfo;
- private readonly int MaxTempFiles;
- private readonly IComparer<BytesRef> comparator;
-
- /// <summary>
- /// Default comparator: sorts in binary (codepoint) order </summary>
- public static readonly IComparer<BytesRef> DEFAULT_COMPARATOR = BytesRef.UTF8SortedAsUnicodeComparator.Instance;
-
- /// <summary>
- /// Defaults constructor.
- /// </summary>
- /// <seealso cref= #defaultTempDir() </seealso>
- /// <seealso cref= BufferSize#automatic() </seealso>
- public OfflineSorter()
- : this(DEFAULT_COMPARATOR, BufferSize.Automatic(), DefaultTempDir(), MAX_TEMPFILES)
- {
- if (!InstanceFieldsInitialized)
- {
- InitializeInstanceFields();
- InstanceFieldsInitialized = true;
- }
- }
-
- /// <summary>
- /// Defaults constructor with a custom comparator.
- /// </summary>
- /// <seealso cref= #defaultTempDir() </seealso>
- /// <seealso cref= BufferSize#automatic() </seealso>
- public OfflineSorter(IComparer<BytesRef> comparator)
- : this(comparator, BufferSize.Automatic(), DefaultTempDir(), MAX_TEMPFILES)
- {
- if (!InstanceFieldsInitialized)
- {
- InitializeInstanceFields();
- InstanceFieldsInitialized = true;
- }
- }
-
- /// <summary>
- /// All-details constructor.
- /// </summary>
- public OfflineSorter(IComparer<BytesRef> comparator, BufferSize ramBufferSize, /*DirectoryInfo tempDirectory,*/ int maxTempfiles)
- {
- if (!InstanceFieldsInitialized)
- {
- InitializeInstanceFields();
- InstanceFieldsInitialized = true;
- }
- if (ramBufferSize.Bytes < ABSOLUTE_MIN_SORT_BUFFER_SIZE)
- {
- throw new System.ArgumentException(MIN_BUFFER_SIZE_MSG + ": " + ramBufferSize.Bytes);
- }
-
- if (maxTempfiles < 2)
- {
- throw new System.ArgumentException("maxTempFiles must be >= 2");
- }
-
- this.RamBufferSize = ramBufferSize;
- this.MaxTempFiles = maxTempfiles;
- this.comparator = comparator;
- }
-
- /// <summary>
- /// Sort input to output, explicit hint for the buffer size. The amount of allocated
- /// memory may deviate from the hint (may be smaller or larger).
- /// </summary>
- public SortInfo Sort(FileInfo input, FileInfo output)
- {
- sortInfo = new SortInfo(this) {TotalTime = DateTime.Now.Millisecond};
-
- output.Delete();
-
- var merges = new List<FileInfo>();
- bool success2 = false;
- try
- {
- var inputStream = new ByteSequencesReader(input);
- bool success = false;
- try
- {
- int lines = 0;
- while ((lines = ReadPartition(inputStream)) > 0)
- {
- merges.Add(SortPartition(lines));
- sortInfo.TempMergeFiles++;
- sortInfo.Lines += lines;
-
- // Handle intermediate merges.
- if (merges.Count == MaxTempFiles)
- {
- var intermediate = new FileInfo(Path.GetTempFileName());
- try
- {
- MergePartitions(merges, intermediate);
- }
- finally
- {
- foreach (var file in merges)
- {
- file.Delete();
- }
- merges.Clear();
- merges.Add(intermediate);
- }
- sortInfo.TempMergeFiles++;
- }
- }
- success = true;
- }
- finally
- {
- if (success)
- {
- IOUtils.Close(inputStream);
- }
- else
- {
- IOUtils.CloseWhileHandlingException(inputStream);
- }
- }
-
- // One partition, try to rename or copy if unsuccessful.
- if (merges.Count == 1)
- {
- FileInfo single = merges[0];
- Copy(single, output);
- try
- {
- File.Delete(single.FullName);
- }
- catch (Exception)
- {
- // ignored
- }
- }
- else
- {
- // otherwise merge the partitions with a priority queue.
- MergePartitions(merges, output);
- }
- success2 = true;
- }
- finally
- {
- foreach (FileInfo file in merges)
- {
- file.Delete();
- }
- if (!success2)
- {
- output.Delete();
- }
- }
-
- sortInfo.TotalTime = (DateTime.Now.Millisecond - sortInfo.TotalTime);
- return sortInfo;
- }
-
- /// <summary>
- /// Returns the default temporary directory. By default, the System's temp folder. If not accessible
- /// or not available, an IOException is thrown
- /// </summary>
- public static DirectoryInfo DefaultTempDir()
- {
- return new DirectoryInfo(Path.GetTempPath());
- }
-
- /// <summary>
- /// Copies one file to another.
- /// </summary>
- private static void Copy(FileInfo file, FileInfo output)
- {
- File.Copy(file.FullName, output.FullName);
- }
-
- /// <summary>
- /// Sort a single partition in-memory. </summary>
- internal FileInfo SortPartition(int len)
- {
- var data = this.Buffer;
- var tempFile = new FileInfo(Path.GetTempFileName());
- //var tempFile1 = File.Create(new ());
- //FileInfo tempFile = FileInfo.createTempFile("sort", "partition", TempDirectory);
-
- long start = DateTime.Now.Millisecond;
- sortInfo.SortTime += (DateTime.Now.Millisecond - start);
-
- var @out = new ByteSequencesWriter(tempFile);
- BytesRef spare;
- try
- {
- BytesRefIterator iter = Buffer.Iterator(comparator);
- while ((spare = iter.Next()) != null)
- {
- Debug.Assert(spare.Length <= short.MaxValue);
- @out.Write(spare);
- }
-
- @out.Dispose();
-
- // Clean up the buffer for the next partition.
- data.Clear();
- return tempFile;
- }
- finally
- {
- IOUtils.Close(@out);
- }
- }
-
- /// <summary>
- /// Merge a list of sorted temporary files (partitions) into an output file </summary>
- internal void MergePartitions(IList<FileInfo> merges, FileInfo outputFile)
- {
- long start = DateTime.Now.Millisecond;
-
- var @out = new ByteSequencesWriter(outputFile);
-
- PriorityQueue<FileAndTop> queue = new PriorityQueueAnonymousInnerClassHelper(this, merges.Count);
-
- var streams = new ByteSequencesReader[merges.Count];
- try
- {
- // Open streams and read the top for each file
- for (int i = 0; i < merges.Count; i++)
- {
- streams[i] = new ByteSequencesReader(merges[i]);
- sbyte[] line = streams[i].Read();
- if (line != null)
- {
- queue.InsertWithOverflow(new FileAndTop(i, line));
- }
- }
-
- // Unix utility sort() uses ordered array of files to pick the next line from, updating
- // it as it reads new lines. The PQ used here is a more elegant solution and has
- // a nicer theoretical complexity bound :) The entire sorting process is I/O bound anyway
- // so it shouldn't make much of a difference (didn't check).
- FileAndTop top;
- while ((top = queue.Top()) != null)
- {
- @out.Write(top.Current);
- if (!streams[top.Fd].Read(top.Current))
- {
- queue.Pop();
- }
- else
- {
- queue.UpdateTop();
- }
- }
-
- SortInfo.MergeTime += DateTime.UtcNow.Ticks - start;
- SortInfo.MergeRounds++;
- }
- finally
- {
- // The logic below is: if an exception occurs in closing out, it has a priority over exceptions
- // happening in closing streams.
- try
- {
- IOUtils.Close(streams);
- }
- finally
- {
- IOUtils.Close(@out);
- }
- }
- }
-
- private class PriorityQueueAnonymousInnerClassHelper : PriorityQueue<FileAndTop>
- {
- private readonly OfflineSorter OuterInstance;
-
- public PriorityQueueAnonymousInnerClassHelper(OfflineSorter outerInstance, int size)
- : base(size)
- {
- this.OuterInstance = outerInstance;
- }
-
- public override bool LessThan(FileAndTop a, FileAndTop b)
- {
- return OuterInstance.comparator.Compare(a.Current, b.Current) < 0;
- }
- }
-
- /// <summary>
- /// Read in a single partition of data </summary>
- internal int ReadPartition(ByteSequencesReader reader)
- {
- long start = DateTime.Now.Millisecond;
- var scratch = new BytesRef();
- while ((scratch.Bytes = reader.Read()) != null)
- {
- scratch.Length = scratch.Bytes.Length;
- Buffer.Append(scratch);
- // Account for the created objects.
- // (buffer slots do not account to buffer size.)
- if (RamBufferSize.Bytes < BufferBytesUsed.Get())
- {
- break;
- }
- }
- sortInfo.ReadTime += (DateTime.Now.Millisecond - start);
- return Buffer.Size();
- }
-
- internal class FileAndTop
- {
- internal readonly int Fd;
- internal readonly BytesRef Current;
-
- internal FileAndTop(int fd, sbyte[] firstLine)
- {
- this.Fd = fd;
- this.Current = new BytesRef(firstLine);
- }
- }
-
- /// <summary>
- /// Utility class to emit length-prefixed byte[] entries to an output stream for sorting.
- /// Complementary to <seealso cref="ByteSequencesReader"/>.
- /// </summary>
- public class ByteSequencesWriter : IDisposable
- {
- internal readonly DataOutput Os;
-
- /// <summary>
- /// Constructs a ByteSequencesWriter to the provided File </summary>
- public ByteSequencesWriter(FileInfo file)
- : this(new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))))
- {
- }
-
- /// <summary>
- /// Constructs a ByteSequencesWriter to the provided DataOutput </summary>
- public ByteSequencesWriter(DataOutput os)
- {
- this.Os = os;
- }
-
- /// <summary>
- /// Writes a BytesRef. </summary>
- /// <seealso cref= #write(byte[], int, int) </seealso>
- public virtual void Write(BytesRef @ref)
- {
- Debug.Assert(@ref != null);
- Write(@ref.Bytes, @ref.Offset, @ref.Length);
- }
-
- /// <summary>
- /// Writes a byte array. </summary>
- /// <seealso cref= #write(byte[], int, int) </seealso>
- public virtual void Write(sbyte[] bytes)
- {
- Write(bytes, 0, bytes.Length);
- }
-
- /// <summary>
- /// Writes a byte array.
- /// <p>
- /// The length is written as a <code>short</code>, followed
- /// by the bytes.
- /// </summary>
- public virtual void Write(sbyte[] bytes, int off, int len)
- {
- Debug.Assert(bytes != null);
- Debug.Assert(off >= 0 && off + len <= bytes.Length);
- Debug.Assert(len >= 0);
- Os.WriteShort(len);
- Os.Write(bytes, off, len);
- }
-
- /// <summary>
- /// Closes the provided <seealso cref="DataOutput"/> if it is <seealso cref="IDisposable"/>.
- /// </summary>
- public void Dispose()
- {
- var os = Os as IDisposable;
- if (os != null)
- {
- os.Dispose();
- }
- }
- }
-
- /// <summary>
- /// Utility class to read length-prefixed byte[] entries from an input.
- /// Complementary to <seealso cref="ByteSequencesWriter"/>.
- /// </summary>
- public class ByteSequencesReader : IDisposable
- {
- internal readonly DataInput inputStream;
-
- /// <summary>
- /// Constructs a ByteSequencesReader from the provided File </summary>
- public ByteSequencesReader(FileInfo file)
- : this(new DataInputStream(new BufferedInputStream(new FileInputStream(file))))
- {
- }
-
- /// <summary>
- /// Constructs a ByteSequencesReader from the provided DataInput </summary>
- public ByteSequencesReader(DataInput inputStream)
- {
- this.inputStream = inputStream;
- }
-
- /// <summary>
- /// Reads the next entry into the provided <seealso cref="BytesRef"/>. The internal
- /// storage is resized if needed.
- /// </summary>
- /// <returns> Returns <code>false</code> if EOF occurred when trying to read
- /// the header of the next sequence. Returns <code>true</code> otherwise. </returns>
- /// <exception cref="EOFException"> if the file ends before the full sequence is read. </exception>
- public virtual bool Read(BytesRef @ref)
- {
- short length;
- try
- {
- length = inputStream.ReadShort();
- }
- catch (EOFException)
- {
- return false;
- }
-
- @ref.Grow(length);
- @ref.Offset = 0;
- @ref.Length = length;
- inputStream.ReadFully(@ref.Bytes, 0, length);
- return true;
- }
-
- /// <summary>
- /// Reads the next entry and returns it if successful.
- /// </summary>
- /// <seealso cref= #read(BytesRef)
- /// </seealso>
- /// <returns> Returns <code>null</code> if EOF occurred before the next entry
- /// could be read. </returns>
- /// <exception cref="EOFException"> if the file ends before the full sequence is read. </exception>
- public virtual sbyte[] Read()
- {
- short length;
- try
- {
- length = inputStream.ReadShort();
- }
- catch (EOFException e)
- {
- return null;
- }
-
- Debug.Assert(length >= 0, "Sanity: sequence length < 0: " + length);
- sbyte[] result = new sbyte[length];
- inputStream.ReadFully(result);
- return result;
- }
-
- /// <summary>
- /// Closes the provided <seealso cref="DataInput"/> if it is <seealso cref="IDisposable"/>.
- /// </summary>
- public void Dispose()
- {
- var @is = inputStream as IDisposable;
- if (@is != null)
- {
- @is.Dispose();
- }
- }
- }
-
- /// <summary>
- /// Returns the comparator in use to sort entries </summary>
- public IComparer<BytesRef> Comparator
- {
- get
- {
- return comparator;
- }
- }
+// private bool InstanceFieldsInitialized = false;
+//
+// private void InitializeInstanceFields()
+// {
+// Buffer = new BytesRefArray(BufferBytesUsed);
+// }
+//
+// /// <summary>
+// /// Convenience constant for megabytes </summary>
+// public const long MB = 1024 * 1024;
+// /// <summary>
+// /// Convenience constant for gigabytes </summary>
+// public static readonly long GB = MB * 1024;
+//
+// /// <summary>
+// /// Minimum recommended buffer size for sorting.
+// /// </summary>
+// public const long MIN_BUFFER_SIZE_MB = 32;
+//
+// /// <summary>
+// /// Absolute minimum required buffer size for sorting.
+// /// </summary>
+// public static readonly long ABSOLUTE_MIN_SORT_BUFFER_SIZE = MB / 2;
+// private const string MIN_BUFFER_SIZE_MSG = "At least 0.5MB RAM buffer is needed";
+//
+// /// <summary>
+// /// Maximum number of temporary files before doing an intermediate merge.
+// /// </summary>
+// public const int MAX_TEMPFILES = 128;
+//
+// /// <summary>
+// /// A bit more descriptive unit for constructors.
+// /// </summary>
+// /// <seealso cref= #automatic() </seealso>
+// /// <seealso cref= #megabytes(long) </seealso>
+// public sealed class BufferSize
+// {
+// internal readonly int Bytes;
+//
+// internal BufferSize(long bytes)
+// {
+// if (bytes > int.MaxValue)
+// {
+// throw new System.ArgumentException("Buffer too large for Java (" + (int.MaxValue / MB) + "mb max): " + bytes);
+// }
+//
+// if (bytes < ABSOLUTE_MIN_SORT_BUFFER_SIZE)
+// {
+// throw new System.ArgumentException(MIN_BUFFER_SIZE_MSG + ": " + bytes);
+// }
+//
+// this.Bytes = (int)bytes;
+// }
+//
+// /// <summary>
+// /// Creates a <seealso cref="BufferSize"/> in MB. The given
+// /// values must be > 0 and < 2048.
+// /// </summary>
+// public static BufferSize Megabytes(long mb)
+// {
+// return new BufferSize(mb * MB);
+// }
+//
+// /// <summary>
+// /// Approximately half of the currently available free heap, but no less
+// /// than <seealso cref="#ABSOLUTE_MIN_SORT_BUFFER_SIZE"/>. However if current heap allocation
+// /// is insufficient or if there is a large portion of unallocated heap-space available
+// /// for sorting consult with max allowed heap size.
+// /// </summary>
+// public static BufferSize Automatic()
+// {
+// var proc = Process.GetCurrentProcess();
+//
+// // take sizes in "conservative" order
+// long max = proc.PeakVirtualMemorySize64; // max allocated; java has it as Runtime.maxMemory();
+// long total = proc.VirtualMemorySize64; // currently allocated; java has it as Runtime.totalMemory();
+// long free = rt.freeMemory(); // unused portion of currently allocated
+// long totalAvailableBytes = max - total + free;
+//
+// // by free mem (attempting to not grow the heap for this)
+// long sortBufferByteSize = free / 2;
+// const long minBufferSizeBytes = MIN_BUFFER_SIZE_MB * MB;
+// if (sortBufferByteSize < minBufferSizeBytes || totalAvailableBytes > 10 * minBufferSizeBytes) // lets see if we need/should to grow the heap
+// {
+// if (totalAvailableBytes / 2 > minBufferSizeBytes) // there is enough mem for a reasonable buffer
+// {
+// sortBufferByteSize = totalAvailableBytes / 2; // grow the heap
+// }
+// else
+// {
+// //heap seems smallish lets be conservative fall back to the free/2
+// sortBufferByteSize = Math.Max(ABSOLUTE_MIN_SORT_BUFFER_SIZE, sortBufferByteSize);
+// }
+// }
+// return new BufferSize(Math.Min((long)int.MaxValue, sortBufferByteSize));
+// }
+// }
+//
+// /// <summary>
+// /// Sort info (debugging mostly).
+// /// </summary>
+// public class SortInfo
+// {
+// internal bool InstanceFieldsInitialized = false;
+//
+// internal virtual void InitializeInstanceFields()
+// {
+// BufferSize = OuterInstance.RamBufferSize.Bytes;
+// }
+//
+// private readonly OfflineSorter OuterInstance;
+//
+// /// <summary>
+// /// number of temporary files created when merging partitions </summary>
+// public int TempMergeFiles;
+// /// <summary>
+// /// number of partition merges </summary>
+// public int MergeRounds;
+// /// <summary>
+// /// number of lines of data read </summary>
+// public int Lines;
+// /// <summary>
+// /// time spent merging sorted partitions (in milliseconds) </summary>
+// public long MergeTime;
+// /// <summary>
+// /// time spent sorting data (in milliseconds) </summary>
+// public long SortTime;
+// /// <summary>
+// /// total time spent (in milliseconds) </summary>
+// public long TotalTime;
+// /// <summary>
+// /// time spent in i/o read (in milliseconds) </summary>
+// public long ReadTime;
+// /// <summary>
+// /// read buffer size (in bytes) </summary>
+// public long BufferSize;
+//
+// /// <summary>
+// /// create a new SortInfo (with empty statistics) for debugging </summary>
+// public SortInfo(OfflineSorter outerInstance)
+// {
+// this.OuterInstance = outerInstance;
+//
+// if (!InstanceFieldsInitialized)
+// {
+// InitializeInstanceFields();
+// InstanceFieldsInitialized = true;
+// }
+// }
+//
+// public override string ToString()
+// {
+// return string.Format("time=%.2f sec. total (%.2f reading, %.2f sorting, %.2f merging), lines=%d, temp files=%d, merges=%d, soft ram limit=%.2f MB", TotalTime / 1000.0d, ReadTime / 1000.0d, SortTime / 1000.0d, MergeTime / 1000.0d, Lines, TempMergeFiles, MergeRounds, (double)BufferSize / MB);
+// }
+// }
+//
+// private readonly BufferSize RamBufferSize;
+//
+// private readonly Counter BufferBytesUsed = Counter.NewCounter();
+// private BytesRefArray Buffer;
+// private SortInfo sortInfo;
+// private readonly int MaxTempFiles;
+// private readonly IComparer<BytesRef> comparator;
+//
+// /// <summary>
+// /// Default comparator: sorts in binary (codepoint) order </summary>
+// public static readonly IComparer<BytesRef> DEFAULT_COMPARATOR = BytesRef.UTF8SortedAsUnicodeComparator.Instance;
+//
+// /// <summary>
+// /// Defaults constructor.
+// /// </summary>
+// /// <seealso cref= #defaultTempDir() </seealso>
+// /// <seealso cref= BufferSize#automatic() </seealso>
+// public OfflineSorter()
+// : this(DEFAULT_COMPARATOR, BufferSize.Automatic(), DefaultTempDir(), MAX_TEMPFILES)
+// {
+// if (!InstanceFieldsInitialized)
+// {
+// InitializeInstanceFields();
+// InstanceFieldsInitialized = true;
+// }
+// }
+//
+// /// <summary>
+// /// Defaults constructor with a custom comparator.
+// /// </summary>
+// /// <seealso cref= #defaultTempDir() </seealso>
+// /// <seealso cref= BufferSize#automatic() </seealso>
+// public OfflineSorter(IComparer<BytesRef> comparator)
+// : this(comparator, BufferSize.Automatic(), DefaultTempDir(), MAX_TEMPFILES)
+// {
+// if (!InstanceFieldsInitialized)
+// {
+// InitializeInstanceFields();
+// InstanceFieldsInitialized = true;
+// }
+// }
+//
+// /// <summary>
+// /// All-details constructor.
+// /// </summary>
+// public OfflineSorter(IComparer<BytesRef> comparator, BufferSize ramBufferSize, /*DirectoryInfo tempDirectory,*/ int maxTempfiles)
+// {
+// if (!InstanceFieldsInitialized)
+// {
+// InitializeInstanceFields();
+// InstanceFieldsInitialized = true;
+// }
+// if (ramBufferSize.Bytes < ABSOLUTE_MIN_SORT_BUFFER_SIZE)
+// {
+// throw new System.ArgumentException(MIN_BUFFER_SIZE_MSG + ": " + ramBufferSize.Bytes);
+// }
+//
+// if (maxTempfiles < 2)
+// {
+// throw new System.ArgumentException("maxTempFiles must be >= 2");
+// }
+//
+// this.RamBufferSize = ramBufferSize;
+// this.MaxTempFiles = maxTempfiles;
+// this.comparator = comparator;
+// }
+//
+// /// <summary>
+// /// Sort input to output, explicit hint for the buffer size. The amount of allocated
+// /// memory may deviate from the hint (may be smaller or larger).
+// /// </summary>
+// public SortInfo Sort(FileInfo input, FileInfo output)
+// {
+// sortInfo = new SortInfo(this) {TotalTime = DateTime.Now.Millisecond};
+//
+// output.Delete();
+//
+// var merges = new List<FileInfo>();
+// bool success2 = false;
+// try
+// {
+// var inputStream = new ByteSequencesReader(input);
+// bool success = false;
+// try
+// {
+// int lines = 0;
+// while ((lines = ReadPartition(inputStream)) > 0)
+// {
+// merges.Add(SortPartition(lines));
+// sortInfo.TempMergeFiles++;
+// sortInfo.Lines += lines;
+//
+// // Handle intermediate merges.
+// if (merges.Count == MaxTempFiles)
+// {
+// var intermediate = new FileInfo(Path.GetTempFileName());
+// try
+// {
+// MergePartitions(merges, intermediate);
+// }
+// finally
+// {
+// foreach (var file in merges)
+// {
+// file.Delete();
+// }
+// merges.Clear();
+// merges.Add(intermediate);
+// }
+// sortInfo.TempMergeFiles++;
+// }
+// }
+// success = true;
+// }
+// finally
+// {
+// if (success)
+// {
+// IOUtils.Close(inputStream);
+// }
+// else
+// {
+// IOUtils.CloseWhileHandlingException(inputStream);
+// }
+// }
+//
+// // One partition, try to rename or copy if unsuccessful.
+// if (merges.Count == 1)
+// {
+// FileInfo single = merges[0];
+// Copy(single, output);
+// try
+// {
+// File.Delete(single.FullName);
+// }
+// catch (Exception)
+// {
+// // ignored
+// }
+// }
+// else
+// {
+// // otherwise merge the partitions with a priority queue.
+// MergePartitions(merges, output);
+// }
+// success2 = true;
+// }
+// finally
+// {
+// foreach (FileInfo file in merges)
+// {
+// file.Delete();
+// }
+// if (!success2)
+// {
+// output.Delete();
+// }
+// }
+//
+// sortInfo.TotalTime = (DateTime.Now.Millisecond - sortInfo.TotalTime);
+// return sortInfo;
+// }
+//
+// /// <summary>
+// /// Returns the default temporary directory. By default, the System's temp folder. If not accessible
+// /// or not available, an IOException is thrown
+// /// </summary>
+// public static DirectoryInfo DefaultTempDir()
+// {
+// return new DirectoryInfo(Path.GetTempPath());
+// }
+//
+// /// <summary>
+// /// Copies one file to another.
+// /// </summary>
+// private static void Copy(FileInfo file, FileInfo output)
+// {
+// File.Copy(file.FullName, output.FullName);
+// }
+//
+// /// <summary>
+// /// Sort a single partition in-memory. </summary>
+// internal FileInfo SortPartition(int len)
+// {
+// var data = this.Buffer;
+// var tempFile = new FileInfo(Path.GetTempFileName());
+// //var tempFile1 = File.Create(new ());
+// //FileInfo tempFile = FileInfo.createTempFile("sort", "partition", TempDirectory);
+//
+// long start = DateTime.Now.Millisecond;
+// sortInfo.SortTime += (DateTime.Now.Millisecond - start);
+//
+// var @out = new ByteSequencesWriter(tempFile);
+// BytesRef spare;
+// try
+// {
+// BytesRefIterator iter = Buffer.Iterator(comparator);
+// while ((spare = iter.Next()) != null)
+// {
+// Debug.Assert(spare.Length <= short.MaxValue);
+// @out.Write(spare);
+// }
+//
+// @out.Dispose();
+//
+// // Clean up the buffer for the next partition.
+// data.Clear();
+// return tempFile;
+// }
+// finally
+// {
+// IOUtils.Close(@out);
+// }
+// }
+//
+// /// <summary>
+// /// Merge a list of sorted temporary files (partitions) into an output file </summary>
+// internal void MergePartitions(IList<FileInfo> merges, FileInfo outputFile)
+// {
+// long start = DateTime.Now.Millisecond;
+//
+// var @out = new ByteSequencesWriter(outputFile);
+//
+// PriorityQueue<FileAndTop> queue = new PriorityQueueAnonymousInnerClassHelper(this, merges.Count);
+//
+// var streams = new ByteSequencesReader[merges.Count];
+// try
+// {
+// // Open streams and read the top for each file
+// for (int i = 0; i < merges.Count; i++)
+// {
+// streams[i] = new ByteSequencesReader(merges[i]);
+// sbyte[] line = streams[i].Read();
+// if (line != null)
+// {
+// queue.InsertWithOverflow(new FileAndTop(i, line));
+// }
+// }
+//
+// // Unix utility sort() uses ordered array of files to pick the next line from, updating
+// // it as it reads new lines. The PQ used here is a more elegant solution and has
+// // a nicer theoretical complexity bound :) The entire sorting process is I/O bound anyway
+// // so it shouldn't make much of a difference (didn't check).
+// FileAndTop top;
+// while ((top = queue.Top()) != null)
+// {
+// @out.Write(top.Current);
+// if (!streams[top.Fd].Read(top.Current))
+// {
+// queue.Pop();
+// }
+// else
+// {
+// queue.UpdateTop();
+// }
+// }
+//
+// SortInfo.MergeTime += DateTime.UtcNow.Ticks - start;
+// SortInfo.MergeRounds++;
+// }
+// finally
+// {
+// // The logic below is: if an exception occurs in closing out, it has a priority over exceptions
+// // happening in closing streams.
+// try
+// {
+// IOUtils.Close(streams);
+// }
+// finally
+// {
+// IOUtils.Close(@out);
+// }
+// }
+// }
+//
+// private class PriorityQueueAnonymousInnerClassHelper : PriorityQueue<FileAndTop>
+// {
+// private readonly OfflineSorter OuterInstance;
+//
+// public PriorityQueueAnonymousInnerClassHelper(OfflineSorter outerInstance, int size)
+// : base(size)
+// {
+// this.OuterInstance = outerInstance;
+// }
+//
+// public override bool LessThan(FileAndTop a, FileAndTop b)
+// {
+// return OuterInstance.comparator.Compare(a.Current, b.Current) < 0;
+// }
+// }
+//
+// /// <summary>
+// /// Read in a single partition of data </summary>
+// internal int ReadPartition(ByteSequencesReader reader)
+// {
+// long start = DateTime.Now.Millisecond;
+// var scratch = new BytesRef();
+// while ((scratch.Bytes = reader.Read()) != null)
+// {
+// scratch.Length = scratch.Bytes.Length;
+// Buffer.Append(scratch);
+// // Account for the created objects.
+// // (buffer slots do not account to buffer size.)
+// if (RamBufferSize.Bytes < BufferBytesUsed.Get())
+// {
+// break;
+// }
+// }
+// sortInfo.ReadTime += (DateTime.Now.Millisecond - start);
+// return Buffer.Size();
+// }
+//
+// internal class FileAndTop
+// {
+// internal readonly int Fd;
+// internal readonly BytesRef Current;
+//
+// internal FileAndTop(int fd, sbyte[] firstLine)
+// {
+// this.Fd = fd;
+// this.Current = new BytesRef(firstLine);
+// }
+// }
+//
+// /// <summary>
+// /// Utility class to emit length-prefixed byte[] entries to an output stream for sorting.
+// /// Complementary to <seealso cref="ByteSequencesReader"/>.
+// /// </summary>
+// public class ByteSequencesWriter : IDisposable
+// {
+// internal readonly DataOutput Os;
+//
+// /// <summary>
+// /// Constructs a ByteSequencesWriter to the provided File </summary>
+// public ByteSequencesWriter(FileInfo file)
+// : this(new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))))
+// {
+// }
+//
+// /// <summary>
+// /// Constructs a ByteSequencesWriter to the provided DataOutput </summary>
+// public ByteSequencesWriter(DataOutput os)
+// {
+// this.Os = os;
+// }
+//
+// /// <summary>
+// /// Writes a BytesRef. </summary>
+// /// <seealso cref= #write(byte[], int, int) </seealso>
+// public virtual void Write(BytesRef @ref)
+// {
+// Debug.Assert(@ref != null);
+// Write(@ref.Bytes, @ref.Offset, @ref.Length);
+// }
+//
+// /// <summary>
+// /// Writes a byte array. </summary>
+// /// <seealso cref= #write(byte[], int, int) </seealso>
+// public virtual void Write(sbyte[] bytes)
+// {
+// Write(bytes, 0, bytes.Length);
+// }
+//
+// /// <summary>
+// /// Writes a byte array.
+// /// <p>
+// /// The length is written as a <code>short</code>, followed
+// /// by the bytes.
+// /// </summary>
+// public virtual void Write(sbyte[] bytes, int off, int len)
+// {
+// Debug.Assert(bytes != null);
+// Debug.Assert(off >= 0 && off + len <= bytes.Length);
+// Debug.Assert(len >= 0);
+// Os.WriteShort(len);
+// Os.Write(bytes, off, len);
+// }
+//
+// /// <summary>
+// /// Closes the provided <seealso cref="DataOutput"/> if it is <seealso cref="IDisposable"/>.
+// /// </summary>
+// public void Dispose()
+// {
+// var os = Os as IDisposable;
+// if (os != null)
+// {
+// os.Dispose();
+// }
+// }
+// }
+//
+// /// <summary>
+// /// Utility class to read length-prefixed byte[] entries from an input.
+// /// Complementary to <seealso cref="ByteSequencesWriter"/>.
+// /// </summary>
+// public class ByteSequencesReader : IDisposable
+// {
+// internal readonly DataInput inputStream;
+//
+// /// <summary>
+// /// Constructs a ByteSequencesReader from the provided File </summary>
+// public ByteSequencesReader(FileInfo file)
+// : this(new DataInputStream(new BufferedInputStream(new FileInputStream(file))))
+// {
+// }
+//
+// /// <summary>
+// /// Constructs a ByteSequencesReader from the provided DataInput </summary>
+// public ByteSequencesReader(DataInput inputStream)
+// {
+// this.inputStream = inputStream;
+// }
+//
+// /// <summary>
+// /// Reads the next entry into the provided <seealso cref="BytesRef"/>. The internal
+// /// storage is resized if needed.
+// /// </summary>
+// /// <returns> Returns <code>false</code> if EOF occurred when trying to read
+// /// the header of the next sequence. Returns <code>true</code> otherwise. </returns>
+// /// <exception cref="EOFException"> if the file ends before the full sequence is read. </exception>
+// public virtual bool Read(BytesRef @ref)
+// {
+// short length;
+// try
+// {
+// length = inputStream.ReadShort();
+// }
+// catch (EOFException)
+// {
+// return false;
+// }
+//
+// @ref.Grow(length);
+// @ref.Offset = 0;
+// @ref.Length = length;
+// inputStream.ReadFully(@ref.Bytes, 0, length);
+// return true;
+// }
+//
+// /// <summary>
+// /// Reads the next entry and returns it if successful.
+// /// </summary>
+// /// <seealso cref= #read(BytesRef)
+// /// </seealso>
+// /// <returns> Returns <code>null</code> if EOF occurred before the next entry
+// /// could be read. </returns>
+// /// <exception cref="EOFException"> if the file ends before the full sequence is read. </exception>
+// public virtual sbyte[] Read()
+// {
+// short length;
+// try
+// {
+// length = inputStream.ReadShort();
+// }
+// catch (EOFException e)
+// {
+// return null;
+// }
+//
+// Debug.Assert(length >= 0, "Sanity: sequence length < 0: " + length);
+// sbyte[] result = new sbyte[length];
+// inputStream.ReadFully(result);
+// return result;
+// }
+//
+// /// <summary>
+// /// Closes the provided <seealso cref="DataInput"/> if it is <seealso cref="IDisposable"/>.
+// /// </summary>
+// public void Dispose()
+// {
+// var @is = inputStream as IDisposable;
+// if (@is != null)
+// {
+// @is.Dispose();
+// }
+// }
+// }
+//
+// /// <summary>
+// /// Returns the comparator in use to sort entries </summary>
+// public IComparer<BytesRef> Comparator
+// {
+// get
+// {
+// return comparator;
+// }
+// }
}
}
\ No newline at end of file
[06/11] Skeleton porting of Lucene.Net.Queries
Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/DocValues/BoolDocValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/DocValues/BoolDocValues.cs b/src/Lucene.Net.Queries/Function/DocValues/BoolDocValues.cs
new file mode 100644
index 0000000..1ad0517
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/DocValues/BoolDocValues.cs
@@ -0,0 +1,122 @@
+using System;
+
+namespace org.apache.lucene.queries.function.docvalues
+{
+
+ /*
+ * 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 MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueBool = org.apache.lucene.util.mutable.MutableValueBool;
+
+ /// <summary>
+ /// Abstract <seealso cref="FunctionValues"/> implementation which supports retrieving boolean values.
+ /// Implementations can control how the boolean values are loaded through <seealso cref="#boolVal(int)"/>}
+ /// </summary>
+ public abstract class BoolDocValues : FunctionValues
+ {
+ protected internal readonly ValueSource vs;
+
+ public BoolDocValues(ValueSource vs)
+ {
+ this.vs = vs;
+ }
+
+ public override abstract bool boolVal(int doc);
+
+ public override sbyte byteVal(int doc)
+ {
+ return boolVal(doc) ? (sbyte)1 : (sbyte)0;
+ }
+
+ public override short shortVal(int doc)
+ {
+ return boolVal(doc) ? (short)1 : (short)0;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return boolVal(doc) ? (float)1 : (float)0;
+ }
+
+ public override int intVal(int doc)
+ {
+ return boolVal(doc) ? 1 : 0;
+ }
+
+ public override long longVal(int doc)
+ {
+ return boolVal(doc) ? (long)1 : (long)0;
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return boolVal(doc) ? (double)1 : (double)0;
+ }
+
+ public override string strVal(int doc)
+ {
+ return Convert.ToString(boolVal(doc));
+ }
+
+ public override object objectVal(int doc)
+ {
+ return exists(doc) ? boolVal(doc) : null;
+ }
+
+ public override string ToString(int doc)
+ {
+ return vs.description() + '=' + strVal(doc);
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly BoolDocValues outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(BoolDocValues outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueBool();
+ }
+
+ private readonly MutableValueBool mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.boolVal(doc);
+ mval.exists = outerInstance.exists(doc);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/DocValues/DocTermsIndexDocValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/DocValues/DocTermsIndexDocValues.cs b/src/Lucene.Net.Queries/Function/DocValues/DocTermsIndexDocValues.cs
new file mode 100644
index 0000000..79f490c
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/DocValues/DocTermsIndexDocValues.cs
@@ -0,0 +1,234 @@
+using System;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.docvalues
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using SortedDocValues = org.apache.lucene.index.SortedDocValues;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+ using CharsRef = org.apache.lucene.util.CharsRef;
+ using UnicodeUtil = org.apache.lucene.util.UnicodeUtil;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueStr = org.apache.lucene.util.mutable.MutableValueStr;
+
+ /// <summary>
+ /// Serves as base class for FunctionValues based on DocTermsIndex.
+ /// @lucene.internal
+ /// </summary>
+ public abstract class DocTermsIndexDocValues : FunctionValues
+ {
+ protected internal readonly SortedDocValues termsIndex;
+ protected internal readonly ValueSource vs;
+ protected internal readonly MutableValueStr val = new MutableValueStr();
+ protected internal readonly BytesRef spare = new BytesRef();
+ protected internal readonly CharsRef spareChars = new CharsRef();
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public DocTermsIndexDocValues(org.apache.lucene.queries.function.ValueSource vs, org.apache.lucene.index.AtomicReaderContext context, String field) throws java.io.IOException
+ public DocTermsIndexDocValues(ValueSource vs, AtomicReaderContext context, string field)
+ {
+ try
+ {
+ termsIndex = FieldCache.DEFAULT.getTermsIndex(context.reader(), field);
+ }
+ catch (Exception e)
+ {
+ throw new DocTermsIndexException(field, e);
+ }
+ this.vs = vs;
+ }
+
+ protected internal abstract string toTerm(string readableValue);
+
+ public override bool exists(int doc)
+ {
+ return ordVal(doc) >= 0;
+ }
+
+ public override int ordVal(int doc)
+ {
+ return termsIndex.getOrd(doc);
+ }
+
+ public override int numOrd()
+ {
+ return termsIndex.ValueCount;
+ }
+
+ public override bool bytesVal(int doc, BytesRef target)
+ {
+ termsIndex.get(doc, target);
+ return target.length > 0;
+ }
+
+ public override string strVal(int doc)
+ {
+ termsIndex.get(doc, spare);
+ if (spare.length == 0)
+ {
+ return null;
+ }
+ UnicodeUtil.UTF8toUTF16(spare, spareChars);
+ return spareChars.ToString();
+ }
+
+ public override bool boolVal(int doc)
+ {
+ return exists(doc);
+ }
+
+ public override abstract object objectVal(int doc); // force subclasses to override
+
+ public override ValueSourceScorer getRangeScorer(IndexReader reader, string lowerVal, string upperVal, bool includeLower, bool includeUpper)
+ {
+ // TODO: are lowerVal and upperVal in indexed form or not?
+ lowerVal = lowerVal == null ? null : toTerm(lowerVal);
+ upperVal = upperVal == null ? null : toTerm(upperVal);
+
+ int lower = int.MinValue;
+ if (lowerVal != null)
+ {
+ lower = termsIndex.lookupTerm(new BytesRef(lowerVal));
+ if (lower < 0)
+ {
+ lower = -lower - 1;
+ }
+ else if (!includeLower)
+ {
+ lower++;
+ }
+ }
+
+ int upper = int.MaxValue;
+ if (upperVal != null)
+ {
+ upper = termsIndex.lookupTerm(new BytesRef(upperVal));
+ if (upper < 0)
+ {
+ upper = -upper - 2;
+ }
+ else if (!includeUpper)
+ {
+ upper--;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int ll = lower;
+ int ll = lower;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int uu = upper;
+ int uu = upper;
+
+ return new ValueSourceScorerAnonymousInnerClassHelper(this, reader, this, ll, uu);
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper : ValueSourceScorer
+ {
+ private readonly DocTermsIndexDocValues outerInstance;
+
+ private int ll;
+ private int uu;
+
+ public ValueSourceScorerAnonymousInnerClassHelper(DocTermsIndexDocValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.docvalues.DocTermsIndexDocValues this, int ll, int uu) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.ll = ll;
+ this.uu = uu;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ int ord = outerInstance.termsIndex.getOrd(doc);
+ return ord >= ll && ord <= uu;
+ }
+ }
+
+ public override string ToString(int doc)
+ {
+ return vs.description() + '=' + strVal(doc);
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly DocTermsIndexDocValues outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(DocTermsIndexDocValues outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueStr();
+ }
+
+ private readonly MutableValueStr mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ int ord = outerInstance.termsIndex.getOrd(doc);
+ if (ord == -1)
+ {
+ mval.value.bytes = BytesRef.EMPTY_BYTES;
+ mval.value.offset = 0;
+ mval.value.length = 0;
+ mval.exists = false;
+ }
+ else
+ {
+ outerInstance.termsIndex.lookupOrd(ord, mval.value);
+ mval.exists = true;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Custom Exception to be thrown when the DocTermsIndex for a field cannot be generated
+ /// </summary>
+ public sealed class DocTermsIndexException : Exception
+ {
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public DocTermsIndexException(final String fieldName, final RuntimeException cause)
+ public DocTermsIndexException(string fieldName, Exception cause) : base("Can't initialize DocTermsIndex to generate (function) FunctionValues for field: " + fieldName, cause)
+ {
+ }
+
+ }
+
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/DocValues/DoubleDocValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/DocValues/DoubleDocValues.cs b/src/Lucene.Net.Queries/Function/DocValues/DoubleDocValues.cs
new file mode 100644
index 0000000..afc2a59
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/DocValues/DoubleDocValues.cs
@@ -0,0 +1,256 @@
+using System;
+
+namespace org.apache.lucene.queries.function.docvalues
+{
+
+ /*
+ * 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 IndexReader = org.apache.lucene.index.IndexReader;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueDouble = org.apache.lucene.util.mutable.MutableValueDouble;
+
+ /// <summary>
+ /// Abstract <seealso cref="FunctionValues"/> implementation which supports retrieving double values.
+ /// Implementations can control how the double values are loaded through <seealso cref="#doubleVal(int)"/>}
+ /// </summary>
+ public abstract class DoubleDocValues : FunctionValues
+ {
+ protected internal readonly ValueSource vs;
+
+ public DoubleDocValues(ValueSource vs)
+ {
+ this.vs = vs;
+ }
+
+ public override sbyte byteVal(int doc)
+ {
+ return (sbyte)doubleVal(doc);
+ }
+
+ public override short shortVal(int doc)
+ {
+ return (short)doubleVal(doc);
+ }
+
+ public override float floatVal(int doc)
+ {
+ return (float)doubleVal(doc);
+ }
+
+ public override int intVal(int doc)
+ {
+ return (int)doubleVal(doc);
+ }
+
+ public override long longVal(int doc)
+ {
+ return (long)doubleVal(doc);
+ }
+
+ public override bool boolVal(int doc)
+ {
+ return doubleVal(doc) != 0;
+ }
+
+ public override abstract double doubleVal(int doc);
+
+ public override string strVal(int doc)
+ {
+ return Convert.ToString(doubleVal(doc));
+ }
+
+ public override object objectVal(int doc)
+ {
+ return exists(doc) ? doubleVal(doc) : null;
+ }
+
+ public override string ToString(int doc)
+ {
+ return vs.description() + '=' + strVal(doc);
+ }
+
+ public override ValueSourceScorer getRangeScorer(IndexReader reader, string lowerVal, string upperVal, bool includeLower, bool includeUpper)
+ {
+ double lower, upper;
+
+ if (lowerVal == null)
+ {
+ lower = double.NegativeInfinity;
+ }
+ else
+ {
+ lower = Convert.ToDouble(lowerVal);
+ }
+
+ if (upperVal == null)
+ {
+ upper = double.PositiveInfinity;
+ }
+ else
+ {
+ upper = Convert.ToDouble(upperVal);
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final double l = lower;
+ double l = lower;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final double u = upper;
+ double u = upper;
+
+
+ if (includeLower && includeUpper)
+ {
+ return new ValueSourceScorerAnonymousInnerClassHelper(this, reader, this, l, u);
+ }
+ else if (includeLower && !includeUpper)
+ {
+ return new ValueSourceScorerAnonymousInnerClassHelper2(this, reader, this, l, u);
+ }
+ else if (!includeLower && includeUpper)
+ {
+ return new ValueSourceScorerAnonymousInnerClassHelper3(this, reader, this, l, u);
+ }
+ else
+ {
+ return new ValueSourceScorerAnonymousInnerClassHelper4(this, reader, this, l, u);
+ }
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper : ValueSourceScorer
+ {
+ private readonly DoubleDocValues outerInstance;
+
+ private double l;
+ private double u;
+
+ public ValueSourceScorerAnonymousInnerClassHelper(DoubleDocValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.docvalues.DoubleDocValues this, double l, double u) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.l = l;
+ this.u = u;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ double docVal = outerInstance.doubleVal(doc);
+ return docVal >= l && docVal <= u;
+ }
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper2 : ValueSourceScorer
+ {
+ private readonly DoubleDocValues outerInstance;
+
+ private double l;
+ private double u;
+
+ public ValueSourceScorerAnonymousInnerClassHelper2(DoubleDocValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.docvalues.DoubleDocValues this, double l, double u) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.l = l;
+ this.u = u;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ double docVal = outerInstance.doubleVal(doc);
+ return docVal >= l && docVal < u;
+ }
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper3 : ValueSourceScorer
+ {
+ private readonly DoubleDocValues outerInstance;
+
+ private double l;
+ private double u;
+
+ public ValueSourceScorerAnonymousInnerClassHelper3(DoubleDocValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.docvalues.DoubleDocValues this, double l, double u) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.l = l;
+ this.u = u;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ double docVal = outerInstance.doubleVal(doc);
+ return docVal > l && docVal <= u;
+ }
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper4 : ValueSourceScorer
+ {
+ private readonly DoubleDocValues outerInstance;
+
+ private double l;
+ private double u;
+
+ public ValueSourceScorerAnonymousInnerClassHelper4(DoubleDocValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.docvalues.DoubleDocValues this, double l, double u) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.l = l;
+ this.u = u;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ double docVal = outerInstance.doubleVal(doc);
+ return docVal > l && docVal < u;
+ }
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly DoubleDocValues outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(DoubleDocValues outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueDouble();
+ }
+
+ private readonly MutableValueDouble mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.doubleVal(doc);
+ mval.exists = outerInstance.exists(doc);
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/DocValues/FloatDocValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/DocValues/FloatDocValues.cs b/src/Lucene.Net.Queries/Function/DocValues/FloatDocValues.cs
new file mode 100644
index 0000000..72df9b0
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/DocValues/FloatDocValues.cs
@@ -0,0 +1,117 @@
+using System;
+
+namespace org.apache.lucene.queries.function.docvalues
+{
+
+ /*
+ * 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 MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueFloat = org.apache.lucene.util.mutable.MutableValueFloat;
+
+ /// <summary>
+ /// Abstract <seealso cref="FunctionValues"/> implementation which supports retrieving float values.
+ /// Implementations can control how the float values are loaded through <seealso cref="#floatVal(int)"/>}
+ /// </summary>
+ public abstract class FloatDocValues : FunctionValues
+ {
+ protected internal readonly ValueSource vs;
+
+ public FloatDocValues(ValueSource vs)
+ {
+ this.vs = vs;
+ }
+
+ public override sbyte byteVal(int doc)
+ {
+ return (sbyte)floatVal(doc);
+ }
+
+ public override short shortVal(int doc)
+ {
+ return (short)floatVal(doc);
+ }
+
+ public override abstract float floatVal(int doc);
+
+ public override int intVal(int doc)
+ {
+ return (int)floatVal(doc);
+ }
+
+ public override long longVal(int doc)
+ {
+ return (long)floatVal(doc);
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return (double)floatVal(doc);
+ }
+
+ public override string strVal(int doc)
+ {
+ return Convert.ToString(floatVal(doc));
+ }
+
+ public override object objectVal(int doc)
+ {
+ return exists(doc) ? floatVal(doc) : null;
+ }
+
+ public override string ToString(int doc)
+ {
+ return vs.description() + '=' + strVal(doc);
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly FloatDocValues outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(FloatDocValues outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueFloat();
+ }
+
+ private readonly MutableValueFloat mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.floatVal(doc);
+ mval.exists = outerInstance.exists(doc);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/DocValues/IntDocValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/DocValues/IntDocValues.cs b/src/Lucene.Net.Queries/Function/DocValues/IntDocValues.cs
new file mode 100644
index 0000000..c3f934e
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/DocValues/IntDocValues.cs
@@ -0,0 +1,183 @@
+using System;
+
+namespace org.apache.lucene.queries.function.docvalues
+{
+
+ /*
+ * 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 IndexReader = org.apache.lucene.index.IndexReader;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueInt = org.apache.lucene.util.mutable.MutableValueInt;
+
+ /// <summary>
+ /// Abstract <seealso cref="FunctionValues"/> implementation which supports retrieving int values.
+ /// Implementations can control how the int values are loaded through <seealso cref="#intVal(int)"/>
+ /// </summary>
+ public abstract class IntDocValues : FunctionValues
+ {
+ protected internal readonly ValueSource vs;
+
+ public IntDocValues(ValueSource vs)
+ {
+ this.vs = vs;
+ }
+
+ public override sbyte byteVal(int doc)
+ {
+ return (sbyte)intVal(doc);
+ }
+
+ public override short shortVal(int doc)
+ {
+ return (short)intVal(doc);
+ }
+
+ public override float floatVal(int doc)
+ {
+ return (float)intVal(doc);
+ }
+
+ public override abstract int intVal(int doc);
+
+ public override long longVal(int doc)
+ {
+ return (long)intVal(doc);
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return (double)intVal(doc);
+ }
+
+ public override string strVal(int doc)
+ {
+ return Convert.ToString(intVal(doc));
+ }
+
+ public override object objectVal(int doc)
+ {
+ return exists(doc) ? intVal(doc) : null;
+ }
+
+ public override string ToString(int doc)
+ {
+ return vs.description() + '=' + strVal(doc);
+ }
+
+ public override ValueSourceScorer getRangeScorer(IndexReader reader, string lowerVal, string upperVal, bool includeLower, bool includeUpper)
+ {
+ int lower, upper;
+
+ // instead of using separate comparison functions, adjust the endpoints.
+
+ if (lowerVal == null)
+ {
+ lower = int.MinValue;
+ }
+ else
+ {
+ lower = Convert.ToInt32(lowerVal);
+ if (!includeLower && lower < int.MaxValue)
+ {
+ lower++;
+ }
+ }
+
+ if (upperVal == null)
+ {
+ upper = int.MaxValue;
+ }
+ else
+ {
+ upper = Convert.ToInt32(upperVal);
+ if (!includeUpper && upper > int.MinValue)
+ {
+ upper--;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int ll = lower;
+ int ll = lower;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int uu = upper;
+ int uu = upper;
+
+ return new ValueSourceScorerAnonymousInnerClassHelper(this, reader, this, ll, uu);
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper : ValueSourceScorer
+ {
+ private readonly IntDocValues outerInstance;
+
+ private int ll;
+ private int uu;
+
+ public ValueSourceScorerAnonymousInnerClassHelper(IntDocValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.docvalues.IntDocValues this, int ll, int uu) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.ll = ll;
+ this.uu = uu;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ int val = outerInstance.intVal(doc);
+ // only check for deleted if it's the default value
+ // if (val==0 && reader.isDeleted(doc)) return false;
+ return val >= ll && val <= uu;
+ }
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly IntDocValues outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(IntDocValues outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueInt();
+ }
+
+ private readonly MutableValueInt mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.intVal(doc);
+ mval.exists = outerInstance.exists(doc);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/DocValues/LongDocValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/DocValues/LongDocValues.cs b/src/Lucene.Net.Queries/Function/DocValues/LongDocValues.cs
new file mode 100644
index 0000000..da27a4c
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/DocValues/LongDocValues.cs
@@ -0,0 +1,193 @@
+using System;
+
+namespace org.apache.lucene.queries.function.docvalues
+{
+
+ /*
+ * 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 IndexReader = org.apache.lucene.index.IndexReader;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueLong = org.apache.lucene.util.mutable.MutableValueLong;
+
+ /// <summary>
+ /// Abstract <seealso cref="FunctionValues"/> implementation which supports retrieving long values.
+ /// Implementations can control how the long values are loaded through <seealso cref="#longVal(int)"/>}
+ /// </summary>
+ public abstract class LongDocValues : FunctionValues
+ {
+ protected internal readonly ValueSource vs;
+
+ public LongDocValues(ValueSource vs)
+ {
+ this.vs = vs;
+ }
+
+ public override sbyte byteVal(int doc)
+ {
+ return (sbyte)longVal(doc);
+ }
+
+ public override short shortVal(int doc)
+ {
+ return (short)longVal(doc);
+ }
+
+ public override float floatVal(int doc)
+ {
+ return (float)longVal(doc);
+ }
+
+ public override int intVal(int doc)
+ {
+ return (int)longVal(doc);
+ }
+
+ public override abstract long longVal(int doc);
+
+ public override double doubleVal(int doc)
+ {
+ return (double)longVal(doc);
+ }
+
+ public override bool boolVal(int doc)
+ {
+ return longVal(doc) != 0;
+ }
+
+ public override string strVal(int doc)
+ {
+ return Convert.ToString(longVal(doc));
+ }
+
+ public override object objectVal(int doc)
+ {
+ return exists(doc) ? longVal(doc) : null;
+ }
+
+ public override string ToString(int doc)
+ {
+ return vs.description() + '=' + strVal(doc);
+ }
+
+ protected internal virtual long externalToLong(string extVal)
+ {
+ return Convert.ToInt64(extVal);
+ }
+
+ public override ValueSourceScorer getRangeScorer(IndexReader reader, string lowerVal, string upperVal, bool includeLower, bool includeUpper)
+ {
+ long lower, upper;
+
+ // instead of using separate comparison functions, adjust the endpoints.
+
+ if (lowerVal == null)
+ {
+ lower = long.MinValue;
+ }
+ else
+ {
+ lower = externalToLong(lowerVal);
+ if (!includeLower && lower < long.MaxValue)
+ {
+ lower++;
+ }
+ }
+
+ if (upperVal == null)
+ {
+ upper = long.MaxValue;
+ }
+ else
+ {
+ upper = externalToLong(upperVal);
+ if (!includeUpper && upper > long.MinValue)
+ {
+ upper--;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long ll = lower;
+ long ll = lower;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long uu = upper;
+ long uu = upper;
+
+ return new ValueSourceScorerAnonymousInnerClassHelper(this, reader, this, ll, uu);
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper : ValueSourceScorer
+ {
+ private readonly LongDocValues outerInstance;
+
+ private long ll;
+ private long uu;
+
+ public ValueSourceScorerAnonymousInnerClassHelper(LongDocValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.docvalues.LongDocValues this, long ll, long uu) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.ll = ll;
+ this.uu = uu;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ long val = outerInstance.longVal(doc);
+ // only check for deleted if it's the default value
+ // if (val==0 && reader.isDeleted(doc)) return false;
+ return val >= ll && val <= uu;
+ }
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly LongDocValues outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(LongDocValues outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueLong();
+ }
+
+ private readonly MutableValueLong mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.longVal(doc);
+ mval.exists = outerInstance.exists(doc);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/DocValues/StrDocValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/DocValues/StrDocValues.cs b/src/Lucene.Net.Queries/Function/DocValues/StrDocValues.cs
new file mode 100644
index 0000000..ea3c450
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/DocValues/StrDocValues.cs
@@ -0,0 +1,89 @@
+namespace org.apache.lucene.queries.function.docvalues
+{
+
+ /*
+ * 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 MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueStr = org.apache.lucene.util.mutable.MutableValueStr;
+
+ /// <summary>
+ /// Abstract <seealso cref="FunctionValues"/> implementation which supports retrieving String values.
+ /// Implementations can control how the String values are loaded through <seealso cref="#strVal(int)"/>}
+ /// </summary>
+ public abstract class StrDocValues : FunctionValues
+ {
+ protected internal readonly ValueSource vs;
+
+ public StrDocValues(ValueSource vs)
+ {
+ this.vs = vs;
+ }
+
+ public override abstract string strVal(int doc);
+
+ public override object objectVal(int doc)
+ {
+ return exists(doc) ? strVal(doc) : null;
+ }
+
+ public override bool boolVal(int doc)
+ {
+ return exists(doc);
+ }
+
+ public override string ToString(int doc)
+ {
+ return vs.description() + "='" + strVal(doc) + "'";
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly StrDocValues outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(StrDocValues outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueStr();
+ }
+
+ private readonly MutableValueStr mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.exists = outerInstance.bytesVal(doc, mval.value);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/FunctionQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/FunctionQuery.cs b/src/Lucene.Net.Queries/Function/FunctionQuery.cs
new file mode 100644
index 0000000..e0642f1
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/FunctionQuery.cs
@@ -0,0 +1,270 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace org.apache.lucene.queries.function
+{
+
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using Term = org.apache.lucene.index.Term;
+ using org.apache.lucene.search;
+ using MultiFields = org.apache.lucene.index.MultiFields;
+ using Bits = org.apache.lucene.util.Bits;
+
+
+
+ /// <summary>
+ /// Returns a score for each document based on a ValueSource,
+ /// often some function of the value of a field.
+ ///
+ /// <b>Note: This API is experimental and may change in non backward-compatible ways in the future</b>
+ ///
+ ///
+ /// </summary>
+ public class FunctionQuery : Query
+ {
+ internal readonly ValueSource func;
+
+ /// <param name="func"> defines the function to be used for scoring </param>
+ public FunctionQuery(ValueSource func)
+ {
+ this.func = func;
+ }
+
+ /// <returns> The associated ValueSource </returns>
+ public virtual ValueSource ValueSource
+ {
+ get
+ {
+ return func;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Query rewrite(org.apache.lucene.index.IndexReader reader) throws java.io.IOException
+ public override Query rewrite(IndexReader reader)
+ {
+ return this;
+ }
+
+ public override void extractTerms(HashSet<Term> terms)
+ {
+ }
+
+ protected internal class FunctionWeight : Weight
+ {
+ private readonly FunctionQuery outerInstance;
+
+ protected internal readonly IndexSearcher searcher;
+ protected internal float queryNorm;
+ protected internal float queryWeight;
+ protected internal readonly IDictionary context;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public FunctionWeight(IndexSearcher searcher) throws java.io.IOException
+ public FunctionWeight(FunctionQuery outerInstance, IndexSearcher searcher)
+ {
+ this.outerInstance = outerInstance;
+ this.searcher = searcher;
+ this.context = ValueSource.newContext(searcher);
+ outerInstance.func.createWeight(context, searcher);
+ }
+
+ public override Query Query
+ {
+ get
+ {
+ return outerInstance;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public float getValueForNormalization() throws java.io.IOException
+ public override float ValueForNormalization
+ {
+ get
+ {
+ queryWeight = Boost;
+ return queryWeight * queryWeight;
+ }
+ }
+
+ public override void normalize(float norm, float topLevelBoost)
+ {
+ this.queryNorm = norm * topLevelBoost;
+ queryWeight *= this.queryNorm;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Scorer scorer(org.apache.lucene.index.AtomicReaderContext context, org.apache.lucene.util.Bits acceptDocs) throws java.io.IOException
+ public override Scorer scorer(AtomicReaderContext context, Bits acceptDocs)
+ {
+ return new AllScorer(outerInstance, context, acceptDocs, this, queryWeight);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Explanation explain(org.apache.lucene.index.AtomicReaderContext context, int doc) throws java.io.IOException
+ public override Explanation explain(AtomicReaderContext context, int doc)
+ {
+ return ((AllScorer)scorer(context, context.reader().LiveDocs)).explain(doc);
+ }
+ }
+
+ protected internal class AllScorer : Scorer
+ {
+ private readonly FunctionQuery outerInstance;
+
+ internal readonly IndexReader reader;
+ internal readonly FunctionWeight weight;
+ internal readonly int maxDoc;
+ internal readonly float qWeight;
+ internal int doc = -1;
+ internal readonly FunctionValues vals;
+ internal readonly Bits acceptDocs;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public AllScorer(org.apache.lucene.index.AtomicReaderContext context, org.apache.lucene.util.Bits acceptDocs, FunctionWeight w, float qWeight) throws java.io.IOException
+ public AllScorer(FunctionQuery outerInstance, AtomicReaderContext context, Bits acceptDocs, FunctionWeight w, float qWeight) : base(w)
+ {
+ this.outerInstance = outerInstance;
+ this.weight = w;
+ this.qWeight = qWeight;
+ this.reader = context.reader();
+ this.maxDoc = reader.maxDoc();
+ this.acceptDocs = acceptDocs;
+ vals = outerInstance.func.getValues(weight.context, context);
+ }
+
+ public override int docID()
+ {
+ return doc;
+ }
+
+ // instead of matching all docs, we could also embed a query.
+ // the score could either ignore the subscore, or boost it.
+ // Containment: floatline(foo:myTerm, "myFloatField", 1.0, 0.0f)
+ // Boost: foo:myTerm^floatline("myFloatField",1.0,0.0f)
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int nextDoc() throws java.io.IOException
+ public override int nextDoc()
+ {
+ for (;;)
+ {
+ ++doc;
+ if (doc >= maxDoc)
+ {
+ return doc = NO_MORE_DOCS;
+ }
+ if (acceptDocs != null && !acceptDocs.get(doc))
+ {
+ continue;
+ }
+ return doc;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int advance(int target) throws java.io.IOException
+ public override int advance(int target)
+ {
+ // this will work even if target==NO_MORE_DOCS
+ doc = target - 1;
+ return nextDoc();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public float score() throws java.io.IOException
+ public override float score()
+ {
+ float score = qWeight * vals.floatVal(doc);
+
+ // Current Lucene priority queues can't handle NaN and -Infinity, so
+ // map to -Float.MAX_VALUE. This conditional handles both -infinity
+ // and NaN since comparisons with NaN are always false.
+ return score > float.NegativeInfinity ? score : -float.MaxValue;
+ }
+
+ public override long cost()
+ {
+ return maxDoc;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int freq() throws java.io.IOException
+ public override int freq()
+ {
+ return 1;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public Explanation explain(int doc) throws java.io.IOException
+ public virtual Explanation explain(int doc)
+ {
+ float sc = qWeight * vals.floatVal(doc);
+
+ Explanation result = new ComplexExplanation(true, sc, "FunctionQuery(" + outerInstance.func + "), product of:");
+
+ result.addDetail(vals.explain(doc));
+ result.addDetail(new Explanation(Boost, "boost"));
+ result.addDetail(new Explanation(weight.queryNorm,"queryNorm"));
+ return result;
+ }
+ }
+
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Weight createWeight(IndexSearcher searcher) throws java.io.IOException
+ public override Weight createWeight(IndexSearcher searcher)
+ {
+ return new FunctionQuery.FunctionWeight(this, searcher);
+ }
+
+
+ /// <summary>
+ /// Prints a user-readable version of this query. </summary>
+ public override string ToString(string field)
+ {
+ float boost = Boost;
+ return (boost != 1.0?"(":"") + func.ToString() + (boost == 1.0 ? "" : ")^" + boost);
+ }
+
+
+ /// <summary>
+ /// Returns true if <code>o</code> is equal to this. </summary>
+ public override bool Equals(object o)
+ {
+ if (!typeof(FunctionQuery).IsInstanceOfType(o))
+ {
+ return false;
+ }
+ FunctionQuery other = (FunctionQuery)o;
+ return this.Boost == other.Boost && this.func.Equals(other.func);
+ }
+
+ /// <summary>
+ /// Returns a hash code value for this object. </summary>
+ public override int GetHashCode()
+ {
+ return func.GetHashCode() * 31 + float.floatToIntBits(Boost);
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/FunctionValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/FunctionValues.cs b/src/Lucene.Net.Queries/Function/FunctionValues.cs
new file mode 100644
index 0000000..862d0ba
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/FunctionValues.cs
@@ -0,0 +1,362 @@
+using System;
+
+namespace org.apache.lucene.queries.function
+{
+
+ /*
+ * 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 org.apache.lucene.search;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueFloat = org.apache.lucene.util.mutable.MutableValueFloat;
+
+ /// <summary>
+ /// Represents field values as different types.
+ /// Normally created via a <seealso cref="ValueSource"/> for a particular field and reader.
+ ///
+ ///
+ /// </summary>
+
+ // FunctionValues is distinct from ValueSource because
+ // there needs to be an object created at query evaluation time that
+ // is not referenced by the query itself because:
+ // - Query objects should be MT safe
+ // - For caching, Query objects are often used as keys... you don't
+ // want the Query carrying around big objects
+ public abstract class FunctionValues
+ {
+
+ public virtual sbyte byteVal(int doc)
+ {
+ throw new System.NotSupportedException();
+ }
+ public virtual short shortVal(int doc)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public virtual float floatVal(int doc)
+ {
+ throw new System.NotSupportedException();
+ }
+ public virtual int intVal(int doc)
+ {
+ throw new System.NotSupportedException();
+ }
+ public virtual long longVal(int doc)
+ {
+ throw new System.NotSupportedException();
+ }
+ public virtual double doubleVal(int doc)
+ {
+ throw new System.NotSupportedException();
+ }
+ // TODO: should we make a termVal, returns BytesRef?
+ public virtual string strVal(int doc)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public virtual bool boolVal(int doc)
+ {
+ return intVal(doc) != 0;
+ }
+
+ /// <summary>
+ /// returns the bytes representation of the string val - TODO: should this return the indexed raw bytes not? </summary>
+ public virtual bool bytesVal(int doc, BytesRef target)
+ {
+ string s = strVal(doc);
+ if (s == null)
+ {
+ target.length = 0;
+ return false;
+ }
+ target.copyChars(s);
+ return true;
+ }
+
+ /// <summary>
+ /// Native Java Object representation of the value </summary>
+ public virtual object objectVal(int doc)
+ {
+ // most FunctionValues are functions, so by default return a Float()
+ return floatVal(doc);
+ }
+
+ /// <summary>
+ /// Returns true if there is a value for this document </summary>
+ public virtual bool exists(int doc)
+ {
+ return true;
+ }
+
+ /// <param name="doc"> The doc to retrieve to sort ordinal for </param>
+ /// <returns> the sort ordinal for the specified doc
+ /// TODO: Maybe we can just use intVal for this... </returns>
+ public virtual int ordVal(int doc)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ /// <returns> the number of unique sort ordinals this instance has </returns>
+ public virtual int numOrd()
+ {
+ throw new System.NotSupportedException();
+ }
+ public abstract string ToString(int doc);
+
+ /// <summary>
+ /// Abstraction of the logic required to fill the value of a specified doc into
+ /// a reusable <seealso cref="MutableValue"/>. Implementations of <seealso cref="FunctionValues"/>
+ /// are encouraged to define their own implementations of ValueFiller if their
+ /// value is not a float.
+ ///
+ /// @lucene.experimental
+ /// </summary>
+ public abstract class ValueFiller
+ {
+ /// <summary>
+ /// MutableValue will be reused across calls </summary>
+ public abstract MutableValue Value {get;}
+
+ /// <summary>
+ /// MutableValue will be reused across calls. Returns true if the value exists. </summary>
+ public abstract void fillValue(int doc);
+ }
+
+ /// <summary>
+ /// @lucene.experimental </summary>
+ public virtual ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly FunctionValues outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(FunctionValues outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueFloat();
+ }
+
+ private readonly MutableValueFloat mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.floatVal(doc);
+ }
+ }
+
+ //For Functions that can work with multiple values from the same document. This does not apply to all functions
+ public virtual void byteVal(int doc, sbyte[] vals)
+ {
+ throw new System.NotSupportedException();
+ }
+ public virtual void shortVal(int doc, short[] vals)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public virtual void floatVal(int doc, float[] vals)
+ {
+ throw new System.NotSupportedException();
+ }
+ public virtual void intVal(int doc, int[] vals)
+ {
+ throw new System.NotSupportedException();
+ }
+ public virtual void longVal(int doc, long[] vals)
+ {
+ throw new System.NotSupportedException();
+ }
+ public virtual void doubleVal(int doc, double[] vals)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ // TODO: should we make a termVal, fills BytesRef[]?
+ public virtual void strVal(int doc, string[] vals)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public virtual Explanation explain(int doc)
+ {
+ return new Explanation(floatVal(doc), ToString(doc));
+ }
+
+ public virtual ValueSourceScorer getScorer(IndexReader reader)
+ {
+ return new ValueSourceScorer(reader, this);
+ }
+
+ // A RangeValueSource can't easily be a ValueSource that takes another ValueSource
+ // because it needs different behavior depending on the type of fields. There is also
+ // a setup cost - parsing and normalizing params, and doing a binary search on the StringIndex.
+ // TODO: change "reader" to AtomicReaderContext
+ public virtual ValueSourceScorer getRangeScorer(IndexReader reader, string lowerVal, string upperVal, bool includeLower, bool includeUpper)
+ {
+ float lower;
+ float upper;
+
+ if (lowerVal == null)
+ {
+ lower = float.NegativeInfinity;
+ }
+ else
+ {
+ lower = Convert.ToSingle(lowerVal);
+ }
+ if (upperVal == null)
+ {
+ upper = float.PositiveInfinity;
+ }
+ else
+ {
+ upper = Convert.ToSingle(upperVal);
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float l = lower;
+ float l = lower;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float u = upper;
+ float u = upper;
+
+ if (includeLower && includeUpper)
+ {
+ return new ValueSourceScorerAnonymousInnerClassHelper(this, reader, this, l, u);
+ }
+ else if (includeLower && !includeUpper)
+ {
+ return new ValueSourceScorerAnonymousInnerClassHelper2(this, reader, this, l, u);
+ }
+ else if (!includeLower && includeUpper)
+ {
+ return new ValueSourceScorerAnonymousInnerClassHelper3(this, reader, this, l, u);
+ }
+ else
+ {
+ return new ValueSourceScorerAnonymousInnerClassHelper4(this, reader, this, l, u);
+ }
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper : ValueSourceScorer
+ {
+ private readonly FunctionValues outerInstance;
+
+ private float l;
+ private float u;
+
+ public ValueSourceScorerAnonymousInnerClassHelper(FunctionValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.FunctionValues this, float l, float u) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.l = l;
+ this.u = u;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ float docVal = outerInstance.floatVal(doc);
+ return docVal >= l && docVal <= u;
+ }
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper2 : ValueSourceScorer
+ {
+ private readonly FunctionValues outerInstance;
+
+ private float l;
+ private float u;
+
+ public ValueSourceScorerAnonymousInnerClassHelper2(FunctionValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.FunctionValues this, float l, float u) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.l = l;
+ this.u = u;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ float docVal = outerInstance.floatVal(doc);
+ return docVal >= l && docVal < u;
+ }
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper3 : ValueSourceScorer
+ {
+ private readonly FunctionValues outerInstance;
+
+ private float l;
+ private float u;
+
+ public ValueSourceScorerAnonymousInnerClassHelper3(FunctionValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.FunctionValues this, float l, float u) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.l = l;
+ this.u = u;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ float docVal = outerInstance.floatVal(doc);
+ return docVal > l && docVal <= u;
+ }
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper4 : ValueSourceScorer
+ {
+ private readonly FunctionValues outerInstance;
+
+ private float l;
+ private float u;
+
+ public ValueSourceScorerAnonymousInnerClassHelper4(FunctionValues outerInstance, IndexReader reader, org.apache.lucene.queries.function.FunctionValues this, float l, float u) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.l = l;
+ this.u = u;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ float docVal = outerInstance.floatVal(doc);
+ return docVal > l && docVal < u;
+ }
+ }
+ }
+
+
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource.cs
new file mode 100644
index 0000000..bb131af
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource.cs
@@ -0,0 +1,223 @@
+using System.Collections;
+
+namespace org.apache.lucene.queries.function
+{
+
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FieldComparator = org.apache.lucene.search.FieldComparator;
+ using FieldComparatorSource = org.apache.lucene.search.FieldComparatorSource;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using SortField = org.apache.lucene.search.SortField;
+
+
+ /// <summary>
+ /// Instantiates <seealso cref="FunctionValues"/> for a particular reader.
+ /// <br>
+ /// Often used when creating a <seealso cref="FunctionQuery"/>.
+ ///
+ ///
+ /// </summary>
+ public abstract class ValueSource
+ {
+
+ /// <summary>
+ /// Gets the values for this reader and the context that was previously
+ /// passed to createWeight()
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public abstract FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException;
+ public abstract FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext);
+
+ public override abstract bool Equals(object o);
+
+ public override abstract int GetHashCode();
+
+ /// <summary>
+ /// description of field, used in explain()
+ /// </summary>
+ public abstract string description();
+
+ public override string ToString()
+ {
+ return description();
+ }
+
+
+ /// <summary>
+ /// Implementations should propagate createWeight to sub-ValueSources which can optionally store
+ /// weight info in the context. The context object will be passed to getValues()
+ /// where this info can be retrieved.
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public virtual void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ }
+
+ /// <summary>
+ /// Returns a new non-threadsafe context map.
+ /// </summary>
+ public static IDictionary newContext(IndexSearcher searcher)
+ {
+ IDictionary context = new IdentityHashMap();
+ context["searcher"] = searcher;
+ return context;
+ }
+
+
+ //
+ // Sorting by function
+ //
+
+ /// <summary>
+ /// EXPERIMENTAL: This method is subject to change.
+ /// <para>
+ /// Get the SortField for this ValueSource. Uses the <seealso cref="#getValues(java.util.Map, AtomicReaderContext)"/>
+ /// to populate the SortField.
+ ///
+ /// </para>
+ /// </summary>
+ /// <param name="reverse"> true if this is a reverse sort. </param>
+ /// <returns> The <seealso cref="org.apache.lucene.search.SortField"/> for the ValueSource </returns>
+ public virtual SortField getSortField(bool reverse)
+ {
+ return new ValueSourceSortField(this, reverse);
+ }
+
+ internal class ValueSourceSortField : SortField
+ {
+ private readonly ValueSource outerInstance;
+
+ public ValueSourceSortField(ValueSource outerInstance, bool reverse) : base(outerInstance.description(), SortField.Type.REWRITEABLE, reverse)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.SortField rewrite(org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override SortField rewrite(IndexSearcher searcher)
+ {
+ IDictionary context = newContext(searcher);
+ outerInstance.createWeight(context, searcher);
+ return new SortField(Field, new ValueSourceComparatorSource(outerInstance, context), Reverse);
+ }
+ }
+
+ internal class ValueSourceComparatorSource : FieldComparatorSource
+ {
+ private readonly ValueSource outerInstance;
+
+ internal readonly IDictionary context;
+
+ public ValueSourceComparatorSource(ValueSource outerInstance, IDictionary context)
+ {
+ this.outerInstance = outerInstance;
+ this.context = context;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.FieldComparator<Double> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws java.io.IOException
+ public override FieldComparator<double?> newComparator(string fieldname, int numHits, int sortPos, bool reversed)
+ {
+ return new ValueSourceComparator(outerInstance, context, numHits);
+ }
+ }
+
+ /// <summary>
+ /// Implement a <seealso cref="org.apache.lucene.search.FieldComparator"/> that works
+ /// off of the <seealso cref="FunctionValues"/> for a ValueSource
+ /// instead of the normal Lucene FieldComparator that works off of a FieldCache.
+ /// </summary>
+ internal class ValueSourceComparator : FieldComparator<double?>
+ {
+ private readonly ValueSource outerInstance;
+
+ internal readonly double[] values;
+ internal FunctionValues docVals;
+ internal double bottom;
+ internal readonly IDictionary fcontext;
+ internal double topValue;
+
+ internal ValueSourceComparator(ValueSource outerInstance, IDictionary fcontext, int numHits)
+ {
+ this.outerInstance = outerInstance;
+ this.fcontext = fcontext;
+ values = new double[numHits];
+ }
+
+ public override int compare(int slot1, int slot2)
+ {
+ return values[slot1].CompareTo(values[slot2]);
+ }
+
+ public override int compareBottom(int doc)
+ {
+ return bottom.CompareTo(docVals.doubleVal(doc));
+ }
+
+ public override void copy(int slot, int doc)
+ {
+ values[slot] = docVals.doubleVal(doc);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.FieldComparator setNextReader(org.apache.lucene.index.AtomicReaderContext context) throws java.io.IOException
+ public override FieldComparator setNextReader(AtomicReaderContext context)
+ {
+ docVals = outerInstance.getValues(fcontext, context);
+ return this;
+ }
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: @Override public void setBottom(final int bottom)
+ public override int Bottom
+ {
+ set
+ {
+ this.bottom = values[value];
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: @Override public void setTopValue(final Double value)
+ public override double? TopValue
+ {
+ set
+ {
+ this.topValue = (double)value;
+ }
+ }
+
+ public override double? value(int slot)
+ {
+ return values[slot];
+ }
+
+ public override int compareTop(int doc)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final double docValue = docVals.doubleVal(doc);
+ double docValue = docVals.doubleVal(doc);
+ return topValue.CompareTo(docValue);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/BoolFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/BoolFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/BoolFunction.cs
new file mode 100644
index 0000000..85399df
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/BoolFunction.cs
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ /// <summary>
+ /// Abstract parent class for those <seealso cref="ValueSource"/> implementations which
+ /// apply boolean logic to their values
+ /// </summary>
+ public abstract class BoolFunction : ValueSource
+ {
+ // TODO: placeholder to return type, among other common future functionality
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/ByteFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/ByteFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/ByteFieldSource.cs
new file mode 100644
index 0000000..0e2ffc6
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/ByteFieldSource.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+
+ /// <summary>
+ /// Obtains int field values from the <seealso cref="org.apache.lucene.search.FieldCache"/>
+ /// using <code>getInts()</code>
+ /// and makes those values available as other numeric types, casting as needed. *
+ ///
+ ///
+ /// </summary>
+ [Obsolete]
+ public class ByteFieldSource : FieldCacheSource
+ {
+
+ private readonly FieldCache.ByteParser parser;
+
+ public ByteFieldSource(string field) : this(field, null)
+ {
+ }
+
+ public ByteFieldSource(string field, FieldCache.ByteParser parser) : base(field)
+ {
+ this.parser = parser;
+ }
+
+ public override string description()
+ {
+ return "byte(" + field + ')';
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldCache.Bytes arr = cache.getBytes(readerContext.reader(), field, parser, false);
+ FieldCache.Bytes arr = cache.getBytes(readerContext.reader(), field, parser, false);
+
+ return new FunctionValuesAnonymousInnerClassHelper(this, arr);
+ }
+
+ private class FunctionValuesAnonymousInnerClassHelper : FunctionValues
+ {
+ private readonly ByteFieldSource outerInstance;
+
+ private FieldCache.Bytes arr;
+
+ public FunctionValuesAnonymousInnerClassHelper(ByteFieldSource outerInstance, FieldCache.Bytes arr)
+ {
+ this.outerInstance = outerInstance;
+ this.arr = arr;
+ }
+
+ public override sbyte byteVal(int doc)
+ {
+ return arr.get(doc);
+ }
+
+ public override short shortVal(int doc)
+ {
+ return (short) arr.get(doc);
+ }
+
+ public override float floatVal(int doc)
+ {
+ return (float) arr.get(doc);
+ }
+
+ public override int intVal(int doc)
+ {
+ return (int) arr.get(doc);
+ }
+
+ public override long longVal(int doc)
+ {
+ return (long) arr.get(doc);
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return (double) arr.get(doc);
+ }
+
+ public override string strVal(int doc)
+ {
+ return Convert.ToString(arr.get(doc));
+ }
+
+ public override string ToString(int doc)
+ {
+ return outerInstance.description() + '=' + byteVal(doc);
+ }
+
+ public override object objectVal(int doc)
+ {
+ return arr.get(doc); // TODO: valid?
+ }
+
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o.GetType() != typeof(ByteFieldSource))
+ {
+ return false;
+ }
+ ByteFieldSource other = (ByteFieldSource) o;
+ return base.Equals(other) && (this.parser == null ? other.parser == null : this.parser.GetType() == other.parser.GetType());
+ }
+
+ public override int GetHashCode()
+ {
+ int h = parser == null ? typeof(sbyte?).GetHashCode() : parser.GetType().GetHashCode();
+ h += base.GetHashCode();
+ return h;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/BytesRefFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/BytesRefFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/BytesRefFieldSource.cs
new file mode 100644
index 0000000..f091aee
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/BytesRefFieldSource.cs
@@ -0,0 +1,140 @@
+using System.Collections;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using BinaryDocValues = org.apache.lucene.index.BinaryDocValues;
+ using FieldInfo = org.apache.lucene.index.FieldInfo;
+ using DocValuesType = org.apache.lucene.index.FieldInfo.DocValuesType;
+ using DocTermsIndexDocValues = org.apache.lucene.queries.function.docvalues.DocTermsIndexDocValues;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+ using Bits = org.apache.lucene.util.Bits;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+ /// <summary>
+ /// An implementation for retrieving <seealso cref="FunctionValues"/> instances for string based fields.
+ /// </summary>
+ public class BytesRefFieldSource : FieldCacheSource
+ {
+
+ public BytesRefFieldSource(string field) : base(field)
+ {
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.FieldInfo fieldInfo = readerContext.reader().getFieldInfos().fieldInfo(field);
+ FieldInfo fieldInfo = readerContext.reader().FieldInfos.fieldInfo(field);
+ // To be sorted or not to be sorted, that is the question
+ // TODO: do it cleaner?
+ if (fieldInfo != null && fieldInfo.DocValuesType == FieldInfo.DocValuesType.BINARY)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.BinaryDocValues binaryValues = org.apache.lucene.search.FieldCache.DEFAULT.getTerms(readerContext.reader(), field, true);
+ BinaryDocValues binaryValues = FieldCache.DEFAULT.getTerms(readerContext.reader(), field, true);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.Bits docsWithField = org.apache.lucene.search.FieldCache.DEFAULT.getDocsWithField(readerContext.reader(), field);
+ Bits docsWithField = FieldCache.DEFAULT.getDocsWithField(readerContext.reader(), field);
+ return new FunctionValuesAnonymousInnerClassHelper(this, binaryValues, docsWithField);
+ }
+ else
+ {
+ return new DocTermsIndexDocValuesAnonymousInnerClassHelper(this, this, readerContext, field);
+ }
+ }
+
+ private class FunctionValuesAnonymousInnerClassHelper : FunctionValues
+ {
+ private readonly BytesRefFieldSource outerInstance;
+
+ private BinaryDocValues binaryValues;
+ private Bits docsWithField;
+
+ public FunctionValuesAnonymousInnerClassHelper(BytesRefFieldSource outerInstance, BinaryDocValues binaryValues, Bits docsWithField)
+ {
+ this.outerInstance = outerInstance;
+ this.binaryValues = binaryValues;
+ this.docsWithField = docsWithField;
+ }
+
+
+ public override bool exists(int doc)
+ {
+ return docsWithField.get(doc);
+ }
+
+ public override bool bytesVal(int doc, BytesRef target)
+ {
+ binaryValues.get(doc, target);
+ return target.length > 0;
+ }
+
+ public override string strVal(int doc)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.BytesRef bytes = new org.apache.lucene.util.BytesRef();
+ BytesRef bytes = new BytesRef();
+ return bytesVal(doc, bytes) ? bytes.utf8ToString() : null;
+ }
+
+ public override object objectVal(int doc)
+ {
+ return strVal(doc);
+ }
+
+ public override string ToString(int doc)
+ {
+ return outerInstance.description() + '=' + strVal(doc);
+ }
+ }
+
+ private class DocTermsIndexDocValuesAnonymousInnerClassHelper : DocTermsIndexDocValues
+ {
+ private readonly BytesRefFieldSource outerInstance;
+
+ public DocTermsIndexDocValuesAnonymousInnerClassHelper(BytesRefFieldSource outerInstance, org.apache.lucene.queries.function.valuesource.BytesRefFieldSource this, AtomicReaderContext readerContext, string field) : base(this, readerContext, field)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+
+ protected internal override string toTerm(string readableValue)
+ {
+ return readableValue;
+ }
+
+ public override object objectVal(int doc)
+ {
+ return strVal(doc);
+ }
+
+ public override string ToString(int doc)
+ {
+ return outerInstance.description() + '=' + strVal(doc);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/ConstNumberSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/ConstNumberSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/ConstNumberSource.cs
new file mode 100644
index 0000000..33a0aa0
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/ConstNumberSource.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ /// <summary>
+ /// <code>ConstNumberSource</code> is the base class for all constant numbers
+ /// </summary>
+ public abstract class ConstNumberSource : ValueSource
+ {
+ public abstract int Int {get;}
+ public abstract long Long {get;}
+ public abstract float Float {get;}
+ public abstract double Double {get;}
+ public abstract Number Number {get;}
+ public abstract bool Bool {get;}
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/ConstValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/ConstValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/ConstValueSource.cs
new file mode 100644
index 0000000..9933f13
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/ConstValueSource.cs
@@ -0,0 +1,156 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+
+
+ /// <summary>
+ /// <code>ConstValueSource</code> returns a constant for all documents
+ /// </summary>
+ public class ConstValueSource : ConstNumberSource
+ {
+ internal readonly float constant;
+ private readonly double dv;
+
+ public ConstValueSource(float constant)
+ {
+ this.constant = constant;
+ this.dv = constant;
+ }
+
+ public override string description()
+ {
+ return "const(" + constant + ")";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly ConstValueSource outerInstance;
+
+ public FloatDocValuesAnonymousInnerClassHelper(ConstValueSource outerInstance, org.apache.lucene.queries.function.valuesource.ConstValueSource this) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return outerInstance.constant;
+ }
+ public override int intVal(int doc)
+ {
+ return (int)outerInstance.constant;
+ }
+ public override long longVal(int doc)
+ {
+ return (long)outerInstance.constant;
+ }
+ public override double doubleVal(int doc)
+ {
+ return outerInstance.dv;
+ }
+ public override string ToString(int doc)
+ {
+ return outerInstance.description();
+ }
+ public override object objectVal(int doc)
+ {
+ return outerInstance.constant;
+ }
+ public override bool boolVal(int doc)
+ {
+ return outerInstance.constant != 0.0f;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return float.floatToIntBits(constant) * 31;
+ }
+
+ public override bool Equals(object o)
+ {
+ if (!(o is ConstValueSource))
+ {
+ return false;
+ }
+ ConstValueSource other = (ConstValueSource)o;
+ return this.constant == other.constant;
+ }
+
+ public override int Int
+ {
+ get
+ {
+ return (int)constant;
+ }
+ }
+
+ public override long Long
+ {
+ get
+ {
+ return (long)constant;
+ }
+ }
+
+ public override float Float
+ {
+ get
+ {
+ return constant;
+ }
+ }
+
+ public override double Double
+ {
+ get
+ {
+ return dv;
+ }
+ }
+
+ public override Number Number
+ {
+ get
+ {
+ return constant;
+ }
+ }
+
+ public override bool Bool
+ {
+ get
+ {
+ return constant != 0.0f;
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/DefFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/DefFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/DefFunction.cs
new file mode 100644
index 0000000..48a67d4
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/DefFunction.cs
@@ -0,0 +1,153 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+ /// <summary>
+ /// <seealso cref="ValueSource"/> implementation which only returns the values from the provided
+ /// ValueSources which are available for a particular docId. Consequently, when combined
+ /// with a <seealso cref="ConstValueSource"/>, this function serves as a way to return a default
+ /// value when the values for a field are unavailable.
+ /// </summary>
+ public class DefFunction : MultiFunction
+ {
+ public DefFunction(IList<ValueSource> sources) : base(sources)
+ {
+ }
+
+ protected internal override string name()
+ {
+ return "def";
+ }
+
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map fcontext, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary fcontext, AtomicReaderContext readerContext)
+ {
+
+
+ return new ValuesAnonymousInnerClassHelper(this, valsArr(sources, fcontext, readerContext));
+ }
+
+ private class ValuesAnonymousInnerClassHelper : Values
+ {
+ private readonly DefFunction outerInstance;
+
+ public ValuesAnonymousInnerClassHelper(DefFunction outerInstance, FunctionValues[] valsArr) : base(outerInstance, valsArr)
+ {
+ this.outerInstance = outerInstance;
+ upto = valsArr.Length - 1;
+ }
+
+ internal readonly int upto;
+
+ private FunctionValues get(int doc)
+ {
+ for (int i = 0; i < upto; i++)
+ {
+ FunctionValues vals = valsArr[i];
+ if (vals.exists(doc))
+ {
+ return vals;
+ }
+ }
+ return valsArr[upto];
+ }
+
+ public override sbyte byteVal(int doc)
+ {
+ return get(doc).byteVal(doc);
+ }
+
+ public override short shortVal(int doc)
+ {
+ return get(doc).shortVal(doc);
+ }
+
+ public override float floatVal(int doc)
+ {
+ return get(doc).floatVal(doc);
+ }
+
+ public override int intVal(int doc)
+ {
+ return get(doc).intVal(doc);
+ }
+
+ public override long longVal(int doc)
+ {
+ return get(doc).longVal(doc);
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return get(doc).doubleVal(doc);
+ }
+
+ public override string strVal(int doc)
+ {
+ return get(doc).strVal(doc);
+ }
+
+ public override bool boolVal(int doc)
+ {
+ return get(doc).boolVal(doc);
+ }
+
+ public override bool bytesVal(int doc, BytesRef target)
+ {
+ return get(doc).bytesVal(doc, target);
+ }
+
+ public override object objectVal(int doc)
+ {
+ return get(doc).objectVal(doc);
+ }
+
+ public override bool exists(int doc)
+ {
+ // return true if any source is exists?
+ foreach (FunctionValues vals in valsArr)
+ {
+ if (vals.exists(doc))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ // TODO: need ValueSource.type() to determine correct type
+ return base.ValueFiller;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
[11/11] git commit: Skeleton port of Lucene.Net.Memory
Posted by sy...@apache.org.
Skeleton port of Lucene.Net.Memory
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/531b4af0
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/531b4af0
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/531b4af0
Branch: refs/heads/master
Commit: 531b4af02d67e3025b8092d1c88e99f47af051d1
Parents: 674f0cb
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Tue Sep 16 01:44:12 2014 +0300
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Tue Sep 16 01:44:12 2014 +0300
----------------------------------------------------------------------
src/Lucene.Net.Memory/HashMapHelperClass.cs | 26 +
src/Lucene.Net.Memory/Lucene.Net.Memory.csproj | 61 +
src/Lucene.Net.Memory/MemoryIndex.cs | 1606 ++++++++++++++++++
.../MemoryIndexNormDocValues.cs | 47 +
.../Properties/AssemblyInfo.cs | 35 +
5 files changed, 1775 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/531b4af0/src/Lucene.Net.Memory/HashMapHelperClass.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Memory/HashMapHelperClass.cs b/src/Lucene.Net.Memory/HashMapHelperClass.cs
new file mode 100644
index 0000000..395d53e
--- /dev/null
+++ b/src/Lucene.Net.Memory/HashMapHelperClass.cs
@@ -0,0 +1,26 @@
+//---------------------------------------------------------------------------------------------------------
+// Copyright © 2007 - 2014 Tangible Software Solutions Inc.
+// This class can be used by anyone provided that the copyright notice remains intact.
+//
+// This class is used to replace calls to some Java HashMap or Hashtable methods.
+//---------------------------------------------------------------------------------------------------------
+using System.Collections.Generic;
+internal static class HashMapHelperClass
+{
+ internal static HashSet<KeyValuePair<TKey, TValue>> SetOfKeyValuePairs<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
+ {
+ var entries = new HashSet<KeyValuePair<TKey, TValue>>();
+ foreach (KeyValuePair<TKey, TValue> keyValuePair in dictionary)
+ {
+ entries.Add(keyValuePair);
+ }
+ return entries;
+ }
+
+ internal static TValue GetValueOrNull<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
+ {
+ TValue ret;
+ dictionary.TryGetValue(key, out ret);
+ return ret;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/531b4af0/src/Lucene.Net.Memory/Lucene.Net.Memory.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Memory/Lucene.Net.Memory.csproj b/src/Lucene.Net.Memory/Lucene.Net.Memory.csproj
new file mode 100644
index 0000000..3ba5780
--- /dev/null
+++ b/src/Lucene.Net.Memory/Lucene.Net.Memory.csproj
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{42ECF239-AFC1-427D-921E-B5A277809CF0}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Lucene.Net.Memory</RootNamespace>
+ <AssemblyName>Lucene.Net.Memory</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="HashMapHelperClass.cs" />
+ <Compile Include="MemoryIndex.cs" />
+ <Compile Include="MemoryIndexNormDocValues.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Lucene.Net.Core\Lucene.Net.csproj">
+ <Project>{5d4ad9be-1ffb-41ab-9943-25737971bf57}</Project>
+ <Name>Lucene.Net</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/531b4af0/src/Lucene.Net.Memory/MemoryIndex.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Memory/MemoryIndex.cs b/src/Lucene.Net.Memory/MemoryIndex.cs
new file mode 100644
index 0000000..8e339ca
--- /dev/null
+++ b/src/Lucene.Net.Memory/MemoryIndex.cs
@@ -0,0 +1,1606 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Search.Similarities;
+using Lucene.Net.Store;
+using Lucene.Net.Util;
+
+namespace Lucene.Net.Memory
+{
+
+ /*
+ * 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.
+ */
+
+ /// <summary>
+ /// High-performance single-document main memory Apache Lucene fulltext search index.
+ ///
+ /// <h4>Overview</h4>
+ ///
+ /// This class is a replacement/substitute for a large subset of
+ /// <seealso cref="RAMDirectory"/> functionality. It is designed to
+ /// enable maximum efficiency for on-the-fly matchmaking combining structured and
+ /// fuzzy fulltext search in realtime streaming applications such as Nux XQuery based XML
+ /// message queues, publish-subscribe systems for Blogs/newsfeeds, text chat, data acquisition and
+ /// distribution systems, application level routers, firewalls, classifiers, etc.
+ /// Rather than targeting fulltext search of infrequent queries over huge persistent
+ /// data archives (historic search), this class targets fulltext search of huge
+ /// numbers of queries over comparatively small transient realtime data (prospective
+ /// search).
+ /// For example as in
+ /// <pre class="prettyprint">
+ /// float score = search(String text, Query query)
+ /// </pre>
+ /// <para>
+ /// Each instance can hold at most one Lucene "document", with a document containing
+ /// zero or more "fields", each field having a name and a fulltext value. The
+ /// fulltext value is tokenized (split and transformed) into zero or more index terms
+ /// (aka words) on <code>addField()</code>, according to the policy implemented by an
+ /// Analyzer. For example, Lucene analyzers can split on whitespace, normalize to lower case
+ /// for case insensitivity, ignore common terms with little discriminatory value such as "he", "in", "and" (stop
+ /// words), reduce the terms to their natural linguistic root form such as "fishing"
+ /// being reduced to "fish" (stemming), resolve synonyms/inflexions/thesauri
+ /// (upon indexing and/or querying), etc. For details, see
+ /// <a target="_blank" href="http://today.java.net/pub/a/today/2003/07/30/LuceneIntro.html">Lucene Analyzer Intro</a>.
+ /// </para>
+ /// <para>
+ /// Arbitrary Lucene queries can be run against this class - see <a target="_blank"
+ /// href="{@docRoot}/../queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description">
+ /// Lucene Query Syntax</a>
+ /// as well as <a target="_blank"
+ /// href="http://today.java.net/pub/a/today/2003/11/07/QueryParserRules.html">Query Parser Rules</a>.
+ /// Note that a Lucene query selects on the field names and associated (indexed)
+ /// tokenized terms, not on the original fulltext(s) - the latter are not stored
+ /// but rather thrown away immediately after tokenization.
+ /// </para>
+ /// <para>
+ /// For some interesting background information on search technology, see Bob Wyman's
+ /// <a target="_blank"
+ /// href="http://bobwyman.pubsub.com/main/2005/05/mary_hodder_poi.html">Prospective Search</a>,
+ /// Jim Gray's
+ /// <a target="_blank" href="http://www.acmqueue.org/modules.php?name=Content&pa=showpage&pid=293&page=4">
+ /// A Call to Arms - Custom subscriptions</a>, and Tim Bray's
+ /// <a target="_blank"
+ /// href="http://www.tbray.org/ongoing/When/200x/2003/07/30/OnSearchTOC">On Search, the Series</a>.
+ ///
+ ///
+ /// <h4>Example Usage</h4>
+ ///
+ /// <pre class="prettyprint">
+ /// Analyzer analyzer = new SimpleAnalyzer(version);
+ /// MemoryIndex index = new MemoryIndex();
+ /// index.addField("content", "Readings about Salmons and other select Alaska fishing Manuals", analyzer);
+ /// index.addField("author", "Tales of James", analyzer);
+ /// QueryParser parser = new QueryParser(version, "content", analyzer);
+ /// float score = index.search(parser.parse("+author:james +salmon~ +fish* manual~"));
+ /// if (score > 0.0f) {
+ /// System.out.println("it's a match");
+ /// } else {
+ /// System.out.println("no match found");
+ /// }
+ /// System.out.println("indexData=" + index.toString());
+ /// </pre>
+ ///
+ ///
+ /// <h4>Example XQuery Usage</h4>
+ ///
+ /// <pre class="prettyprint">
+ /// (: An XQuery that finds all books authored by James that have something to do with "salmon fishing manuals", sorted by relevance :)
+ /// declare namespace lucene = "java:nux.xom.pool.FullTextUtil";
+ /// declare variable $query := "+salmon~ +fish* manual~"; (: any arbitrary Lucene query can go here :)
+ ///
+ /// for $book in /books/book[author="James" and lucene:match(abstract, $query) > 0.0]
+ /// let $score := lucene:match($book/abstract, $query)
+ /// order by $score descending
+ /// return $book
+ /// </pre>
+ ///
+ ///
+ /// <h4>No thread safety guarantees</h4>
+ ///
+ /// An instance can be queried multiple times with the same or different queries,
+ /// but an instance is not thread-safe. If desired use idioms such as:
+ /// <pre class="prettyprint">
+ /// MemoryIndex index = ...
+ /// synchronized (index) {
+ /// // read and/or write index (i.e. add fields and/or query)
+ /// }
+ /// </pre>
+ ///
+ ///
+ /// <h4>Performance Notes</h4>
+ ///
+ /// Internally there's a new data structure geared towards efficient indexing
+ /// and searching, plus the necessary support code to seamlessly plug into the Lucene
+ /// framework.
+ /// </para>
+ /// <para>
+ /// This class performs very well for very small texts (e.g. 10 chars)
+ /// as well as for large texts (e.g. 10 MB) and everything in between.
+ /// Typically, it is about 10-100 times faster than <code>RAMDirectory</code>.
+ /// Note that <code>RAMDirectory</code> has particularly
+ /// large efficiency overheads for small to medium sized texts, both in time and space.
+ /// Indexing a field with N tokens takes O(N) in the best case, and O(N logN) in the worst
+ /// case. Memory consumption is probably larger than for <code>RAMDirectory</code>.
+ /// </para>
+ /// <para>
+ /// Example throughput of many simple term queries over a single MemoryIndex:
+ /// ~500000 queries/sec on a MacBook Pro, jdk 1.5.0_06, server VM.
+ /// As always, your mileage may vary.
+ /// </para>
+ /// <para>
+ /// If you're curious about
+ /// the whereabouts of bottlenecks, run java 1.5 with the non-perturbing '-server
+ /// -agentlib:hprof=cpu=samples,depth=10' flags, then study the trace log and
+ /// correlate its hotspot trailer with its call stack headers (see <a
+ /// target="_blank"
+ /// href="http://java.sun.com/developer/technicalArticles/Programming/HPROF.html">
+ /// hprof tracing </a>).
+ ///
+ /// </para>
+ /// </summary>
+ public class MemoryIndex
+ {
+
+ /// <summary>
+ /// info for each field: Map<String fieldName, Info field> </summary>
+ private readonly Dictionary<string, Info> fields = new Dictionary<string, Info>();
+
+ /// <summary>
+ /// fields sorted ascending by fieldName; lazily computed on demand </summary>
+ [NonSerialized]
+ private KeyValuePair<string, Info>[] sortedFields;
+
+ private readonly bool storeOffsets;
+
+ private const bool DEBUG = false;
+
+ private readonly ByteBlockPool byteBlockPool;
+ private readonly IntBlockPool intBlockPool;
+ // private final IntBlockPool.SliceReader postingsReader;
+ private readonly IntBlockPool.SliceWriter postingsWriter;
+
+ private Dictionary<string, FieldInfo> fieldInfos = new Dictionary<string, FieldInfo>();
+
+ private Counter bytesUsed;
+
+ /// <summary>
+ /// Sorts term entries into ascending order; also works for
+ /// Arrays.binarySearch() and Arrays.sort()
+ /// </summary>
+ private static readonly IComparer<object> termComparator = new ComparatorAnonymousInnerClassHelper();
+
+ private class ComparatorAnonymousInnerClassHelper : IComparer<object>
+ {
+ public ComparatorAnonymousInnerClassHelper()
+ {
+ }
+
+//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
+//ORIGINAL LINE: @Override @SuppressWarnings({"unchecked","rawtypes"}) public int compare(Object o1, Object o2)
+ public virtual int Compare(object o1, object o2)
+ {
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: if (o1 instanceof java.util.Map.Entry<?,?>)
+ if (o1 is KeyValuePair<?, ?>)
+ {
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: o1 = ((java.util.Map.Entry<?,?>) o1).getKey();
+ o1 = ((KeyValuePair<?, ?>) o1).Key;
+ }
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: if (o2 instanceof java.util.Map.Entry<?,?>)
+ if (o2 is KeyValuePair<?, ?>)
+ {
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: o2 = ((java.util.Map.Entry<?,?>) o2).getKey();
+ o2 = ((KeyValuePair<?, ?>) o2).Key;
+ }
+ if (o1 == o2)
+ {
+ return 0;
+ }
+ return ((IComparable) o1).CompareTo((IComparable) o2);
+ }
+ }
+
+ /// <summary>
+ /// Constructs an empty instance.
+ /// </summary>
+ public MemoryIndex() : this(false)
+ {
+ }
+
+ /// <summary>
+ /// Constructs an empty instance that can optionally store the start and end
+ /// character offset of each token term in the text. This can be useful for
+ /// highlighting of hit locations with the Lucene highlighter package.
+ /// Protected until the highlighter package matures, so that this can actually
+ /// be meaningfully integrated.
+ /// </summary>
+ /// <param name="storeOffsets">
+ /// whether or not to store the start and end character offset of
+ /// each token term in the text </param>
+ public MemoryIndex(bool storeOffsets) : this(storeOffsets, 0)
+ {
+
+ }
+
+ /// <summary>
+ /// Expert: This constructor accepts an upper limit for the number of bytes that should be reused if this instance is <seealso cref="#reset()"/>. </summary>
+ /// <param name="storeOffsets"> <code>true</code> if offsets should be stored </param>
+ /// <param name="maxReusedBytes"> the number of bytes that should remain in the internal memory pools after <seealso cref="#reset()"/> is called </param>
+ internal MemoryIndex(bool storeOffsets, long maxReusedBytes)
+ {
+ this.storeOffsets = storeOffsets;
+ this.bytesUsed = Counter.newCounter();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int maxBufferedByteBlocks = (int)((maxReusedBytes/2) / org.apache.lucene.util.ByteBlockPool.BYTE_BLOCK_SIZE);
+ int maxBufferedByteBlocks = (int)((maxReusedBytes / 2) / ByteBlockPool.BYTE_BLOCK_SIZE);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int maxBufferedIntBlocks = (int)((maxReusedBytes - (maxBufferedByteBlocks*org.apache.lucene.util.ByteBlockPool.BYTE_BLOCK_SIZE))/(org.apache.lucene.util.IntBlockPool.INT_BLOCK_SIZE * org.apache.lucene.util.RamUsageEstimator.NUM_BYTES_INT));
+ int maxBufferedIntBlocks = (int)((maxReusedBytes - (maxBufferedByteBlocks * ByteBlockPool.BYTE_BLOCK_SIZE)) / (IntBlockPool.INT_BLOCK_SIZE * RamUsageEstimator.NUM_BYTES_INT));
+ assert(maxBufferedByteBlocks * ByteBlockPool.BYTE_BLOCK_SIZE) + (maxBufferedIntBlocks * IntBlockPool.INT_BLOCK_SIZE * RamUsageEstimator.NUM_BYTES_INT) <= maxReusedBytes;
+ byteBlockPool = new ByteBlockPool(new RecyclingByteBlockAllocator(ByteBlockPool.BYTE_BLOCK_SIZE, maxBufferedByteBlocks, bytesUsed));
+ intBlockPool = new IntBlockPool(new RecyclingIntBlockAllocator(IntBlockPool.INT_BLOCK_SIZE, maxBufferedIntBlocks, bytesUsed));
+ postingsWriter = new SliceWriter(intBlockPool);
+ }
+
+ /// <summary>
+ /// Convenience method; Tokenizes the given field text and adds the resulting
+ /// terms to the index; Equivalent to adding an indexed non-keyword Lucene
+ /// <seealso cref="org.apache.lucene.document.Field"/> that is tokenized, not stored,
+ /// termVectorStored with positions (or termVectorStored with positions and offsets),
+ /// </summary>
+ /// <param name="fieldName">
+ /// a name to be associated with the text </param>
+ /// <param name="text">
+ /// the text to tokenize and index. </param>
+ /// <param name="analyzer">
+ /// the analyzer to use for tokenization </param>
+ public virtual void addField(string fieldName, string text, Analyzer analyzer)
+ {
+ if (fieldName == null)
+ {
+ throw new System.ArgumentException("fieldName must not be null");
+ }
+ if (text == null)
+ {
+ throw new System.ArgumentException("text must not be null");
+ }
+ if (analyzer == null)
+ {
+ throw new System.ArgumentException("analyzer must not be null");
+ }
+
+ TokenStream stream;
+ try
+ {
+ stream = analyzer.TokenStream(fieldName, text);
+ }
+ catch (IOException ex)
+ {
+ throw new Exception(ex);
+ }
+
+ addField(fieldName, stream, 1.0f, analyzer.GetPositionIncrementGap(fieldName), analyzer.GetOffsetGap(fieldName));
+ }
+
+ /// <summary>
+ /// Convenience method; Creates and returns a token stream that generates a
+ /// token for each keyword in the given collection, "as is", without any
+ /// transforming text analysis. The resulting token stream can be fed into
+ /// <seealso cref="#addField(String, TokenStream)"/>, perhaps wrapped into another
+ /// <seealso cref="org.apache.lucene.analysis.TokenFilter"/>, as desired.
+ /// </summary>
+ /// <param name="keywords">
+ /// the keywords to generate tokens for </param>
+ /// <returns> the corresponding token stream </returns>
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public <T> org.apache.lucene.analysis.TokenStream keywordTokenStream(final java.util.Collection<T> keywords)
+ public virtual TokenStream keywordTokenStream<T>(ICollection<T> keywords)
+ {
+ // TODO: deprecate & move this method into AnalyzerUtil?
+ if (keywords == null)
+ {
+ throw new System.ArgumentException("keywords must not be null");
+ }
+
+ return new TokenStreamAnonymousInnerClassHelper(this, keywords);
+ }
+
+ private class TokenStreamAnonymousInnerClassHelper : TokenStream
+ {
+ private readonly MemoryIndex outerInstance;
+
+ private ICollection<T> keywords;
+
+ public TokenStreamAnonymousInnerClassHelper(MemoryIndex outerInstance, ICollection<T> keywords)
+ {
+ this.outerInstance = outerInstance;
+ this.keywords = keywords;
+ iter = keywords.GetEnumerator();
+ start = 0;
+ termAtt = addAttribute(typeof(CharTermAttribute));
+ offsetAtt = addAttribute(typeof(OffsetAttribute));
+ }
+
+ private IEnumerator<T> iter;
+ private int start;
+ private readonly CharTermAttribute termAtt;
+ private readonly OffsetAttribute offsetAtt;
+
+ public override bool incrementToken()
+ {
+ if (!iter.hasNext())
+ {
+ return false;
+ }
+
+ T obj = iter.next();
+ if (obj == null)
+ {
+ throw new System.ArgumentException("keyword must not be null");
+ }
+
+ string term = obj.ToString();
+ clearAttributes();
+ termAtt.setEmpty().append(term);
+ offsetAtt.setOffset(start, start + termAtt.length());
+ start += term.Length + 1; // separate words by 1 (blank) character
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Equivalent to <code>addField(fieldName, stream, 1.0f)</code>.
+ /// </summary>
+ /// <param name="fieldName">
+ /// a name to be associated with the text </param>
+ /// <param name="stream">
+ /// the token stream to retrieve tokens from </param>
+ public virtual void addField(string fieldName, TokenStream stream)
+ {
+ addField(fieldName, stream, 1.0f);
+ }
+
+ /// <summary>
+ /// Iterates over the given token stream and adds the resulting terms to the index;
+ /// Equivalent to adding a tokenized, indexed, termVectorStored, unstored,
+ /// Lucene <seealso cref="org.apache.lucene.document.Field"/>.
+ /// Finally closes the token stream. Note that untokenized keywords can be added with this method via
+ /// <seealso cref="#keywordTokenStream(Collection)"/>, the Lucene <code>KeywordTokenizer</code> or similar utilities.
+ /// </summary>
+ /// <param name="fieldName">
+ /// a name to be associated with the text </param>
+ /// <param name="stream">
+ /// the token stream to retrieve tokens from. </param>
+ /// <param name="boost">
+ /// the boost factor for hits for this field
+ /// </param>
+ /// <seealso cref= org.apache.lucene.document.Field#setBoost(float) </seealso>
+ public virtual void addField(string fieldName, TokenStream stream, float boost)
+ {
+ addField(fieldName, stream, boost, 0);
+ }
+
+
+ /// <summary>
+ /// Iterates over the given token stream and adds the resulting terms to the index;
+ /// Equivalent to adding a tokenized, indexed, termVectorStored, unstored,
+ /// Lucene <seealso cref="org.apache.lucene.document.Field"/>.
+ /// Finally closes the token stream. Note that untokenized keywords can be added with this method via
+ /// <seealso cref="#keywordTokenStream(Collection)"/>, the Lucene <code>KeywordTokenizer</code> or similar utilities.
+ /// </summary>
+ /// <param name="fieldName">
+ /// a name to be associated with the text </param>
+ /// <param name="stream">
+ /// the token stream to retrieve tokens from. </param>
+ /// <param name="boost">
+ /// the boost factor for hits for this field
+ /// </param>
+ /// <param name="positionIncrementGap">
+ /// the position increment gap if fields with the same name are added more than once
+ ///
+ /// </param>
+ /// <seealso cref= org.apache.lucene.document.Field#setBoost(float) </seealso>
+ public virtual void addField(string fieldName, TokenStream stream, float boost, int positionIncrementGap)
+ {
+ addField(fieldName, stream, boost, positionIncrementGap, 1);
+ }
+
+ /// <summary>
+ /// Iterates over the given token stream and adds the resulting terms to the index;
+ /// Equivalent to adding a tokenized, indexed, termVectorStored, unstored,
+ /// Lucene <seealso cref="org.apache.lucene.document.Field"/>.
+ /// Finally closes the token stream. Note that untokenized keywords can be added with this method via
+ /// <seealso cref="#keywordTokenStream(Collection)"/>, the Lucene <code>KeywordTokenizer</code> or similar utilities.
+ ///
+ /// </summary>
+ /// <param name="fieldName">
+ /// a name to be associated with the text </param>
+ /// <param name="stream">
+ /// the token stream to retrieve tokens from. </param>
+ /// <param name="boost">
+ /// the boost factor for hits for this field </param>
+ /// <param name="positionIncrementGap">
+ /// the position increment gap if fields with the same name are added more than once </param>
+ /// <param name="offsetGap">
+ /// the offset gap if fields with the same name are added more than once </param>
+ /// <seealso cref= org.apache.lucene.document.Field#setBoost(float) </seealso>
+ public virtual void addField(string fieldName, TokenStream stream, float boost, int positionIncrementGap, int offsetGap)
+ {
+ try
+ {
+ if (fieldName == null)
+ {
+ throw new System.ArgumentException("fieldName must not be null");
+ }
+ if (stream == null)
+ {
+ throw new System.ArgumentException("token stream must not be null");
+ }
+ if (boost <= 0.0f)
+ {
+ throw new System.ArgumentException("boost factor must be greater than 0.0");
+ }
+ int numTokens = 0;
+ int numOverlapTokens = 0;
+ int pos = -1;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.BytesRefHash terms;
+ BytesRefHash terms;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final SliceByteStartArray sliceArray;
+ SliceByteStartArray sliceArray;
+ Info info = null;
+ long sumTotalTermFreq = 0;
+ int offset = 0;
+ if ((info = fields[fieldName]) != null)
+ {
+ numTokens = info.numTokens;
+ numOverlapTokens = info.numOverlapTokens;
+ pos = info.lastPosition + positionIncrementGap;
+ offset = info.lastOffset + offsetGap;
+ terms = info.terms;
+ boost *= info.boost;
+ sliceArray = info.sliceArray;
+ sumTotalTermFreq = info.sumTotalTermFreq;
+ }
+ else
+ {
+ sliceArray = new SliceByteStartArray(BytesRefHash.DEFAULT_CAPACITY);
+ terms = new BytesRefHash(byteBlockPool, BytesRefHash.DEFAULT_CAPACITY, sliceArray);
+ }
+
+ if (!fieldInfos.ContainsKey(fieldName))
+ {
+ fieldInfos[fieldName] = new FieldInfo(fieldName, true, fieldInfos.Count, false, false, false, this.storeOffsets ? FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS : FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS, null, null, null);
+ }
+ TermToBytesRefAttribute termAtt = stream.getAttribute(typeof(TermToBytesRefAttribute));
+ PositionIncrementAttribute posIncrAttribute = stream.addAttribute(typeof(PositionIncrementAttribute));
+ OffsetAttribute offsetAtt = stream.addAttribute(typeof(OffsetAttribute));
+ BytesRef @ref = termAtt.BytesRef;
+ stream.reset();
+
+ while (stream.incrementToken())
+ {
+ termAtt.fillBytesRef();
+ // if (DEBUG) System.err.println("token='" + term + "'");
+ numTokens++;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int posIncr = posIncrAttribute.getPositionIncrement();
+ int posIncr = posIncrAttribute.PositionIncrement;
+ if (posIncr == 0)
+ {
+ numOverlapTokens++;
+ }
+ pos += posIncr;
+ int ord = terms.add(@ref);
+ if (ord < 0)
+ {
+ ord = (-ord) - 1;
+ postingsWriter.reset(sliceArray.end[ord]);
+ }
+ else
+ {
+ sliceArray.start[ord] = postingsWriter.startNewSlice();
+ }
+ sliceArray.freq[ord]++;
+ sumTotalTermFreq++;
+ if (!storeOffsets)
+ {
+ postingsWriter.writeInt(pos);
+ }
+ else
+ {
+ postingsWriter.writeInt(pos);
+ postingsWriter.writeInt(offsetAtt.startOffset() + offset);
+ postingsWriter.writeInt(offsetAtt.endOffset() + offset);
+ }
+ sliceArray.end[ord] = postingsWriter.CurrentOffset;
+ }
+ stream.end();
+
+ // ensure infos.numTokens > 0 invariant; needed for correct operation of terms()
+ if (numTokens > 0)
+ {
+ fields[fieldName] = new Info(terms, sliceArray, numTokens, numOverlapTokens, boost, pos, offsetAtt.endOffset() + offset, sumTotalTermFreq);
+ sortedFields = null; // invalidate sorted view, if any
+ }
+ } // can never happen
+ catch (Exception e)
+ {
+ throw new Exception(e);
+ }
+ finally
+ {
+ try
+ {
+ if (stream != null)
+ {
+ stream.close();
+ }
+ }
+ catch (IOException e2)
+ {
+ throw new Exception(e2);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Creates and returns a searcher that can be used to execute arbitrary
+ /// Lucene queries and to collect the resulting query results as hits.
+ /// </summary>
+ /// <returns> a searcher </returns>
+ public virtual IndexSearcher createSearcher()
+ {
+ MemoryIndexReader reader = new MemoryIndexReader(this);
+ IndexSearcher searcher = new IndexSearcher(reader); // ensures no auto-close !!
+ reader.Searcher = searcher; // to later get hold of searcher.getSimilarity()
+ return searcher;
+ }
+
+ /// <summary>
+ /// Convenience method that efficiently returns the relevance score by
+ /// matching this index against the given Lucene query expression.
+ /// </summary>
+ /// <param name="query">
+ /// an arbitrary Lucene query to run against this index </param>
+ /// <returns> the relevance score of the matchmaking; A number in the range
+ /// [0.0 .. 1.0], with 0.0 indicating no match. The higher the number
+ /// the better the match.
+ /// </returns>
+ public virtual float Search(Query query)
+ {
+ if (query == null)
+ {
+ throw new System.ArgumentException("query must not be null");
+ }
+
+ IndexSearcher searcher = createSearcher();
+ try
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float[] scores = new float[1];
+ float[] scores = new float[1]; // inits to 0.0f (no match)
+ searcher.search(query, new CollectorAnonymousInnerClassHelper(this, scores));
+ float score = scores[0];
+ return score;
+ } // can never happen (RAMDirectory)
+ catch (IOException e)
+ {
+ throw new Exception(e);
+ }
+ finally
+ {
+ // searcher.close();
+ /*
+ * Note that it is harmless and important for good performance to
+ * NOT close the index reader!!! This avoids all sorts of
+ * unnecessary baggage and locking in the Lucene IndexReader
+ * superclass, all of which is completely unnecessary for this main
+ * memory index data structure without thread-safety claims.
+ *
+ * Wishing IndexReader would be an interface...
+ *
+ * Actually with the new tight createSearcher() API auto-closing is now
+ * made impossible, hence searcher.close() would be harmless and also
+ * would not degrade performance...
+ */
+ }
+ }
+
+ private class CollectorAnonymousInnerClassHelper : Collector
+ {
+ private readonly MemoryIndex outerInstance;
+
+ private float[] scores;
+
+ public CollectorAnonymousInnerClassHelper(MemoryIndex outerInstance, float[] scores)
+ {
+ this.outerInstance = outerInstance;
+ this.scores = scores;
+ }
+
+ private Scorer scorer;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void collect(int doc) throws java.io.IOException
+ public override void collect(int doc)
+ {
+ scores[0] = scorer.score();
+ }
+
+ public override Scorer Scorer
+ {
+ set
+ {
+ this.scorer = value;
+ }
+ }
+
+ public override bool acceptsDocsOutOfOrder()
+ {
+ return true;
+ }
+
+ public override AtomicReaderContext NextReader
+ {
+ set
+ {
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns a reasonable approximation of the main memory [bytes] consumed by
+ /// this instance. Useful for smart memory sensititive caches/pools. </summary>
+ /// <returns> the main memory consumption </returns>
+ public virtual long MemorySize
+ {
+ get
+ {
+ return RamUsageEstimator.sizeOf(this);
+ }
+ }
+
+ /// <summary>
+ /// sorts into ascending order (on demand), reusing memory along the way </summary>
+ private void sortFields()
+ {
+ if (sortedFields == null)
+ {
+ sortedFields = sort(fields);
+ }
+ }
+
+ /// <summary>
+ /// returns a view of the given map's entries, sorted ascending by key </summary>
+ private static KeyValuePair<K, V>[] sort<K, V>(Dictionary<K, V> map)
+ {
+ int size = map.Count;
+//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
+//ORIGINAL LINE: @SuppressWarnings("unchecked") java.util.Map.Entry<K,V>[] entries = new java.util.Map.Entry[size];
+ KeyValuePair<K, V>[] entries = new DictionaryEntry[size];
+
+ IEnumerator<KeyValuePair<K, V>> iter = map.SetOfKeyValuePairs().GetEnumerator();
+ for (int i = 0; i < size; i++)
+ {
+//JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops:
+ entries[i] = iter.next();
+ }
+
+ if (size > 1)
+ {
+ ArrayUtil.introSort(entries, termComparator);
+ }
+ return entries;
+ }
+
+ /// <summary>
+ /// Returns a String representation of the index data for debugging purposes.
+ /// </summary>
+ /// <returns> the string representation </returns>
+ public override string ToString()
+ {
+ StringBuilder result = new StringBuilder(256);
+ sortFields();
+ int sumPositions = 0;
+ int sumTerms = 0;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.BytesRef spare = new org.apache.lucene.util.BytesRef();
+ BytesRef spare = new BytesRef();
+ for (int i = 0; i < sortedFields.Length; i++)
+ {
+ KeyValuePair<string, Info> entry = sortedFields[i];
+ string fieldName = entry.Key;
+ Info info = entry.Value;
+ info.sortTerms();
+ result.Append(fieldName + ":\n");
+ SliceByteStartArray sliceArray = info.sliceArray;
+ int numPositions = 0;
+ SliceReader postingsReader = new SliceReader(intBlockPool);
+ for (int j = 0; j < info.terms.size(); j++)
+ {
+ int ord = info.sortedTerms[j];
+ info.terms.get(ord, spare);
+ int freq = sliceArray.freq[ord];
+ result.Append("\t'" + spare + "':" + freq + ":");
+ postingsReader.reset(sliceArray.start[ord], sliceArray.end[ord]);
+ result.Append(" [");
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int iters = storeOffsets ? 3 : 1;
+ int iters = storeOffsets ? 3 : 1;
+ while (!postingsReader.endOfSlice())
+ {
+ result.Append("(");
+
+ for (int k = 0; k < iters; k++)
+ {
+ result.Append(postingsReader.readInt());
+ if (k < iters - 1)
+ {
+ result.Append(", ");
+ }
+ }
+ result.Append(")");
+ if (!postingsReader.endOfSlice())
+ {
+ result.Append(",");
+ }
+
+ }
+ result.Append("]");
+ result.Append("\n");
+ numPositions += freq;
+ }
+
+ result.Append("\tterms=" + info.terms.size());
+ result.Append(", positions=" + numPositions);
+ result.Append(", memory=" + RamUsageEstimator.humanReadableUnits(RamUsageEstimator.sizeOf(info)));
+ result.Append("\n");
+ sumPositions += numPositions;
+ sumTerms += info.terms.size();
+ }
+
+ result.Append("\nfields=" + sortedFields.Length);
+ result.Append(", terms=" + sumTerms);
+ result.Append(", positions=" + sumPositions);
+ result.Append(", memory=" + RamUsageEstimator.humanReadableUnits(MemorySize));
+ return result.ToString();
+ }
+
+ /// <summary>
+ /// Index data structure for a field; Contains the tokenized term texts and
+ /// their positions.
+ /// </summary>
+ private sealed class Info
+ {
+
+ /// <summary>
+ /// Term strings and their positions for this field: Map <String
+ /// termText, ArrayIntList positions>
+ /// </summary>
+ internal readonly BytesRefHash terms;
+
+ internal readonly SliceByteStartArray sliceArray;
+
+ /// <summary>
+ /// Terms sorted ascending by term text; computed on demand </summary>
+ [NonSerialized]
+ internal int[] sortedTerms;
+
+ /// <summary>
+ /// Number of added tokens for this field </summary>
+ internal readonly int numTokens;
+
+ /// <summary>
+ /// Number of overlapping tokens for this field </summary>
+ internal readonly int numOverlapTokens;
+
+ /// <summary>
+ /// Boost factor for hits for this field </summary>
+ internal readonly float boost;
+
+ internal readonly long sumTotalTermFreq;
+
+ /// <summary>
+ /// the last position encountered in this field for multi field support </summary>
+ internal int lastPosition;
+
+ /// <summary>
+ /// the last offset encountered in this field for multi field support </summary>
+ internal int lastOffset;
+
+ public Info(BytesRefHash terms, SliceByteStartArray sliceArray, int numTokens, int numOverlapTokens, float boost, int lastPosition, int lastOffset, long sumTotalTermFreq)
+ {
+ this.terms = terms;
+ this.sliceArray = sliceArray;
+ this.numTokens = numTokens;
+ this.numOverlapTokens = numOverlapTokens;
+ this.boost = boost;
+ this.sumTotalTermFreq = sumTotalTermFreq;
+ this.lastPosition = lastPosition;
+ this.lastOffset = lastOffset;
+ }
+
+ public long SumTotalTermFreq
+ {
+ get
+ {
+ return sumTotalTermFreq;
+ }
+ }
+
+ /// <summary>
+ /// Sorts hashed terms into ascending order, reusing memory along the
+ /// way. Note that sorting is lazily delayed until required (often it's
+ /// not required at all). If a sorted view is required then hashing +
+ /// sort + binary search is still faster and smaller than TreeMap usage
+ /// (which would be an alternative and somewhat more elegant approach,
+ /// apart from more sophisticated Tries / prefix trees).
+ /// </summary>
+ public void sortTerms()
+ {
+ if (sortedTerms == null)
+ {
+ sortedTerms = terms.sort(BytesRef.UTF8SortedAsUnicodeComparator);
+ }
+ }
+
+ public float Boost
+ {
+ get
+ {
+ return boost;
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Nested classes:
+ ///////////////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// Search support for Lucene framework integration; implements all methods
+ /// required by the Lucene IndexReader contracts.
+ /// </summary>
+ private sealed class MemoryIndexReader : AtomicReader
+ {
+ private readonly MemoryIndex outerInstance;
+
+
+ internal IndexSearcher searcher; // needed to find searcher.getSimilarity()
+
+ internal MemoryIndexReader(MemoryIndex outerInstance) : base(); // avoid as much superclass baggage as possible
+ {
+ this.outerInstance = outerInstance;
+ }
+
+ internal Info getInfo(string fieldName)
+ {
+ return outerInstance.fields[fieldName];
+ }
+
+ internal Info getInfo(int pos)
+ {
+ return outerInstance.sortedFields[pos].Value;
+ }
+
+ public override Bits LiveDocs
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public override FieldInfos FieldInfos
+ {
+ get
+ {
+ return new FieldInfos(outerInstance.fieldInfos.Values.toArray(new FieldInfo[outerInstance.fieldInfos.Count]));
+ }
+ }
+
+ public override NumericDocValues getNumericDocValues(string field)
+ {
+ return null;
+ }
+
+ public override BinaryDocValues getBinaryDocValues(string field)
+ {
+ return null;
+ }
+
+ public override SortedDocValues getSortedDocValues(string field)
+ {
+ return null;
+ }
+
+ public override SortedSetDocValues getSortedSetDocValues(string field)
+ {
+ return null;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.util.Bits getDocsWithField(String field) throws java.io.IOException
+ public override Bits getDocsWithField(string field)
+ {
+ return null;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void checkIntegrity() throws java.io.IOException
+ public override void checkIntegrity()
+ {
+ // no-op
+ }
+
+ private class MemoryFields : Fields
+ {
+ private readonly MemoryIndex.MemoryIndexReader outerInstance;
+
+ public MemoryFields(MemoryIndex.MemoryIndexReader outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+ public override IEnumerator<string> iterator()
+ {
+ return new IteratorAnonymousInnerClassHelper(this);
+ }
+
+ private class IteratorAnonymousInnerClassHelper : IEnumerator<string>
+ {
+ private readonly MemoryFields outerInstance;
+
+ public IteratorAnonymousInnerClassHelper(MemoryFields outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ upto = -1;
+ }
+
+ internal int upto;
+
+ public virtual string next()
+ {
+ upto++;
+ if (upto >= outerInstance.outerInstance.outerInstance.sortedFields.Length)
+ {
+ throw new NoSuchElementException();
+ }
+ return outerInstance.outerInstance.outerInstance.sortedFields[upto].Key;
+ }
+
+ public virtual bool hasNext()
+ {
+ return upto + 1 < outerInstance.outerInstance.outerInstance.sortedFields.Length;
+ }
+
+ public virtual void remove()
+ {
+ throw new System.NotSupportedException();
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.Terms terms(final String field)
+ public override Terms terms(string field)
+ {
+ int i = Arrays.binarySearch(outerInstance.outerInstance.sortedFields, field, termComparator);
+ if (i < 0)
+ {
+ return null;
+ }
+ else
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Info info = getInfo(i);
+ Info info = outerInstance.getInfo(i);
+ info.sortTerms();
+
+ return new TermsAnonymousInnerClassHelper(this, info);
+ }
+ }
+
+ private class TermsAnonymousInnerClassHelper : Terms
+ {
+ private readonly MemoryFields outerInstance;
+
+ private MemoryIndex.Info info;
+
+ public TermsAnonymousInnerClassHelper(MemoryFields outerInstance, MemoryIndex.Info info)
+ {
+ this.outerInstance = outerInstance;
+ this.info = info;
+ }
+
+ public override TermsEnum iterator(TermsEnum reuse)
+ {
+ return new MemoryTermsEnum(outerInstance.outerInstance, info);
+ }
+
+ public override IComparer<BytesRef> Comparator
+ {
+ get
+ {
+ return BytesRef.UTF8SortedAsUnicodeComparator;
+ }
+ }
+
+ public override long size()
+ {
+ return info.terms.size();
+ }
+
+ public override long SumTotalTermFreq
+ {
+ get
+ {
+ return info.SumTotalTermFreq;
+ }
+ }
+
+ public override long SumDocFreq
+ {
+ get
+ {
+ // each term has df=1
+ return info.terms.size();
+ }
+ }
+
+ public override int DocCount
+ {
+ get
+ {
+ return info.terms.size() > 0 ? 1 : 0;
+ }
+ }
+
+ public override bool hasFreqs()
+ {
+ return true;
+ }
+
+ public override bool hasOffsets()
+ {
+ return outerInstance.outerInstance.outerInstance.storeOffsets;
+ }
+
+ public override bool hasPositions()
+ {
+ return true;
+ }
+
+ public override bool hasPayloads()
+ {
+ return false;
+ }
+ }
+
+ public override int size()
+ {
+ return outerInstance.outerInstance.sortedFields.Length;
+ }
+ }
+
+ public override Fields fields()
+ {
+ outerInstance.sortFields();
+ return new MemoryFields(this);
+ }
+
+ private class MemoryTermsEnum : TermsEnum
+ {
+ private readonly MemoryIndex.MemoryIndexReader outerInstance;
+
+ internal readonly Info info;
+ internal readonly BytesRef br = new BytesRef();
+ internal int termUpto = -1;
+
+ public MemoryTermsEnum(MemoryIndex.MemoryIndexReader outerInstance, Info info)
+ {
+ this.outerInstance = outerInstance;
+ this.info = info;
+ info.sortTerms();
+ }
+
+ internal int binarySearch(BytesRef b, BytesRef bytesRef, int low, int high, BytesRefHash hash, int[] ords, IComparer<BytesRef> comparator)
+ {
+ int mid = 0;
+ while (low <= high)
+ {
+ mid = (int)((uint)(low + high) >> 1);
+ hash.get(ords[mid], bytesRef);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int cmp = comparator.compare(bytesRef, b);
+ int cmp = comparator.Compare(bytesRef, b);
+ if (cmp < 0)
+ {
+ low = mid + 1;
+ }
+ else if (cmp > 0)
+ {
+ high = mid - 1;
+ }
+ else
+ {
+ return mid;
+ }
+ }
+ Debug.Assert(comparator.Compare(bytesRef, b) != 0);
+ return -(low + 1);
+ }
+
+
+ public override bool seekExact(BytesRef text)
+ {
+ termUpto = binarySearch(text, br, 0, info.terms.size() - 1, info.terms, info.sortedTerms, BytesRef.UTF8SortedAsUnicodeComparator);
+ return termUpto >= 0;
+ }
+
+ public override SeekStatus seekCeil(BytesRef text)
+ {
+ termUpto = binarySearch(text, br, 0, info.terms.size() - 1, info.terms, info.sortedTerms, BytesRef.UTF8SortedAsUnicodeComparator);
+ if (termUpto < 0) // not found; choose successor
+ {
+ termUpto = -termUpto - 1;
+ if (termUpto >= info.terms.size())
+ {
+ return SeekStatus.END;
+ }
+ else
+ {
+ info.terms.get(info.sortedTerms[termUpto], br);
+ return SeekStatus.NOT_FOUND;
+ }
+ }
+ else
+ {
+ return SeekStatus.FOUND;
+ }
+ }
+
+ public override void SeekExact(long ord)
+ {
+ Debug.Assert(ord < info.terms.size());
+ termUpto = (int) ord;
+ }
+
+ public override BytesRef Next()
+ {
+ termUpto++;
+ if (termUpto >= info.terms.size())
+ {
+ return null;
+ }
+ else
+ {
+ info.terms.get(info.sortedTerms[termUpto], br);
+ return br;
+ }
+ }
+
+ public override BytesRef term()
+ {
+ return br;
+ }
+
+ public override long ord()
+ {
+ return termUpto;
+ }
+
+ public override int docFreq()
+ {
+ return 1;
+ }
+
+ public override long totalTermFreq()
+ {
+ return info.sliceArray.freq[info.sortedTerms[termUpto]];
+ }
+
+ public override DocsEnum docs(Bits liveDocs, DocsEnum reuse, int flags)
+ {
+ if (reuse == null || !(reuse is MemoryDocsEnum))
+ {
+ reuse = new MemoryDocsEnum(outerInstance);
+ }
+ return ((MemoryDocsEnum) reuse).reset(liveDocs, info.sliceArray.freq[info.sortedTerms[termUpto]]);
+ }
+
+ public override DocsAndPositionsEnum docsAndPositions(Bits liveDocs, DocsAndPositionsEnum reuse, int flags)
+ {
+ if (reuse == null || !(reuse is MemoryDocsAndPositionsEnum))
+ {
+ reuse = new MemoryDocsAndPositionsEnum(outerInstance);
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int ord = info.sortedTerms[termUpto];
+ int ord = info.sortedTerms[termUpto];
+ return ((MemoryDocsAndPositionsEnum) reuse).reset(liveDocs, info.sliceArray.start[ord], info.sliceArray.end[ord], info.sliceArray.freq[ord]);
+ }
+
+ public override IComparer<BytesRef> Comparator
+ {
+ get
+ {
+ return BytesRef.UTF8SortedAsUnicodeComparator;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void seekExact(org.apache.lucene.util.BytesRef term, org.apache.lucene.index.TermState state) throws java.io.IOException
+ public override void seekExact(BytesRef term, TermState state)
+ {
+ Debug.Assert(state != null);
+ this.seekExact(((OrdTermState)state).ord);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.TermState termState() throws java.io.IOException
+ public override TermState termState()
+ {
+ OrdTermState ts = new OrdTermState();
+ ts.ord = termUpto;
+ return ts;
+ }
+ }
+
+ private class MemoryDocsEnum : DocsEnum
+ {
+ private readonly MemoryIndex.MemoryIndexReader outerInstance;
+
+ public MemoryDocsEnum(MemoryIndex.MemoryIndexReader outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+ internal bool hasNext;
+ internal Bits liveDocs;
+ internal int doc = -1;
+ internal int freq_Renamed;
+
+ public virtual DocsEnum reset(Bits liveDocs, int freq)
+ {
+ this.liveDocs = liveDocs;
+ hasNext = true;
+ doc = -1;
+ this.freq_Renamed = freq;
+ return this;
+ }
+
+ public override int docID()
+ {
+ return doc;
+ }
+
+ public override int nextDoc()
+ {
+ if (hasNext && (liveDocs == null || liveDocs.get(0)))
+ {
+ hasNext = false;
+ return doc = 0;
+ }
+ else
+ {
+ return doc = NO_MORE_DOCS;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int advance(int target) throws java.io.IOException
+ public override int advance(int target)
+ {
+ return slowAdvance(target);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int freq() throws java.io.IOException
+ public override int freq()
+ {
+ return freq_Renamed;
+ }
+
+ public override long cost()
+ {
+ return 1;
+ }
+ }
+
+ private class MemoryDocsAndPositionsEnum : DocsAndPositionsEnum
+ {
+ private readonly MemoryIndex.MemoryIndexReader outerInstance;
+
+ internal int posUpto; // for assert
+ internal bool hasNext;
+ internal Bits liveDocs;
+ internal int doc = -1;
+ internal SliceReader sliceReader;
+ internal int freq_Renamed;
+ internal int startOffset_Renamed;
+ internal int endOffset_Renamed;
+
+ public MemoryDocsAndPositionsEnum(MemoryIndex.MemoryIndexReader outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ this.sliceReader = new SliceReader(outerInstance.outerInstance.intBlockPool);
+ }
+
+ public virtual DocsAndPositionsEnum reset(Bits liveDocs, int start, int end, int freq)
+ {
+ this.liveDocs = liveDocs;
+ this.sliceReader.reset(start, end);
+ posUpto = 0; // for assert
+ hasNext = true;
+ doc = -1;
+ this.freq_Renamed = freq;
+ return this;
+ }
+
+
+ public override int docID()
+ {
+ return doc;
+ }
+
+ public override int nextDoc()
+ {
+ if (hasNext && (liveDocs == null || liveDocs.get(0)))
+ {
+ hasNext = false;
+ return doc = 0;
+ }
+ else
+ {
+ return doc = NO_MORE_DOCS;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int advance(int target) throws java.io.IOException
+ public override int advance(int target)
+ {
+ return slowAdvance(target);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int freq() throws java.io.IOException
+ public override int freq()
+ {
+ return freq_Renamed;
+ }
+
+ public override int nextPosition()
+ {
+ Debug.Assert(posUpto++ < freq_Renamed);
+ Debug.Assert(!sliceReader.endOfSlice(), " stores offsets : " + startOffset_Renamed);
+ if (outerInstance.outerInstance.storeOffsets)
+ {
+ int pos = sliceReader.readInt();
+ startOffset_Renamed = sliceReader.readInt();
+ endOffset_Renamed = sliceReader.readInt();
+ return pos;
+ }
+ else
+ {
+ return sliceReader.readInt();
+ }
+ }
+
+ public override int startOffset()
+ {
+ return startOffset_Renamed;
+ }
+
+ public override int endOffset()
+ {
+ return endOffset_Renamed;
+ }
+
+ public override BytesRef Payload
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public override long cost()
+ {
+ return 1;
+ }
+ }
+
+ public override Fields getTermVectors(int docID)
+ {
+ if (docID == 0)
+ {
+ return fields();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ internal Similarity Similarity
+ {
+ get
+ {
+ if (searcher != null)
+ {
+ return searcher.Similarity;
+ }
+ return IndexSearcher.DefaultSimilarity;
+ }
+ }
+
+ internal IndexSearcher Searcher
+ {
+ set
+ {
+ this.searcher = value;
+ }
+ }
+
+ public override int numDocs()
+ {
+ if (DEBUG)
+ {
+ Console.Error.WriteLine("MemoryIndexReader.numDocs");
+ }
+ return 1;
+ }
+
+ public override int maxDoc()
+ {
+ if (DEBUG)
+ {
+ Console.Error.WriteLine("MemoryIndexReader.maxDoc");
+ }
+ return 1;
+ }
+
+ public override void document(int docID, StoredFieldVisitor visitor)
+ {
+ if (DEBUG)
+ {
+ Console.Error.WriteLine("MemoryIndexReader.document");
+ }
+ // no-op: there are no stored fields
+ }
+
+ protected internal override void doClose()
+ {
+ if (DEBUG)
+ {
+ Console.Error.WriteLine("MemoryIndexReader.doClose");
+ }
+ }
+
+ /// <summary>
+ /// performance hack: cache norms to avoid repeated expensive calculations </summary>
+ internal NumericDocValues cachedNormValues;
+ internal string cachedFieldName;
+ internal Similarity cachedSimilarity;
+
+ public override NumericDocValues getNormValues(string field)
+ {
+ FieldInfo fieldInfo = outerInstance.fieldInfos[field];
+ if (fieldInfo == null || fieldInfo.omitsNorms())
+ {
+ return null;
+ }
+ NumericDocValues norms = cachedNormValues;
+ Similarity sim = Similarity;
+ if (!field.Equals(cachedFieldName) || sim != cachedSimilarity) // not cached?
+ {
+ Info info = getInfo(field);
+ int numTokens = info != null ? info.numTokens : 0;
+ int numOverlapTokens = info != null ? info.numOverlapTokens : 0;
+ float boost = info != null ? info.Boost : 1.0f;
+ FieldInvertState invertState = new FieldInvertState(field, 0, numTokens, numOverlapTokens, 0, boost);
+ long value = sim.computeNorm(invertState);
+ norms = new MemoryIndexNormDocValues(value);
+ // cache it for future reuse
+ cachedNormValues = norms;
+ cachedFieldName = field;
+ cachedSimilarity = sim;
+ if (DEBUG)
+ {
+ Console.Error.WriteLine("MemoryIndexReader.norms: " + field + ":" + value + ":" + numTokens);
+ }
+ }
+ return norms;
+ }
+ }
+
+ /// <summary>
+ /// Resets the <seealso cref="MemoryIndex"/> to its initial state and recycles all internal buffers.
+ /// </summary>
+ public virtual void reset()
+ {
+ this.fieldInfos.Clear();
+ this.fields.Clear();
+ this.sortedFields = null;
+ byteBlockPool.reset(false, false); // no need to 0-fill the buffers
+ intBlockPool.reset(true, false); // here must must 0-fill since we use slices
+ }
+
+ private sealed class SliceByteStartArray : BytesRefHash.DirectBytesStartArray
+ {
+ internal int[] start; // the start offset in the IntBlockPool per term
+ internal int[] end; // the end pointer in the IntBlockPool for the postings slice per term
+ internal int[] freq; // the term frequency
+
+ public SliceByteStartArray(int initSize) : base(initSize)
+ {
+ }
+
+ public override int[] init()
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int[] ord = base.init();
+ int[] ord = base.init();
+ start = new int[ArrayUtil.oversize(ord.Length, RamUsageEstimator.NUM_BYTES_INT)];
+ end = new int[ArrayUtil.oversize(ord.Length, RamUsageEstimator.NUM_BYTES_INT)];
+ freq = new int[ArrayUtil.oversize(ord.Length, RamUsageEstimator.NUM_BYTES_INT)];
+ Debug.Assert(start.Length >= ord.Length);
+ Debug.Assert(end.Length >= ord.Length);
+ Debug.Assert(freq.Length >= ord.Length);
+ return ord;
+ }
+
+ public override int[] grow()
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int[] ord = base.grow();
+ int[] ord = base.grow();
+ if (start.Length < ord.Length)
+ {
+ start = ArrayUtil.grow(start, ord.Length);
+ end = ArrayUtil.grow(end, ord.Length);
+ freq = ArrayUtil.grow(freq, ord.Length);
+ }
+ Debug.Assert(start.Length >= ord.Length);
+ Debug.Assert(end.Length >= ord.Length);
+ Debug.Assert(freq.Length >= ord.Length);
+ return ord;
+ }
+
+ public override int[] clear()
+ {
+ start = end = null;
+ return base.clear();
+ }
+
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/531b4af0/src/Lucene.Net.Memory/MemoryIndexNormDocValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Memory/MemoryIndexNormDocValues.cs b/src/Lucene.Net.Memory/MemoryIndexNormDocValues.cs
new file mode 100644
index 0000000..cc051b9
--- /dev/null
+++ b/src/Lucene.Net.Memory/MemoryIndexNormDocValues.cs
@@ -0,0 +1,47 @@
+using Lucene.Net.Index;
+
+namespace Lucene.Net.Memory
+{
+ /*
+ * 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.
+ */
+
+ ///
+ /// <summary>
+ /// @lucene.internal
+ /// </summary>
+ internal class MemoryIndexNormDocValues : NumericDocValues
+ {
+ private readonly long value;
+ public MemoryIndexNormDocValues(long value)
+ {
+ this.value = value;
+ }
+
+ public override long Get(int docID)
+ {
+ if (docID != 0)
+ {
+ throw new System.IndexOutOfRangeException();
+ }
+ else
+ {
+ return value;
+ }
+ }
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/531b4af0/src/Lucene.Net.Memory/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Memory/Properties/AssemblyInfo.cs b/src/Lucene.Net.Memory/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4b92a94
--- /dev/null
+++ b/src/Lucene.Net.Memory/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Lucene.Net.Memory")]
+[assembly: AssemblyDescription("Single-document in-memory index implementation")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Lucene.Net.Memory")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("ca052094-4c45-44d7-9dcf-3d46ae6930fe")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
[08/11] Skeleton porting of Lucene.Net.Misc
Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Store/NativeUnixDirectory.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Store/NativeUnixDirectory.cs b/src/Lucene.Net.Misc/Store/NativeUnixDirectory.cs
new file mode 100644
index 0000000..ad74aa1
--- /dev/null
+++ b/src/Lucene.Net.Misc/Store/NativeUnixDirectory.cs
@@ -0,0 +1,527 @@
+using System;
+using System.Diagnostics;
+
+namespace org.apache.lucene.store
+{
+
+ /*
+ * 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.
+ */
+
+ ignore
+ import java.nio.channels.FileChannel;
+
+ import org.apache.lucene.store.Directory; // javadoc
+ import org.apache.lucene.store.IOContext.Context;
+
+ // TODO
+ // - newer Linux kernel versions (after 2.6.29) have
+ // improved MADV_SEQUENTIAL (and hopefully also
+ // FADV_SEQUENTIAL) interaction with the buffer
+ // cache; we should explore using that instead of direct
+ // IO when context is merge
+
+ /// <summary>
+ /// A <seealso cref="Directory"/> implementation for all Unixes that uses
+ /// DIRECT I/O to bypass OS level IO caching during
+ /// merging. For all other cases (searching, writing) we delegate
+ /// to the provided Directory instance.
+ ///
+ /// <para>See <a
+ /// href="{@docRoot}/overview-summary.html#NativeUnixDirectory">Overview</a>
+ /// for more details.
+ ///
+ /// </para>
+ /// <para>To use this you must compile
+ /// NativePosixUtil.cpp (exposes Linux-specific APIs through
+ /// JNI) for your platform, by running <code>ant
+ /// build-native-unix</code>, and then putting the resulting
+ /// <code>libNativePosixUtil.so</code> (from
+ /// <code>lucene/build/native</code>) onto your dynamic
+ /// linker search path.
+ ///
+ /// </para>
+ /// <para><b>WARNING</b>: this code is very new and quite easily
+ /// could contain horrible bugs. For example, here's one
+ /// known issue: if you use seek in <code>IndexOutput</code>, and then
+ /// write more than one buffer's worth of bytes, then the
+ /// file will be wrong. Lucene does not do this today (only writes
+ /// small number of bytes after seek), but that may change.
+ ///
+ /// </para>
+ /// <para>This directory passes Solr and Lucene tests on Linux
+ /// and OS X; other Unixes should work but have not been
+ /// tested! Use at your own risk.
+ ///
+ /// @lucene.experimental
+ /// </para>
+ /// </summary>
+ public class NativeUnixDirectory extends FSDirectory
+ {
+
+ // TODO: this is OS dependent, but likely 512 is the LCD
+ private final static long ALIGN = 512;
+ private final static long ALIGN_NOT_MASK = ~(ALIGN - 1);
+
+ /// <summary>
+ /// Default buffer size before writing to disk (256 KB);
+ /// larger means less IO load but more RAM and direct
+ /// buffer storage space consumed during merging.
+ /// </summary>
+
+ public final static int DEFAULT_MERGE_BUFFER_SIZE = 262144;
+
+ /// <summary>
+ /// Default min expected merge size before direct IO is
+ /// used (10 MB):
+ /// </summary>
+ public final static long DEFAULT_MIN_BYTES_DIRECT = 10 * 1024 * 1024;
+
+ private final int mergeBufferSize;
+ private final long minBytesDirect;
+ private final Directory @delegate;
+
+ /// <summary>
+ /// Create a new NIOFSDirectory for the named location.
+ /// </summary>
+ /// <param name="path"> the path of the directory </param>
+ /// <param name="mergeBufferSize"> Size of buffer to use for
+ /// merging. See <seealso cref="#DEFAULT_MERGE_BUFFER_SIZE"/>. </param>
+ /// <param name="minBytesDirect"> Merges, or files to be opened for
+ /// reading, smaller than this will
+ /// not use direct IO. See {@link
+ /// #DEFAULT_MIN_BYTES_DIRECT} </param>
+ /// <param name="delegate"> fallback Directory for non-merges </param>
+ /// <exception cref="IOException"> If there is a low-level I/O error </exception>
+ public NativeUnixDirectory(File path, int mergeBufferSize, long minBytesDirect, Directory @delegate) throws IOException
+ {
+ base(path, @delegate.LockFactory);
+ if ((mergeBufferSize & ALIGN) != 0)
+ {
+ throw new System.ArgumentException("mergeBufferSize must be 0 mod " + ALIGN + " (got: " + mergeBufferSize + ")");
+ }
+ this.mergeBufferSize = mergeBufferSize;
+ this.minBytesDirect = minBytesDirect;
+ this.@delegate = @delegate;
+ }
+
+ /// <summary>
+ /// Create a new NIOFSDirectory for the named location.
+ /// </summary>
+ /// <param name="path"> the path of the directory </param>
+ /// <param name="delegate"> fallback Directory for non-merges </param>
+ /// <exception cref="IOException"> If there is a low-level I/O error </exception>
+ public NativeUnixDirectory(File path, Directory @delegate) throws IOException
+ {
+ this(path, DEFAULT_MERGE_BUFFER_SIZE, DEFAULT_MIN_BYTES_DIRECT, @delegate);
+ }
+
+ public IndexInput openInput(string name, IOContext context) throws IOException
+ {
+ ensureOpen();
+ if (context.context != Context.MERGE || context.mergeInfo.estimatedMergeBytes < minBytesDirect || fileLength(name) < minBytesDirect)
+ {
+ return @delegate.openInput(name, context);
+ }
+ else
+ {
+ return new NativeUnixIndexInput(new File(Directory, name), mergeBufferSize);
+ }
+ }
+
+ public IndexOutput createOutput(string name, IOContext context) throws IOException
+ {
+ ensureOpen();
+ if (context.context != Context.MERGE || context.mergeInfo.estimatedMergeBytes < minBytesDirect)
+ {
+ return @delegate.createOutput(name, context);
+ }
+ else
+ {
+ ensureCanWrite(name);
+ return new NativeUnixIndexOutput(new File(Directory, name), mergeBufferSize);
+ }
+ }
+
+ private final static class NativeUnixIndexOutput extends IndexOutput
+ {
+ private final ByteBuffer buffer;
+ private final FileOutputStream fos;
+ private final FileChannel channel;
+ private final int bufferSize;
+
+ //private final File path;
+
+ private int bufferPos;
+ private long filePos;
+ private long fileLength;
+ private bool isOpen;
+
+ public NativeUnixIndexOutput(File path, int bufferSize) throws IOException
+ {
+ //this.path = path;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final java.io.FileDescriptor fd = NativePosixUtil.open_direct(path.toString(), false);
+ FileDescriptor fd = NativePosixUtil.open_direct(path.ToString(), false);
+ fos = new FileOutputStream(fd);
+ //fos = new FileOutputStream(path);
+ channel = fos.Channel;
+ buffer = ByteBuffer.allocateDirect(bufferSize);
+ this.bufferSize = bufferSize;
+ isOpen = true;
+ }
+
+ public void writeByte(sbyte b) throws IOException
+ {
+ Debug.Assert(bufferPos == buffer.position(), "bufferPos=" + bufferPos + " vs buffer.position()=" + buffer.position());
+ buffer.put(b);
+ if (++bufferPos == bufferSize)
+ {
+ dump();
+ }
+ }
+
+ public void writeBytes(sbyte[] src, int offset, int len) throws IOException
+ {
+ int toWrite = len;
+ while (true)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int left = bufferSize - bufferPos;
+ int left = bufferSize - bufferPos;
+ if (left <= toWrite)
+ {
+ buffer.put(src, offset, left);
+ toWrite -= left;
+ offset += left;
+ bufferPos = bufferSize;
+ dump();
+ }
+ else
+ {
+ buffer.put(src, offset, toWrite);
+ bufferPos += toWrite;
+ break;
+ }
+ }
+ }
+
+ //@Override
+ //public void setLength() throws IOException {
+ // TODO -- how to impl this? neither FOS nor
+ // FileChannel provides an API?
+ //}
+
+ public void flush()
+ {
+ // TODO -- I don't think this method is necessary?
+ }
+
+ private void dump() throws IOException
+ {
+ buffer.flip();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long limit = filePos + buffer.limit();
+ long limit = filePos + buffer.limit();
+ if (limit > fileLength)
+ {
+ // this dump extends the file
+ fileLength = limit;
+ }
+ else
+ {
+ // we had seek'd back & wrote some changes
+ }
+
+ // must always round to next block
+ buffer.limit((int)((buffer.limit() + ALIGN - 1) & ALIGN_NOT_MASK));
+
+ assert(buffer.limit() & ALIGN_NOT_MASK) == buffer.limit() : "limit=" + buffer.limit() + " vs " + (buffer.limit() & ALIGN_NOT_MASK);
+ assert(filePos & ALIGN_NOT_MASK) == filePos;
+ //System.out.println(Thread.currentThread().getName() + ": dump to " + filePos + " limit=" + buffer.limit() + " fos=" + fos);
+ channel.write(buffer, filePos);
+ filePos += bufferPos;
+ bufferPos = 0;
+ buffer.clear();
+ //System.out.println("dump: done");
+
+ // TODO: the case where we'd seek'd back, wrote an
+ // entire buffer, we must here read the next buffer;
+ // likely Lucene won't trip on this since we only
+ // write smallish amounts on seeking back
+ }
+
+ public long FilePointer
+ {
+ return filePos + bufferPos;
+ }
+
+ // TODO: seek is fragile at best; it can only properly
+ // handle seek & then change bytes that fit entirely
+ // within one buffer
+ public void seek(long pos) throws IOException
+ {
+ if (pos != FilePointer)
+ {
+ dump();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long alignedPos = pos & ALIGN_NOT_MASK;
+ long alignedPos = pos & ALIGN_NOT_MASK;
+ filePos = alignedPos;
+ int n = (int) NativePosixUtil.pread(fos.FD, filePos, buffer);
+ if (n < bufferSize)
+ {
+ buffer.limit(n);
+ }
+ //System.out.println("seek refill=" + n);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int delta = (int)(pos - alignedPos);
+ int delta = (int)(pos - alignedPos);
+ buffer.position(delta);
+ bufferPos = delta;
+ }
+ }
+
+ public long length()
+ {
+ return fileLength + bufferPos;
+ }
+
+ public long Checksum throws IOException
+ {
+ throw new System.NotSupportedException("this directory currently does not work at all!");
+ }
+
+ public void close() throws IOException
+ {
+ if (isOpen)
+ {
+ isOpen = false;
+ try
+ {
+ dump();
+ }
+ finally
+ {
+ try
+ {
+ //System.out.println("direct close set len=" + fileLength + " vs " + channel.size() + " path=" + path);
+ channel.truncate(fileLength);
+ //System.out.println(" now: " + channel.size());
+ }
+ finally
+ {
+ try
+ {
+ channel.close();
+ }
+ finally
+ {
+ fos.close();
+ //System.out.println(" final len=" + path.length());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private final static class NativeUnixIndexInput extends IndexInput
+ {
+ private final ByteBuffer buffer;
+ private final FileInputStream fis;
+ private final FileChannel channel;
+ private final int bufferSize;
+
+ private bool isOpen;
+ private bool isClone;
+ private long filePos;
+ private int bufferPos;
+
+ public NativeUnixIndexInput(File path, int bufferSize) throws IOException
+ {
+ base("NativeUnixIndexInput(path=\"" + path.Path + "\")");
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final java.io.FileDescriptor fd = NativePosixUtil.open_direct(path.toString(), true);
+ FileDescriptor fd = NativePosixUtil.open_direct(path.ToString(), true);
+ fis = new FileInputStream(fd);
+ channel = fis.Channel;
+ this.bufferSize = bufferSize;
+ buffer = ByteBuffer.allocateDirect(bufferSize);
+ isOpen = true;
+ isClone = false;
+ filePos = -bufferSize;
+ bufferPos = bufferSize;
+ //System.out.println("D open " + path + " this=" + this);
+ }
+
+ // for clone
+ public NativeUnixIndexInput(NativeUnixIndexInput other) throws IOException
+ {
+ base(other.ToString());
+ this.fis = null;
+ channel = other.channel;
+ this.bufferSize = other.bufferSize;
+ buffer = ByteBuffer.allocateDirect(bufferSize);
+ filePos = -bufferSize;
+ bufferPos = bufferSize;
+ isOpen = true;
+ isClone = true;
+ //System.out.println("D clone this=" + this);
+ seek(other.FilePointer);
+ }
+
+ public void close() throws IOException
+ {
+ if (isOpen && !isClone)
+ {
+ try
+ {
+ channel.close();
+ }
+ finally
+ {
+ if (!isClone)
+ {
+ fis.close();
+ }
+ }
+ }
+ }
+
+ public long FilePointer
+ {
+ return filePos + bufferPos;
+ }
+
+ public void seek(long pos) throws IOException
+ {
+ if (pos != FilePointer)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long alignedPos = pos & ALIGN_NOT_MASK;
+ long alignedPos = pos & ALIGN_NOT_MASK;
+ filePos = alignedPos - bufferSize;
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int delta = (int)(pos - alignedPos);
+ int delta = (int)(pos - alignedPos);
+ if (delta != 0)
+ {
+ refill();
+ buffer.position(delta);
+ bufferPos = delta;
+ }
+ else
+ {
+ // force refill on next read
+ bufferPos = bufferSize;
+ }
+ }
+ }
+
+ public long length()
+ {
+ try
+ {
+ return channel.size();
+ }
+ catch (IOException ioe)
+ {
+ throw new Exception("IOException during length(): " + this, ioe);
+ }
+ }
+
+ public sbyte readByte() throws IOException
+ {
+ // NOTE: we don't guard against EOF here... ie the
+ // "final" buffer will typically be filled to less
+ // than bufferSize
+ if (bufferPos == bufferSize)
+ {
+ refill();
+ }
+ Debug.Assert(bufferPos == buffer.position(), "bufferPos=" + bufferPos + " vs buffer.position()=" + buffer.position());
+ bufferPos++;
+ return buffer.get();
+ }
+
+ private void refill() throws IOException
+ {
+ buffer.clear();
+ filePos += bufferSize;
+ bufferPos = 0;
+ assert(filePos & ALIGN_NOT_MASK) == filePos : "filePos=" + filePos + " anded=" + (filePos & ALIGN_NOT_MASK);
+ //System.out.println("X refill filePos=" + filePos);
+ int n;
+ try
+ {
+ n = channel.read(buffer, filePos);
+ }
+ catch (IOException ioe)
+ {
+ throw new IOException(ioe.Message + ": " + this, ioe);
+ }
+ if (n < 0)
+ {
+ throw new EOFException("read past EOF: " + this);
+ }
+ buffer.rewind();
+ }
+
+ public void readBytes(sbyte[] dst, int offset, int len) throws IOException
+ {
+ int toRead = len;
+ //System.out.println("\nX readBytes len=" + len + " fp=" + getFilePointer() + " size=" + length() + " this=" + this);
+ while (true)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int left = bufferSize - bufferPos;
+ int left = bufferSize - bufferPos;
+ if (left < toRead)
+ {
+ //System.out.println(" copy " + left);
+ buffer.get(dst, offset, left);
+ toRead -= left;
+ offset += left;
+ refill();
+ }
+ else
+ {
+ //System.out.println(" copy " + toRead);
+ buffer.get(dst, offset, toRead);
+ bufferPos += toRead;
+ //System.out.println(" readBytes done");
+ break;
+ }
+ }
+ }
+
+ public NativeUnixIndexInput MemberwiseClone()
+ {
+ try
+ {
+ return new NativeUnixIndexInput(this);
+ }
+ catch (IOException ioe)
+ {
+ throw new Exception("IOException during clone: " + this, ioe);
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Store/WindowsDirectory.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Store/WindowsDirectory.cs b/src/Lucene.Net.Misc/Store/WindowsDirectory.cs
new file mode 100644
index 0000000..324a0dd
--- /dev/null
+++ b/src/Lucene.Net.Misc/Store/WindowsDirectory.cs
@@ -0,0 +1,181 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace org.apache.lucene.store
+{
+
+ /*
+ * 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.
+ */
+
+
+
+ /// <summary>
+ /// Native <seealso cref="Directory"/> implementation for Microsoft Windows.
+ /// <para>
+ /// Steps:
+ /// <ol>
+ /// <li>Compile the source code to create WindowsDirectory.dll:
+ /// <blockquote>
+ /// c:\mingw\bin\g++ -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at
+ /// -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -static-libgcc
+ /// -static-libstdc++ -shared WindowsDirectory.cpp -o WindowsDirectory.dll
+ /// </blockquote>
+ /// For 64-bit JREs, use mingw64, with the -m64 option.
+ /// <li>Put WindowsDirectory.dll into some directory in your windows PATH
+ /// <li>Open indexes with WindowsDirectory and use it.
+ /// </ol>
+ /// </para>
+ /// @lucene.experimental
+ /// </summary>
+ public class WindowsDirectory : FSDirectory
+ {
+ private const int DEFAULT_BUFFERSIZE = 4096; // default pgsize on ia32/amd64
+
+ static WindowsDirectory()
+ {
+//JAVA TO C# CONVERTER TODO TASK: The library is specified in the 'DllImport' attribute for .NET:
+// System.loadLibrary("WindowsDirectory");
+ }
+
+ /// <summary>
+ /// Create a new WindowsDirectory for the named location.
+ /// </summary>
+ /// <param name="path"> the path of the directory </param>
+ /// <param name="lockFactory"> the lock factory to use, or null for the default
+ /// (<seealso cref="NativeFSLockFactory"/>); </param>
+ /// <exception cref="IOException"> If there is a low-level I/O error </exception>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public WindowsDirectory(java.io.File path, LockFactory lockFactory) throws java.io.IOException
+ public WindowsDirectory(File path, LockFactory lockFactory) : base(path, lockFactory)
+ {
+ }
+
+ /// <summary>
+ /// Create a new WindowsDirectory for the named location and <seealso cref="NativeFSLockFactory"/>.
+ /// </summary>
+ /// <param name="path"> the path of the directory </param>
+ /// <exception cref="IOException"> If there is a low-level I/O error </exception>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public WindowsDirectory(java.io.File path) throws java.io.IOException
+ public WindowsDirectory(File path) : base(path, null)
+ {
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public IndexInput openInput(String name, IOContext context) throws java.io.IOException
+ public override IndexInput openInput(string name, IOContext context)
+ {
+ ensureOpen();
+ return new WindowsIndexInput(new File(Directory, name), Math.Max(BufferedIndexInput.bufferSize(context), DEFAULT_BUFFERSIZE));
+ }
+
+ internal class WindowsIndexInput : BufferedIndexInput
+ {
+ internal readonly long fd;
+ internal readonly long length_Renamed;
+ internal bool isClone;
+ internal bool isOpen;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public WindowsIndexInput(java.io.File file, int bufferSize) throws java.io.IOException
+ public WindowsIndexInput(File file, int bufferSize) : base("WindowsIndexInput(path=\"" + file.Path + "\")", bufferSize)
+ {
+ fd = WindowsDirectory.open(file.Path);
+ length_Renamed = WindowsDirectory.length(fd);
+ isOpen = true;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override protected void readInternal(byte[] b, int offset, int length) throws java.io.IOException
+ protected internal override void readInternal(sbyte[] b, int offset, int length)
+ {
+ int bytesRead;
+ try
+ {
+ bytesRead = WindowsDirectory.read(fd, b, offset, length, FilePointer);
+ }
+ catch (IOException ioe)
+ {
+ throw new IOException(ioe.Message + ": " + this, ioe);
+ }
+
+ if (bytesRead != length)
+ {
+ throw new EOFException("read past EOF: " + this);
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override protected void seekInternal(long pos) throws java.io.IOException
+ protected internal override void seekInternal(long pos)
+ {
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public synchronized void close() throws java.io.IOException
+ public override void close()
+ {
+ lock (this)
+ {
+ // NOTE: we synchronize and track "isOpen" because Lucene sometimes closes IIs twice!
+ if (!isClone && isOpen)
+ {
+ WindowsDirectory.close(fd);
+ isOpen = false;
+ }
+ }
+ }
+
+ public override long length()
+ {
+ return length_Renamed;
+ }
+
+ public override WindowsIndexInput clone()
+ {
+ WindowsIndexInput clone = (WindowsIndexInput)base.clone();
+ clone.isClone = true;
+ return clone;
+ }
+ }
+
+ /// <summary>
+ /// Opens a handle to a file. </summary>
+//JAVA TO C# CONVERTER TODO TASK: Replace 'unknown' with the appropriate dll name:
+ [DllImport("unknown")]
+ private static extern long open(string filename);
+
+ /// <summary>
+ /// Reads data from a file at pos into bytes </summary>
+//JAVA TO C# CONVERTER TODO TASK: Replace 'unknown' with the appropriate dll name:
+ [DllImport("unknown")]
+ private static extern int read(long fd, sbyte[] bytes, int offset, int length, long pos);
+
+ /// <summary>
+ /// Closes a handle to a file </summary>
+//JAVA TO C# CONVERTER TODO TASK: Replace 'unknown' with the appropriate dll name:
+ [DllImport("unknown")]
+ private static extern void close(long fd);
+
+ /// <summary>
+ /// Returns the length of a file </summary>
+//JAVA TO C# CONVERTER TODO TASK: Replace 'unknown' with the appropriate dll name:
+ [DllImport("unknown")]
+ private static extern long length(long fd);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Util/Fst/ListOfOutputs.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Util/Fst/ListOfOutputs.cs b/src/Lucene.Net.Misc/Util/Fst/ListOfOutputs.cs
new file mode 100644
index 0000000..e4660a6
--- /dev/null
+++ b/src/Lucene.Net.Misc/Util/Fst/ListOfOutputs.cs
@@ -0,0 +1,246 @@
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+namespace org.apache.lucene.util.fst
+{
+
+ /*
+ * 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 DataInput = org.apache.lucene.store.DataInput;
+ using DataOutput = org.apache.lucene.store.DataOutput;
+
+ /// <summary>
+ /// Wraps another Outputs implementation and encodes one or
+ /// more of its output values. You can use this when a single
+ /// input may need to map to more than one output,
+ /// maintaining order: pass the same input with a different
+ /// output by calling <seealso cref="Builder#add(IntsRef,Object)"/> multiple
+ /// times. The builder will then combine the outputs using
+ /// the <seealso cref="Outputs#merge(Object,Object)"/> method.
+ ///
+ /// <para>The resulting FST may not be minimal when an input has
+ /// more than one output, as this requires pushing all
+ /// multi-output values to a final state.
+ ///
+ /// </para>
+ /// <para>NOTE: the only way to create multiple outputs is to
+ /// add the same input to the FST multiple times in a row. This is
+ /// how the FST maps a single input to multiple outputs (e.g. you
+ /// cannot pass a List<Object> to <seealso cref="Builder#add"/>). If
+ /// your outputs are longs, and you need at most 2, then use
+ /// <seealso cref="UpToTwoPositiveIntOutputs"/> instead since it stores
+ /// the outputs more compactly (by stealing a bit from each
+ /// long value).
+ ///
+ /// </para>
+ /// <para>NOTE: this cannot wrap itself (ie you cannot make an
+ /// FST with List<List<Object>> outputs using this).
+ ///
+ /// @lucene.experimental
+ /// </para>
+ /// </summary>
+
+
+ // NOTE: i think we could get a more compact FST if, instead
+ // of adding the same input multiple times with a different
+ // output each time, we added it only once with a
+ // pre-constructed List<T> output. This way the "multiple
+ // values" is fully opaque to the Builder/FST. It would
+ // require implementing the full algebra using set
+ // arithmetic (I think?); maybe SetOfOutputs is a good name.
+
+//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
+//ORIGINAL LINE: @SuppressWarnings("unchecked") public final class ListOfOutputs<T> extends Outputs<Object>
+ public sealed class ListOfOutputs<T> : Outputs<object>
+ {
+
+ private readonly Outputs<T> outputs;
+
+ public ListOfOutputs(Outputs<T> outputs)
+ {
+ this.outputs = outputs;
+ }
+
+ public override object common(object output1, object output2)
+ {
+ // These will never be a list:
+ return outputs.common((T) output1, (T) output2);
+ }
+
+ public override object subtract(object @object, object inc)
+ {
+ // These will never be a list:
+ return outputs.subtract((T) @object, (T) inc);
+ }
+
+ public override object add(object prefix, object output)
+ {
+ Debug.Assert(!(prefix is IList));
+ if (!(output is IList))
+ {
+ return outputs.add((T) prefix, (T) output);
+ }
+ else
+ {
+ IList<T> outputList = (IList<T>) output;
+ IList<T> addedList = new List<T>(outputList.Count);
+ foreach (T _output in outputList)
+ {
+ addedList.Add(outputs.add((T) prefix, _output));
+ }
+ return addedList;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void write(Object output, org.apache.lucene.store.DataOutput out) throws java.io.IOException
+ public override void write(object output, DataOutput @out)
+ {
+ Debug.Assert(!(output is IList));
+ outputs.write((T) output, @out);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void writeFinalOutput(Object output, org.apache.lucene.store.DataOutput out) throws java.io.IOException
+ public override void writeFinalOutput(object output, DataOutput @out)
+ {
+ if (!(output is IList))
+ {
+ @out.writeVInt(1);
+ outputs.write((T) output, @out);
+ }
+ else
+ {
+ IList<T> outputList = (IList<T>) output;
+ @out.writeVInt(outputList.Count);
+ foreach (T eachOutput in outputList)
+ {
+ outputs.write(eachOutput, @out);
+ }
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Object read(org.apache.lucene.store.DataInput in) throws java.io.IOException
+ public override object read(DataInput @in)
+ {
+ return outputs.read(@in);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Object readFinalOutput(org.apache.lucene.store.DataInput in) throws java.io.IOException
+ public override object readFinalOutput(DataInput @in)
+ {
+ int count = @in.readVInt();
+ if (count == 1)
+ {
+ return outputs.read(@in);
+ }
+ else
+ {
+ IList<T> outputList = new List<T>(count);
+ for (int i = 0;i < count;i++)
+ {
+ outputList.Add(outputs.read(@in));
+ }
+ return outputList;
+ }
+ }
+
+ public override object NoOutput
+ {
+ get
+ {
+ return outputs.NoOutput;
+ }
+ }
+
+ public override string outputToString(object output)
+ {
+ if (!(output is IList))
+ {
+ return outputs.outputToString((T) output);
+ }
+ else
+ {
+ IList<T> outputList = (IList<T>) output;
+
+ StringBuilder b = new StringBuilder();
+ b.Append('[');
+
+ for (int i = 0;i < outputList.Count;i++)
+ {
+ if (i > 0)
+ {
+ b.Append(", ");
+ }
+ b.Append(outputs.outputToString(outputList[i]));
+ }
+ b.Append(']');
+ return b.ToString();
+ }
+ }
+
+ public override object merge(object first, object second)
+ {
+ IList<T> outputList = new List<T>();
+ if (!(first is IList))
+ {
+ outputList.Add((T) first);
+ }
+ else
+ {
+ outputList.AddRange((IList<T>) first);
+ }
+ if (!(second is IList))
+ {
+ outputList.Add((T) second);
+ }
+ else
+ {
+ outputList.AddRange((IList<T>) second);
+ }
+ //System.out.println("MERGE: now " + outputList.size() + " first=" + outputToString(first) + " second=" + outputToString(second));
+ //System.out.println(" return " + outputToString(outputList));
+ return outputList;
+ }
+
+ public override string ToString()
+ {
+ return "OneOrMoreOutputs(" + outputs + ")";
+ }
+
+ public IList<T> asList(object output)
+ {
+ if (!(output is IList))
+ {
+ IList<T> result = new List<T>(1);
+ result.Add((T) output);
+ return result;
+ }
+ else
+ {
+ return (IList<T>) output;
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Util/Fst/UpToTwoPositiveIntOutputs.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Util/Fst/UpToTwoPositiveIntOutputs.cs b/src/Lucene.Net.Misc/Util/Fst/UpToTwoPositiveIntOutputs.cs
new file mode 100644
index 0000000..8302127
--- /dev/null
+++ b/src/Lucene.Net.Misc/Util/Fst/UpToTwoPositiveIntOutputs.cs
@@ -0,0 +1,328 @@
+using System;
+using System.Diagnostics;
+
+namespace org.apache.lucene.util.fst
+{
+
+ /*
+ * 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 DataInput = org.apache.lucene.store.DataInput;
+ using DataOutput = org.apache.lucene.store.DataOutput;
+
+ /// <summary>
+ /// An FST <seealso cref="Outputs"/> implementation where each output
+ /// is one or two non-negative long values. If it's a
+ /// single output, Long is returned; else, TwoLongs. Order
+ /// is preserved in the TwoLongs case, ie .first is the first
+ /// input/output added to Builder, and .second is the
+ /// second. You cannot store 0 output with this (that's
+ /// reserved to mean "no output")!
+ ///
+ /// <para>NOTE: the only way to create a TwoLongs output is to
+ /// add the same input to the FST twice in a row. This is
+ /// how the FST maps a single input to two outputs (e.g. you
+ /// cannot pass a TwoLongs to <seealso cref="Builder#add"/>. If you
+ /// need more than two then use <seealso cref="ListOfOutputs"/>, but if
+ /// you only have at most 2 then this implementation will
+ /// require fewer bytes as it steals one bit from each long
+ /// value.
+ ///
+ /// </para>
+ /// <para>NOTE: the resulting FST is not guaranteed to be minimal!
+ /// See <seealso cref="Builder"/>.
+ ///
+ /// @lucene.experimental
+ /// </para>
+ /// </summary>
+
+ public sealed class UpToTwoPositiveIntOutputs : Outputs<object>
+ {
+
+ /// <summary>
+ /// Holds two long outputs. </summary>
+ public sealed class TwoLongs
+ {
+ public readonly long first;
+ public readonly long second;
+
+ public TwoLongs(long first, long second)
+ {
+ this.first = first;
+ this.second = second;
+ Debug.Assert(first >= 0);
+ Debug.Assert(second >= 0);
+ }
+
+ public override string ToString()
+ {
+ return "TwoLongs:" + first + "," + second;
+ }
+
+ public override bool Equals(object _other)
+ {
+ if (_other is TwoLongs)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final TwoLongs other = (TwoLongs) _other;
+ TwoLongs other = (TwoLongs) _other;
+ return first == other.first && second == other.second;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return (int)((first ^ ((long)((ulong)first >> 32))) ^ (second ^ (second >> 32)));
+ }
+ }
+
+ private static readonly long? NO_OUTPUT = new long?(0);
+
+ private readonly bool doShare;
+
+ private static readonly UpToTwoPositiveIntOutputs singletonShare = new UpToTwoPositiveIntOutputs(true);
+ private static readonly UpToTwoPositiveIntOutputs singletonNoShare = new UpToTwoPositiveIntOutputs(false);
+
+ private UpToTwoPositiveIntOutputs(bool doShare)
+ {
+ this.doShare = doShare;
+ }
+
+ public static UpToTwoPositiveIntOutputs getSingleton(bool doShare)
+ {
+ return doShare ? singletonShare : singletonNoShare;
+ }
+
+ public long? get(long v)
+ {
+ if (v == 0)
+ {
+ return NO_OUTPUT;
+ }
+ else
+ {
+ return Convert.ToInt64(v);
+ }
+ }
+
+ public TwoLongs get(long first, long second)
+ {
+ return new TwoLongs(first, second);
+ }
+
+ public override long? common(object _output1, object _output2)
+ {
+ Debug.Assert(valid(_output1, false));
+ Debug.Assert(valid(_output2, false));
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Long output1 = (Long) _output1;
+ long? output1 = (long?) _output1;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Long output2 = (Long) _output2;
+ long? output2 = (long?) _output2;
+ if (output1 == NO_OUTPUT || output2 == NO_OUTPUT)
+ {
+ return NO_OUTPUT;
+ }
+ else if (doShare)
+ {
+ Debug.Assert(output1 > 0);
+ Debug.Assert(output2 > 0);
+ return Math.Min(output1, output2);
+ }
+ else if (output1.Equals(output2))
+ {
+ return output1;
+ }
+ else
+ {
+ return NO_OUTPUT;
+ }
+ }
+
+ public override long? subtract(object _output, object _inc)
+ {
+ Debug.Assert(valid(_output, false));
+ Debug.Assert(valid(_inc, false));
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Long output = (Long) _output;
+ long? output = (long?) _output;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Long inc = (Long) _inc;
+ long? inc = (long?) _inc;
+ Debug.Assert(output >= inc);
+
+ if (inc == NO_OUTPUT)
+ {
+ return output;
+ }
+ else if (output.Equals(inc))
+ {
+ return NO_OUTPUT;
+ }
+ else
+ {
+ return output - inc;
+ }
+ }
+
+ public override object add(object _prefix, object _output)
+ {
+ Debug.Assert(valid(_prefix, false));
+ Debug.Assert(valid(_output, true));
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Long prefix = (Long) _prefix;
+ long? prefix = (long?) _prefix;
+ if (_output is long?)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Long output = (Long) _output;
+ long? output = (long?) _output;
+ if (prefix == NO_OUTPUT)
+ {
+ return output;
+ }
+ else if (output == NO_OUTPUT)
+ {
+ return prefix;
+ }
+ else
+ {
+ return prefix + output;
+ }
+ }
+ else
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final TwoLongs output = (TwoLongs) _output;
+ TwoLongs output = (TwoLongs) _output;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long v = prefix;
+ long v = prefix.Value;
+ return new TwoLongs(output.first + v, output.second + v);
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void write(Object _output, org.apache.lucene.store.DataOutput out) throws java.io.IOException
+ public override void write(object _output, DataOutput @out)
+ {
+ Debug.Assert(valid(_output, true));
+ if (_output is long?)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Long output = (Long) _output;
+ long? output = (long?) _output;
+ @out.writeVLong(output << 1);
+ }
+ else
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final TwoLongs output = (TwoLongs) _output;
+ TwoLongs output = (TwoLongs) _output;
+ @out.writeVLong((output.first << 1) | 1);
+ @out.writeVLong(output.second);
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Object read(org.apache.lucene.store.DataInput in) throws java.io.IOException
+ public override object read(DataInput @in)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long code = in.readVLong();
+ long code = @in.readVLong();
+ if ((code & 1) == 0)
+ {
+ // single long
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long v = code >>> 1;
+ long v = (long)((ulong)code >> 1);
+ if (v == 0)
+ {
+ return NO_OUTPUT;
+ }
+ else
+ {
+ return Convert.ToInt64(v);
+ }
+ }
+ else
+ {
+ // two longs
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long first = code >>> 1;
+ long first = (long)((ulong)code >> 1);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long second = in.readVLong();
+ long second = @in.readVLong();
+ return new TwoLongs(first, second);
+ }
+ }
+
+ private bool valid(long? o)
+ {
+ Debug.Assert(o != null);
+ Debug.Assert(o is long?);
+ Debug.Assert(o == NO_OUTPUT || o > 0);
+ return true;
+ }
+
+ // Used only by assert
+ private bool valid(object _o, bool allowDouble)
+ {
+ if (!allowDouble)
+ {
+ Debug.Assert(_o is long?);
+ return valid((long?) _o);
+ }
+ else if (_o is TwoLongs)
+ {
+ return true;
+ }
+ else
+ {
+ return valid((long?) _o);
+ }
+ }
+
+ public override object NoOutput
+ {
+ get
+ {
+ return NO_OUTPUT;
+ }
+ }
+
+ public override string outputToString(object output)
+ {
+ return output.ToString();
+ }
+
+ public override object merge(object first, object second)
+ {
+ Debug.Assert(valid(first, false));
+ Debug.Assert(valid(second, false));
+ return new TwoLongs((long?) first, (long?) second);
+ }
+ }
+
+}
\ No newline at end of file
[09/11] Skeleton porting of Lucene.Net.Misc
Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Index/Sorter/SortingAtomicReader.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Index/Sorter/SortingAtomicReader.cs b/src/Lucene.Net.Misc/Index/Sorter/SortingAtomicReader.cs
new file mode 100644
index 0000000..eb87148
--- /dev/null
+++ b/src/Lucene.Net.Misc/Index/Sorter/SortingAtomicReader.cs
@@ -0,0 +1,1081 @@
+using System;
+using System.Diagnostics;
+
+namespace org.apache.lucene.index.sorter
+{
+
+ /*
+ * 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 IndexOptions = org.apache.lucene.index.FieldInfo.IndexOptions;
+ using DocIdSetIterator = org.apache.lucene.search.DocIdSetIterator;
+ using Sort = org.apache.lucene.search.Sort;
+ using IndexInput = org.apache.lucene.store.IndexInput;
+ using IndexOutput = org.apache.lucene.store.IndexOutput;
+ using RAMFile = org.apache.lucene.store.RAMFile;
+ using RAMInputStream = org.apache.lucene.store.RAMInputStream;
+ using RAMOutputStream = org.apache.lucene.store.RAMOutputStream;
+ using ArrayUtil = org.apache.lucene.util.ArrayUtil;
+ using Bits = org.apache.lucene.util.Bits;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+ using TimSorter = org.apache.lucene.util.TimSorter;
+ using CompiledAutomaton = org.apache.lucene.util.automaton.CompiledAutomaton;
+
+ /// <summary>
+ /// An <seealso cref="AtomicReader"/> which supports sorting documents by a given
+ /// <seealso cref="Sort"/>. You can use this class to sort an index as follows:
+ ///
+ /// <pre class="prettyprint">
+ /// IndexWriter writer; // writer to which the sorted index will be added
+ /// DirectoryReader reader; // reader on the input index
+ /// Sort sort; // determines how the documents are sorted
+ /// AtomicReader sortingReader = SortingAtomicReader.wrap(SlowCompositeReaderWrapper.wrap(reader), sort);
+ /// writer.addIndexes(reader);
+ /// writer.close();
+ /// reader.close();
+ /// </pre>
+ ///
+ /// @lucene.experimental
+ /// </summary>
+ public class SortingAtomicReader : FilterAtomicReader
+ {
+
+ private class SortingFields : FilterFields
+ {
+
+ internal readonly Sorter.DocMap docMap;
+ internal readonly FieldInfos infos;
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public SortingFields(final org.apache.lucene.index.Fields in, org.apache.lucene.index.FieldInfos infos, Sorter.DocMap docMap)
+ public SortingFields(Fields @in, FieldInfos infos, Sorter.DocMap docMap) : base(@in)
+ {
+ this.docMap = docMap;
+ this.infos = infos;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.Terms terms(final String field) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ public override Terms terms(string field)
+ {
+ Terms terms = @in.terms(field);
+ if (terms == null)
+ {
+ return null;
+ }
+ else
+ {
+ return new SortingTerms(terms, infos.fieldInfo(field).IndexOptions, docMap);
+ }
+ }
+
+ }
+
+ private class SortingTerms : FilterTerms
+ {
+
+ internal readonly Sorter.DocMap docMap;
+ internal readonly IndexOptions indexOptions;
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public SortingTerms(final org.apache.lucene.index.Terms in, org.apache.lucene.index.FieldInfo.IndexOptions indexOptions, final Sorter.DocMap docMap)
+ public SortingTerms(Terms @in, IndexOptions indexOptions, Sorter.DocMap docMap) : base(@in)
+ {
+ this.docMap = docMap;
+ this.indexOptions = indexOptions;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.TermsEnum iterator(final org.apache.lucene.index.TermsEnum reuse) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ public override TermsEnum iterator(TermsEnum reuse)
+ {
+ return new SortingTermsEnum(@in.iterator(reuse), docMap, indexOptions);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.TermsEnum intersect(org.apache.lucene.util.automaton.CompiledAutomaton compiled, org.apache.lucene.util.BytesRef startTerm) throws java.io.IOException
+ public override TermsEnum intersect(CompiledAutomaton compiled, BytesRef startTerm)
+ {
+ return new SortingTermsEnum(@in.intersect(compiled, startTerm), docMap, indexOptions);
+ }
+
+ }
+
+ private class SortingTermsEnum : FilterTermsEnum
+ {
+
+ internal readonly Sorter.DocMap docMap; // pkg-protected to avoid synthetic accessor methods
+ internal readonly IndexOptions indexOptions;
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public SortingTermsEnum(final org.apache.lucene.index.TermsEnum in, Sorter.DocMap docMap, org.apache.lucene.index.FieldInfo.IndexOptions indexOptions)
+ public SortingTermsEnum(TermsEnum @in, Sorter.DocMap docMap, IndexOptions indexOptions) : base(@in)
+ {
+ this.docMap = docMap;
+ this.indexOptions = indexOptions;
+ }
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: org.apache.lucene.util.Bits newToOld(final org.apache.lucene.util.Bits liveDocs)
+ internal virtual Bits newToOld(Bits liveDocs)
+ {
+ if (liveDocs == null)
+ {
+ return null;
+ }
+ return new BitsAnonymousInnerClassHelper(this, liveDocs);
+ }
+
+ private class BitsAnonymousInnerClassHelper : Bits
+ {
+ private readonly SortingTermsEnum outerInstance;
+
+ private Bits liveDocs;
+
+ public BitsAnonymousInnerClassHelper(SortingTermsEnum outerInstance, Bits liveDocs)
+ {
+ this.outerInstance = outerInstance;
+ this.liveDocs = liveDocs;
+ }
+
+
+ public override bool get(int index)
+ {
+ return liveDocs.get(outerInstance.docMap.oldToNew(index));
+ }
+
+ public override int length()
+ {
+ return liveDocs.length();
+ }
+
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.DocsEnum docs(org.apache.lucene.util.Bits liveDocs, org.apache.lucene.index.DocsEnum reuse, final int flags) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ public override DocsEnum docs(Bits liveDocs, DocsEnum reuse, int flags)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.DocsEnum inReuse;
+ DocsEnum inReuse;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final SortingDocsEnum wrapReuse;
+ SortingDocsEnum wrapReuse;
+ if (reuse != null && reuse is SortingDocsEnum)
+ {
+ // if we're asked to reuse the given DocsEnum and it is Sorting, return
+ // the wrapped one, since some Codecs expect it.
+ wrapReuse = (SortingDocsEnum) reuse;
+ inReuse = wrapReuse.Wrapped;
+ }
+ else
+ {
+ wrapReuse = null;
+ inReuse = reuse;
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.DocsEnum inDocs = in.docs(newToOld(liveDocs), inReuse, flags);
+ DocsEnum inDocs = @in.docs(newToOld(liveDocs), inReuse, flags);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final boolean withFreqs = indexOptions.compareTo(org.apache.lucene.index.FieldInfo.IndexOptions.DOCS_AND_FREQS) >=0 && (flags & org.apache.lucene.index.DocsEnum.FLAG_FREQS) != 0;
+ bool withFreqs = indexOptions.compareTo(IndexOptions.DOCS_AND_FREQS) >= 0 && (flags & DocsEnum.FLAG_FREQS) != 0;
+ return new SortingDocsEnum(docMap.size(), wrapReuse, inDocs, withFreqs, docMap);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.DocsAndPositionsEnum docsAndPositions(org.apache.lucene.util.Bits liveDocs, org.apache.lucene.index.DocsAndPositionsEnum reuse, final int flags) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ public override DocsAndPositionsEnum docsAndPositions(Bits liveDocs, DocsAndPositionsEnum reuse, int flags)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.DocsAndPositionsEnum inReuse;
+ DocsAndPositionsEnum inReuse;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final SortingDocsAndPositionsEnum wrapReuse;
+ SortingDocsAndPositionsEnum wrapReuse;
+ if (reuse != null && reuse is SortingDocsAndPositionsEnum)
+ {
+ // if we're asked to reuse the given DocsEnum and it is Sorting, return
+ // the wrapped one, since some Codecs expect it.
+ wrapReuse = (SortingDocsAndPositionsEnum) reuse;
+ inReuse = wrapReuse.Wrapped;
+ }
+ else
+ {
+ wrapReuse = null;
+ inReuse = reuse;
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.DocsAndPositionsEnum inDocsAndPositions = in.docsAndPositions(newToOld(liveDocs), inReuse, flags);
+ DocsAndPositionsEnum inDocsAndPositions = @in.docsAndPositions(newToOld(liveDocs), inReuse, flags);
+ if (inDocsAndPositions == null)
+ {
+ return null;
+ }
+
+ // we ignore the fact that offsets may be stored but not asked for,
+ // since this code is expected to be used during addIndexes which will
+ // ask for everything. if that assumption changes in the future, we can
+ // factor in whether 'flags' says offsets are not required.
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final boolean storeOffsets = indexOptions.compareTo(org.apache.lucene.index.FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0;
+ bool storeOffsets = indexOptions.compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0;
+ return new SortingDocsAndPositionsEnum(docMap.size(), wrapReuse, inDocsAndPositions, docMap, storeOffsets);
+ }
+
+ }
+
+ private class SortingBinaryDocValues : BinaryDocValues
+ {
+
+ internal readonly BinaryDocValues @in;
+ internal readonly Sorter.DocMap docMap;
+
+ internal SortingBinaryDocValues(BinaryDocValues @in, Sorter.DocMap docMap)
+ {
+ this.@in = @in;
+ this.docMap = docMap;
+ }
+
+ public override void get(int docID, BytesRef result)
+ {
+ @in.get(docMap.newToOld(docID), result);
+ }
+ }
+
+ private class SortingNumericDocValues : NumericDocValues
+ {
+
+ internal readonly NumericDocValues @in;
+ internal readonly Sorter.DocMap docMap;
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public SortingNumericDocValues(final org.apache.lucene.index.NumericDocValues in, Sorter.DocMap docMap)
+ public SortingNumericDocValues(NumericDocValues @in, Sorter.DocMap docMap)
+ {
+ this.@in = @in;
+ this.docMap = docMap;
+ }
+
+ public override long get(int docID)
+ {
+ return @in.get(docMap.newToOld(docID));
+ }
+ }
+
+ private class SortingBits : Bits
+ {
+
+ internal readonly Bits @in;
+ internal readonly Sorter.DocMap docMap;
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public SortingBits(final org.apache.lucene.util.Bits in, Sorter.DocMap docMap)
+ public SortingBits(Bits @in, Sorter.DocMap docMap)
+ {
+ this.@in = @in;
+ this.docMap = docMap;
+ }
+
+ public override bool get(int index)
+ {
+ return @in.get(docMap.newToOld(index));
+ }
+
+ public override int length()
+ {
+ return @in.length();
+ }
+ }
+
+ private class SortingSortedDocValues : SortedDocValues
+ {
+
+ internal readonly SortedDocValues @in;
+ internal readonly Sorter.DocMap docMap;
+
+ internal SortingSortedDocValues(SortedDocValues @in, Sorter.DocMap docMap)
+ {
+ this.@in = @in;
+ this.docMap = docMap;
+ }
+
+ public override int getOrd(int docID)
+ {
+ return @in.getOrd(docMap.newToOld(docID));
+ }
+
+ public override void lookupOrd(int ord, BytesRef result)
+ {
+ @in.lookupOrd(ord, result);
+ }
+
+ public override int ValueCount
+ {
+ get
+ {
+ return @in.ValueCount;
+ }
+ }
+
+ public override void get(int docID, BytesRef result)
+ {
+ @in.get(docMap.newToOld(docID), result);
+ }
+
+ public override int lookupTerm(BytesRef key)
+ {
+ return @in.lookupTerm(key);
+ }
+ }
+
+ private class SortingSortedSetDocValues : SortedSetDocValues
+ {
+
+ internal readonly SortedSetDocValues @in;
+ internal readonly Sorter.DocMap docMap;
+
+ internal SortingSortedSetDocValues(SortedSetDocValues @in, Sorter.DocMap docMap)
+ {
+ this.@in = @in;
+ this.docMap = docMap;
+ }
+
+ public override long nextOrd()
+ {
+ return @in.nextOrd();
+ }
+
+ public override int Document
+ {
+ set
+ {
+ @in.Document = docMap.newToOld(value);
+ }
+ }
+
+ public override void lookupOrd(long ord, BytesRef result)
+ {
+ @in.lookupOrd(ord, result);
+ }
+
+ public override long ValueCount
+ {
+ get
+ {
+ return @in.ValueCount;
+ }
+ }
+
+ public override long lookupTerm(BytesRef key)
+ {
+ return @in.lookupTerm(key);
+ }
+ }
+
+ internal class SortingDocsEnum : FilterDocsEnum
+ {
+
+ private sealed class DocFreqSorter : TimSorter
+ {
+
+ internal int[] docs;
+ internal int[] freqs;
+ internal readonly int[] tmpDocs;
+ internal int[] tmpFreqs;
+
+ public DocFreqSorter(int maxDoc) : base(maxDoc / 64)
+ {
+ this.tmpDocs = new int[maxDoc / 64];
+ }
+
+ public void reset(int[] docs, int[] freqs)
+ {
+ this.docs = docs;
+ this.freqs = freqs;
+ if (freqs != null && tmpFreqs == null)
+ {
+ tmpFreqs = new int[tmpDocs.Length];
+ }
+ }
+
+ protected internal override int compare(int i, int j)
+ {
+ return docs[i] - docs[j];
+ }
+
+ protected internal override void swap(int i, int j)
+ {
+ int tmpDoc = docs[i];
+ docs[i] = docs[j];
+ docs[j] = tmpDoc;
+
+ if (freqs != null)
+ {
+ int tmpFreq = freqs[i];
+ freqs[i] = freqs[j];
+ freqs[j] = tmpFreq;
+ }
+ }
+
+ protected internal override void copy(int src, int dest)
+ {
+ docs[dest] = docs[src];
+ if (freqs != null)
+ {
+ freqs[dest] = freqs[src];
+ }
+ }
+
+ protected internal override void save(int i, int len)
+ {
+ Array.Copy(docs, i, tmpDocs, 0, len);
+ if (freqs != null)
+ {
+ Array.Copy(freqs, i, tmpFreqs, 0, len);
+ }
+ }
+
+ protected internal override void restore(int i, int j)
+ {
+ docs[j] = tmpDocs[i];
+ if (freqs != null)
+ {
+ freqs[j] = tmpFreqs[i];
+ }
+ }
+
+ protected internal override int compareSaved(int i, int j)
+ {
+ return tmpDocs[i] - docs[j];
+ }
+ }
+
+ internal readonly int maxDoc;
+ internal readonly DocFreqSorter sorter;
+ internal int[] docs;
+ internal int[] freqs;
+ internal int docIt = -1;
+ internal readonly int upto;
+ internal readonly bool withFreqs;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: SortingDocsEnum(int maxDoc, SortingDocsEnum reuse, final org.apache.lucene.index.DocsEnum in, boolean withFreqs, final Sorter.DocMap docMap) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ internal SortingDocsEnum(int maxDoc, SortingDocsEnum reuse, DocsEnum @in, bool withFreqs, Sorter.DocMap docMap) : base(@in)
+ {
+ this.maxDoc = maxDoc;
+ this.withFreqs = withFreqs;
+ if (reuse != null)
+ {
+ if (reuse.maxDoc == maxDoc)
+ {
+ sorter = reuse.sorter;
+ }
+ else
+ {
+ sorter = new DocFreqSorter(maxDoc);
+ }
+ docs = reuse.docs;
+ freqs = reuse.freqs; // maybe null
+ }
+ else
+ {
+ docs = new int[64];
+ sorter = new DocFreqSorter(maxDoc);
+ }
+ docIt = -1;
+ int i = 0;
+ int doc;
+ if (withFreqs)
+ {
+ if (freqs == null || freqs.Length < docs.Length)
+ {
+ freqs = new int[docs.Length];
+ }
+ while ((doc = @in.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS)
+ {
+ if (i >= docs.Length)
+ {
+ docs = ArrayUtil.grow(docs, docs.Length + 1);
+ freqs = ArrayUtil.grow(freqs, freqs.Length + 1);
+ }
+ docs[i] = docMap.oldToNew(doc);
+ freqs[i] = @in.freq();
+ ++i;
+ }
+ }
+ else
+ {
+ freqs = null;
+ while ((doc = @in.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS)
+ {
+ if (i >= docs.Length)
+ {
+ docs = ArrayUtil.grow(docs, docs.Length + 1);
+ }
+ docs[i++] = docMap.oldToNew(doc);
+ }
+ }
+ // TimSort can save much time compared to other sorts in case of
+ // reverse sorting, or when sorting a concatenation of sorted readers
+ sorter.reset(docs, freqs);
+ sorter.sort(0, i);
+ upto = i;
+ }
+
+ // for testing
+ internal virtual bool reused(DocsEnum other)
+ {
+ if (other == null || !(other is SortingDocsEnum))
+ {
+ return false;
+ }
+ return docs == ((SortingDocsEnum) other).docs;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int advance(final int target) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ public override int advance(int target)
+ {
+ // need to support it for checkIndex, but in practice it won't be called, so
+ // don't bother to implement efficiently for now.
+ return slowAdvance(target);
+ }
+
+ public override int docID()
+ {
+ return docIt < 0 ? - 1 : docIt >= upto ? NO_MORE_DOCS : docs[docIt];
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int freq() throws java.io.IOException
+ public override int freq()
+ {
+ return withFreqs && docIt < upto ? freqs[docIt] : 1;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int nextDoc() throws java.io.IOException
+ public override int nextDoc()
+ {
+ if (++docIt >= upto)
+ {
+ return NO_MORE_DOCS;
+ }
+ return docs[docIt];
+ }
+
+ /// <summary>
+ /// Returns the wrapped <seealso cref="DocsEnum"/>. </summary>
+ internal virtual DocsEnum Wrapped
+ {
+ get
+ {
+ return @in;
+ }
+ }
+ }
+
+ internal class SortingDocsAndPositionsEnum : FilterDocsAndPositionsEnum
+ {
+
+ /// <summary>
+ /// A <seealso cref="TimSorter"/> which sorts two parallel arrays of doc IDs and
+ /// offsets in one go. Everytime a doc ID is 'swapped', its correponding offset
+ /// is swapped too.
+ /// </summary>
+ private sealed class DocOffsetSorter : TimSorter
+ {
+
+ internal int[] docs;
+ internal long[] offsets;
+ internal readonly int[] tmpDocs;
+ internal readonly long[] tmpOffsets;
+
+ public DocOffsetSorter(int maxDoc) : base(maxDoc / 64)
+ {
+ this.tmpDocs = new int[maxDoc / 64];
+ this.tmpOffsets = new long[maxDoc / 64];
+ }
+
+ public void reset(int[] docs, long[] offsets)
+ {
+ this.docs = docs;
+ this.offsets = offsets;
+ }
+
+ protected internal override int compare(int i, int j)
+ {
+ return docs[i] - docs[j];
+ }
+
+ protected internal override void swap(int i, int j)
+ {
+ int tmpDoc = docs[i];
+ docs[i] = docs[j];
+ docs[j] = tmpDoc;
+
+ long tmpOffset = offsets[i];
+ offsets[i] = offsets[j];
+ offsets[j] = tmpOffset;
+ }
+
+ protected internal override void copy(int src, int dest)
+ {
+ docs[dest] = docs[src];
+ offsets[dest] = offsets[src];
+ }
+
+ protected internal override void save(int i, int len)
+ {
+ Array.Copy(docs, i, tmpDocs, 0, len);
+ Array.Copy(offsets, i, tmpOffsets, 0, len);
+ }
+
+ protected internal override void restore(int i, int j)
+ {
+ docs[j] = tmpDocs[i];
+ offsets[j] = tmpOffsets[i];
+ }
+
+ protected internal override int compareSaved(int i, int j)
+ {
+ return tmpDocs[i] - docs[j];
+ }
+ }
+
+ internal readonly int maxDoc;
+ internal readonly DocOffsetSorter sorter;
+ internal int[] docs;
+ internal long[] offsets;
+ internal readonly int upto;
+
+ internal readonly IndexInput postingInput;
+ internal readonly bool storeOffsets;
+
+ internal int docIt = -1;
+ internal int pos;
+ internal int startOffset_Renamed = -1;
+ internal int endOffset_Renamed = -1;
+ internal readonly BytesRef payload;
+ internal int currFreq;
+
+ internal readonly RAMFile file;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: SortingDocsAndPositionsEnum(int maxDoc, SortingDocsAndPositionsEnum reuse, final org.apache.lucene.index.DocsAndPositionsEnum in, Sorter.DocMap docMap, boolean storeOffsets) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ internal SortingDocsAndPositionsEnum(int maxDoc, SortingDocsAndPositionsEnum reuse, DocsAndPositionsEnum @in, Sorter.DocMap docMap, bool storeOffsets) : base(@in)
+ {
+ this.maxDoc = maxDoc;
+ this.storeOffsets = storeOffsets;
+ if (reuse != null)
+ {
+ docs = reuse.docs;
+ offsets = reuse.offsets;
+ payload = reuse.payload;
+ file = reuse.file;
+ if (reuse.maxDoc == maxDoc)
+ {
+ sorter = reuse.sorter;
+ }
+ else
+ {
+ sorter = new DocOffsetSorter(maxDoc);
+ }
+ }
+ else
+ {
+ docs = new int[32];
+ offsets = new long[32];
+ payload = new BytesRef(32);
+ file = new RAMFile();
+ sorter = new DocOffsetSorter(maxDoc);
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.store.IndexOutput out = new org.apache.lucene.store.RAMOutputStream(file);
+ IndexOutput @out = new RAMOutputStream(file);
+ int doc;
+ int i = 0;
+ while ((doc = @in.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS)
+ {
+ if (i == docs.Length)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int newLength = org.apache.lucene.util.ArrayUtil.oversize(i + 1, 4);
+ int newLength = ArrayUtil.oversize(i + 1, 4);
+ docs = Arrays.copyOf(docs, newLength);
+ offsets = Arrays.copyOf(offsets, newLength);
+ }
+ docs[i] = docMap.oldToNew(doc);
+ offsets[i] = @out.FilePointer;
+ addPositions(@in, @out);
+ i++;
+ }
+ upto = i;
+ sorter.reset(docs, offsets);
+ sorter.sort(0, upto);
+ @out.close();
+ this.postingInput = new RAMInputStream("", file);
+ }
+
+ // for testing
+ internal virtual bool reused(DocsAndPositionsEnum other)
+ {
+ if (other == null || !(other is SortingDocsAndPositionsEnum))
+ {
+ return false;
+ }
+ return docs == ((SortingDocsAndPositionsEnum) other).docs;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private void addPositions(final org.apache.lucene.index.DocsAndPositionsEnum in, final org.apache.lucene.store.IndexOutput out) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ internal virtual void addPositions(DocsAndPositionsEnum @in, IndexOutput @out)
+ {
+ int freq = @in.freq();
+ @out.writeVInt(freq);
+ int previousPosition = 0;
+ int previousEndOffset = 0;
+ for (int i = 0; i < freq; i++)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int pos = in.nextPosition();
+ int pos = @in.nextPosition();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.BytesRef payload = in.getPayload();
+ BytesRef payload = @in.Payload;
+ // The low-order bit of token is set only if there is a payload, the
+ // previous bits are the delta-encoded position.
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int token = (pos - previousPosition) << 1 | (payload == null ? 0 : 1);
+ int token = (pos - previousPosition) << 1 | (payload == null ? 0 : 1);
+ @out.writeVInt(token);
+ previousPosition = pos;
+ if (storeOffsets) // don't encode offsets if they are not stored
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int startOffset = in.startOffset();
+ int startOffset = @in.startOffset();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int endOffset = in.endOffset();
+ int endOffset = @in.endOffset();
+ @out.writeVInt(startOffset - previousEndOffset);
+ @out.writeVInt(endOffset - startOffset);
+ previousEndOffset = endOffset;
+ }
+ if (payload != null)
+ {
+ @out.writeVInt(payload.length);
+ @out.writeBytes(payload.bytes, payload.offset, payload.length);
+ }
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int advance(final int target) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ public override int advance(int target)
+ {
+ // need to support it for checkIndex, but in practice it won't be called, so
+ // don't bother to implement efficiently for now.
+ return slowAdvance(target);
+ }
+
+ public override int docID()
+ {
+ return docIt < 0 ? - 1 : docIt >= upto ? NO_MORE_DOCS : docs[docIt];
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int endOffset() throws java.io.IOException
+ public override int endOffset()
+ {
+ return endOffset_Renamed;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int freq() throws java.io.IOException
+ public override int freq()
+ {
+ return currFreq;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.util.BytesRef getPayload() throws java.io.IOException
+ public override BytesRef Payload
+ {
+ get
+ {
+ return payload.length == 0 ? null : payload;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int nextDoc() throws java.io.IOException
+ public override int nextDoc()
+ {
+ if (++docIt >= upto)
+ {
+ return DocIdSetIterator.NO_MORE_DOCS;
+ }
+ postingInput.seek(offsets[docIt]);
+ currFreq = postingInput.readVInt();
+ // reset variables used in nextPosition
+ pos = 0;
+ endOffset_Renamed = 0;
+ return docs[docIt];
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int nextPosition() throws java.io.IOException
+ public override int nextPosition()
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int token = postingInput.readVInt();
+ int token = postingInput.readVInt();
+ pos += (int)((uint)token >> 1);
+ if (storeOffsets)
+ {
+ startOffset_Renamed = endOffset_Renamed + postingInput.readVInt();
+ endOffset_Renamed = startOffset_Renamed + postingInput.readVInt();
+ }
+ if ((token & 1) != 0)
+ {
+ payload.offset = 0;
+ payload.length = postingInput.readVInt();
+ if (payload.length > payload.bytes.length)
+ {
+ payload.bytes = new sbyte[ArrayUtil.oversize(payload.length, 1)];
+ }
+ postingInput.readBytes(payload.bytes, 0, payload.length);
+ }
+ else
+ {
+ payload.length = 0;
+ }
+ return pos;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int startOffset() throws java.io.IOException
+ public override int startOffset()
+ {
+ return startOffset_Renamed;
+ }
+
+ /// <summary>
+ /// Returns the wrapped <seealso cref="DocsAndPositionsEnum"/>. </summary>
+ internal virtual DocsAndPositionsEnum Wrapped
+ {
+ get
+ {
+ return @in;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Return a sorted view of <code>reader</code> according to the order
+ /// defined by <code>sort</code>. If the reader is already sorted, this
+ /// method might return the reader as-is.
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public static org.apache.lucene.index.AtomicReader wrap(org.apache.lucene.index.AtomicReader reader, org.apache.lucene.search.Sort sort) throws java.io.IOException
+ public static AtomicReader wrap(AtomicReader reader, Sort sort)
+ {
+ return wrap(reader, (new Sorter(sort)).sort(reader));
+ }
+
+ /// <summary>
+ /// Expert: same as <seealso cref="#wrap(AtomicReader, Sort)"/> but operates directly on a <seealso cref="Sorter.DocMap"/>. </summary>
+ internal static AtomicReader wrap(AtomicReader reader, Sorter.DocMap docMap)
+ {
+ if (docMap == null)
+ {
+ // the reader is already sorter
+ return reader;
+ }
+ if (reader.maxDoc() != docMap.size())
+ {
+ throw new System.ArgumentException("reader.maxDoc() should be equal to docMap.size(), got" + reader.maxDoc() + " != " + docMap.size());
+ }
+ Debug.Assert(Sorter.isConsistent(docMap));
+ return new SortingAtomicReader(reader, docMap);
+ }
+
+ internal readonly Sorter.DocMap docMap; // pkg-protected to avoid synthetic accessor methods
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: private SortingAtomicReader(final org.apache.lucene.index.AtomicReader in, final Sorter.DocMap docMap)
+ private SortingAtomicReader(AtomicReader @in, Sorter.DocMap docMap) : base(@in)
+ {
+ this.docMap = docMap;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void document(final int docID, final org.apache.lucene.index.StoredFieldVisitor visitor) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ public override void document(int docID, StoredFieldVisitor visitor)
+ {
+ @in.document(docMap.newToOld(docID), visitor);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.Fields fields() throws java.io.IOException
+ public override Fields fields()
+ {
+ Fields fields = @in.fields();
+ if (fields == null)
+ {
+ return null;
+ }
+ else
+ {
+ return new SortingFields(fields, @in.FieldInfos, docMap);
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.BinaryDocValues getBinaryDocValues(String field) throws java.io.IOException
+ public override BinaryDocValues getBinaryDocValues(string field)
+ {
+ BinaryDocValues oldDocValues = @in.getBinaryDocValues(field);
+ if (oldDocValues == null)
+ {
+ return null;
+ }
+ else
+ {
+ return new SortingBinaryDocValues(oldDocValues, docMap);
+ }
+ }
+
+ public override Bits LiveDocs
+ {
+ get
+ {
+ //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+ //ORIGINAL LINE: final org.apache.lucene.util.Bits inLiveDocs = in.getLiveDocs();
+ Bits inLiveDocs = @in.LiveDocs;
+ if (inLiveDocs == null)
+ {
+ return null;
+ }
+ else
+ {
+ return new SortingBits(inLiveDocs, docMap);
+ }
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.NumericDocValues getNormValues(String field) throws java.io.IOException
+ public override NumericDocValues getNormValues(string field)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.NumericDocValues norm = in.getNormValues(field);
+ NumericDocValues norm = @in.getNormValues(field);
+ if (norm == null)
+ {
+ return null;
+ }
+ else
+ {
+ return new SortingNumericDocValues(norm, docMap);
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.NumericDocValues getNumericDocValues(String field) throws java.io.IOException
+ public override NumericDocValues getNumericDocValues(string field)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.NumericDocValues oldDocValues = in.getNumericDocValues(field);
+ NumericDocValues oldDocValues = @in.getNumericDocValues(field);
+ if (oldDocValues == null)
+ {
+ return null;
+ }
+ return new SortingNumericDocValues(oldDocValues, docMap);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.SortedDocValues getSortedDocValues(String field) throws java.io.IOException
+ public override SortedDocValues getSortedDocValues(string field)
+ {
+ SortedDocValues sortedDV = @in.getSortedDocValues(field);
+ if (sortedDV == null)
+ {
+ return null;
+ }
+ else
+ {
+ return new SortingSortedDocValues(sortedDV, docMap);
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.SortedSetDocValues getSortedSetDocValues(String field) throws java.io.IOException
+ public override SortedSetDocValues getSortedSetDocValues(string field)
+ {
+ SortedSetDocValues sortedSetDV = @in.getSortedSetDocValues(field);
+ if (sortedSetDV == null)
+ {
+ return null;
+ }
+ else
+ {
+ return new SortingSortedSetDocValues(sortedSetDV, docMap);
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.util.Bits getDocsWithField(String field) throws java.io.IOException
+ public override Bits getDocsWithField(string field)
+ {
+ Bits bits = @in.getDocsWithField(field);
+ if (bits == null || bits is Bits.MatchAllBits || bits is Bits.MatchNoBits)
+ {
+ return bits;
+ }
+ else
+ {
+ return new SortingBits(bits, docMap);
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.Fields getTermVectors(final int docID) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ public override Fields getTermVectors(int docID)
+ {
+ return @in.getTermVectors(docMap.newToOld(docID));
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Index/Sorter/SortingMergePolicy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Index/Sorter/SortingMergePolicy.cs b/src/Lucene.Net.Misc/Index/Sorter/SortingMergePolicy.cs
new file mode 100644
index 0000000..c455d2a
--- /dev/null
+++ b/src/Lucene.Net.Misc/Index/Sorter/SortingMergePolicy.cs
@@ -0,0 +1,309 @@
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace org.apache.lucene.index.sorter
+{
+
+ /*
+ * 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 Analyzer = org.apache.lucene.analysis.Analyzer; // javadocs
+ using Sort = org.apache.lucene.search.Sort;
+ using Directory = org.apache.lucene.store.Directory;
+ using Bits = org.apache.lucene.util.Bits;
+ using MonotonicAppendingLongBuffer = org.apache.lucene.util.packed.MonotonicAppendingLongBuffer;
+
+ /// <summary>
+ /// A <seealso cref="MergePolicy"/> that reorders documents according to a <seealso cref="Sort"/>
+ /// before merging them. As a consequence, all segments resulting from a merge
+ /// will be sorted while segments resulting from a flush will be in the order
+ /// in which documents have been added.
+ /// <para><b>NOTE</b>: Never use this policy if you rely on
+ /// <seealso cref="IndexWriter#addDocuments(Iterable, Analyzer) IndexWriter.addDocuments"/>
+ /// to have sequentially-assigned doc IDs, this policy will scatter doc IDs.
+ /// </para>
+ /// <para><b>NOTE</b>: This policy should only be used with idempotent {@code Sort}s
+ /// so that the order of segments is predictable. For example, using
+ /// <seealso cref="Sort#INDEXORDER"/> in reverse (which is not idempotent) will make
+ /// the order of documents in a segment depend on the number of times the segment
+ /// has been merged.
+ /// @lucene.experimental
+ /// </para>
+ /// </summary>
+ public sealed class SortingMergePolicy : MergePolicy
+ {
+
+ /// <summary>
+ /// Put in the <seealso cref="SegmentInfo#getDiagnostics() diagnostics"/> to denote that
+ /// this segment is sorted.
+ /// </summary>
+ public const string SORTER_ID_PROP = "sorter";
+
+ internal class SortingOneMerge : OneMerge
+ {
+ private readonly SortingMergePolicy outerInstance;
+
+
+ internal IList<AtomicReader> unsortedReaders;
+ internal Sorter.DocMap docMap;
+ internal AtomicReader sortedView;
+
+ internal SortingOneMerge(SortingMergePolicy outerInstance, IList<SegmentCommitInfo> segments) : base(segments)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public java.util.List<org.apache.lucene.index.AtomicReader> getMergeReaders() throws java.io.IOException
+ public override IList<AtomicReader> MergeReaders
+ {
+ get
+ {
+ if (unsortedReaders == null)
+ {
+ unsortedReaders = base.MergeReaders;
+ //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+ //ORIGINAL LINE: final org.apache.lucene.index.AtomicReader atomicView;
+ AtomicReader atomicView;
+ if (unsortedReaders.Count == 1)
+ {
+ atomicView = unsortedReaders[0];
+ }
+ else
+ {
+ //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+ //ORIGINAL LINE: final org.apache.lucene.index.IndexReader multiReader = new org.apache.lucene.index.MultiReader(unsortedReaders.toArray(new org.apache.lucene.index.AtomicReader[unsortedReaders.size()]));
+ IndexReader multiReader = new MultiReader(unsortedReaders.ToArray());
+ atomicView = SlowCompositeReaderWrapper.wrap(multiReader);
+ }
+ docMap = outerInstance.sorter.sort(atomicView);
+ sortedView = SortingAtomicReader.wrap(atomicView, docMap);
+ }
+ // a null doc map means that the readers are already sorted
+ return docMap == null ? unsortedReaders : Collections.singletonList(sortedView);
+ }
+ }
+
+ public override SegmentCommitInfo Info
+ {
+ set
+ {
+ IDictionary<string, string> diagnostics = value.info.Diagnostics;
+ diagnostics[SORTER_ID_PROP] = outerInstance.sorter.ID;
+ base.Info = value;
+ }
+ }
+
+ internal virtual MonotonicAppendingLongBuffer getDeletes(IList<AtomicReader> readers)
+ {
+ MonotonicAppendingLongBuffer deletes = new MonotonicAppendingLongBuffer();
+ int deleteCount = 0;
+ foreach (AtomicReader reader in readers)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int maxDoc = reader.maxDoc();
+ int maxDoc = reader.maxDoc();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.Bits liveDocs = reader.getLiveDocs();
+ Bits liveDocs = reader.LiveDocs;
+ for (int i = 0; i < maxDoc; ++i)
+ {
+ if (liveDocs != null && !liveDocs.get(i))
+ {
+ ++deleteCount;
+ }
+ else
+ {
+ deletes.add(deleteCount);
+ }
+ }
+ }
+ deletes.freeze();
+ return deletes;
+ }
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.index.MergePolicy.DocMap getDocMap(final org.apache.lucene.index.MergeState mergeState)
+ public override MergePolicy.DocMap getDocMap(MergeState mergeState)
+ {
+ if (unsortedReaders == null)
+ {
+ throw new IllegalStateException();
+ }
+ if (docMap == null)
+ {
+ return base.getDocMap(mergeState);
+ }
+ Debug.Assert(mergeState.docMaps.length == 1); // we returned a singleton reader
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.packed.MonotonicAppendingLongBuffer deletes = getDeletes(unsortedReaders);
+ MonotonicAppendingLongBuffer deletes = getDeletes(unsortedReaders);
+ return new DocMapAnonymousInnerClassHelper(this, mergeState, deletes);
+ }
+
+ private class DocMapAnonymousInnerClassHelper : MergePolicy.DocMap
+ {
+ private readonly SortingOneMerge outerInstance;
+
+ private MergeState mergeState;
+ private MonotonicAppendingLongBuffer deletes;
+
+ public DocMapAnonymousInnerClassHelper(SortingOneMerge outerInstance, MergeState mergeState, MonotonicAppendingLongBuffer deletes)
+ {
+ this.outerInstance = outerInstance;
+ this.mergeState = mergeState;
+ this.deletes = deletes;
+ }
+
+ public override int map(int old)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int oldWithDeletes = old + (int) deletes.get(old);
+ int oldWithDeletes = old + (int) deletes.get(old);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int newWithDeletes = docMap.oldToNew(oldWithDeletes);
+ int newWithDeletes = outerInstance.docMap.oldToNew(oldWithDeletes);
+ return mergeState.docMaps[0].get(newWithDeletes);
+ }
+ }
+
+ }
+
+ internal class SortingMergeSpecification : MergeSpecification
+ {
+ private readonly SortingMergePolicy outerInstance;
+
+ public SortingMergeSpecification(SortingMergePolicy outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+
+ public override void add(OneMerge merge)
+ {
+ base.add(new SortingOneMerge(outerInstance, merge.segments));
+ }
+
+ public override string segString(Directory dir)
+ {
+ return "SortingMergeSpec(" + base.segString(dir) + ", sorter=" + outerInstance.sorter + ")";
+ }
+
+ }
+
+ /// <summary>
+ /// Returns {@code true} if the given {@code reader} is sorted by the specified {@code sort}. </summary>
+ public static bool isSorted(AtomicReader reader, Sort sort)
+ {
+ if (reader is SegmentReader)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.SegmentReader segReader = (org.apache.lucene.index.SegmentReader) reader;
+ SegmentReader segReader = (SegmentReader) reader;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final java.util.Map<String, String> diagnostics = segReader.getSegmentInfo().info.getDiagnostics();
+ IDictionary<string, string> diagnostics = segReader.SegmentInfo.info.Diagnostics;
+ if (diagnostics != null && sort.ToString().Equals(diagnostics[SORTER_ID_PROP]))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private MergeSpecification sortedMergeSpecification(MergeSpecification specification)
+ {
+ if (specification == null)
+ {
+ return null;
+ }
+ MergeSpecification sortingSpec = new SortingMergeSpecification(this);
+ foreach (OneMerge merge in specification.merges)
+ {
+ sortingSpec.add(merge);
+ }
+ return sortingSpec;
+ }
+
+ internal readonly MergePolicy @in;
+ internal readonly Sorter sorter;
+ internal readonly Sort sort;
+
+ /// <summary>
+ /// Create a new {@code MergePolicy} that sorts documents with the given {@code sort}. </summary>
+ public SortingMergePolicy(MergePolicy @in, Sort sort)
+ {
+ this.@in = @in;
+ this.sorter = new Sorter(sort);
+ this.sort = sort;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public MergeSpecification findMerges(org.apache.lucene.index.MergeTrigger mergeTrigger, org.apache.lucene.index.SegmentInfos segmentInfos) throws java.io.IOException
+ public override MergeSpecification findMerges(MergeTrigger mergeTrigger, SegmentInfos segmentInfos)
+ {
+ return sortedMergeSpecification(@in.findMerges(mergeTrigger, segmentInfos));
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public MergeSpecification findForcedMerges(org.apache.lucene.index.SegmentInfos segmentInfos, int maxSegmentCount, java.util.Map<org.apache.lucene.index.SegmentCommitInfo,Boolean> segmentsToMerge) throws java.io.IOException
+ public override MergeSpecification findForcedMerges(SegmentInfos segmentInfos, int maxSegmentCount, IDictionary<SegmentCommitInfo, bool?> segmentsToMerge)
+ {
+ return sortedMergeSpecification(@in.findForcedMerges(segmentInfos, maxSegmentCount, segmentsToMerge));
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public MergeSpecification findForcedDeletesMerges(org.apache.lucene.index.SegmentInfos segmentInfos) throws java.io.IOException
+ public override MergeSpecification findForcedDeletesMerges(SegmentInfos segmentInfos)
+ {
+ return sortedMergeSpecification(@in.findForcedDeletesMerges(segmentInfos));
+ }
+
+ public override MergePolicy clone()
+ {
+ return new SortingMergePolicy(@in.clone(), sort);
+ }
+
+ public override void close()
+ {
+ @in.close();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public boolean useCompoundFile(org.apache.lucene.index.SegmentInfos segments, org.apache.lucene.index.SegmentCommitInfo newSegment) throws java.io.IOException
+ public override bool useCompoundFile(SegmentInfos segments, SegmentCommitInfo newSegment)
+ {
+ return @in.useCompoundFile(segments, newSegment);
+ }
+
+ public override IndexWriter IndexWriter
+ {
+ set
+ {
+ @in.IndexWriter = value;
+ }
+ }
+
+ public override string ToString()
+ {
+ return "SortingMergePolicy(" + @in + ", sorter=" + sorter + ")";
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Lucene.Net.Misc.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Lucene.Net.Misc.csproj b/src/Lucene.Net.Misc/Lucene.Net.Misc.csproj
new file mode 100644
index 0000000..e4bc070
--- /dev/null
+++ b/src/Lucene.Net.Misc/Lucene.Net.Misc.csproj
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{A3A0D943-B91A-4B7A-9FCB-6160EA575D95}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Lucene.Net.Misc</RootNamespace>
+ <AssemblyName>Lucene.Net.Misc</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ByteBuffer.cs" />
+ <Compile Include="Document\LazyDocument.cs" />
+ <Compile Include="Index\CompoundFileExtractor.cs" />
+ <Compile Include="Index\IndexSplitter.cs" />
+ <Compile Include="Index\MultiPassIndexSplitter.cs" />
+ <Compile Include="Index\PKIndexSplitter.cs" />
+ <Compile Include="Index\Sorter\BlockJoinComparatorSource.cs" />
+ <Compile Include="Index\Sorter\EarlyTerminatingSortingCollector.cs" />
+ <Compile Include="Index\Sorter\Sorter.cs" />
+ <Compile Include="Index\Sorter\SortingAtomicReader.cs" />
+ <Compile Include="Index\Sorter\SortingMergePolicy.cs" />
+ <Compile Include="Misc\GetTermInfo.cs" />
+ <Compile Include="Misc\HighFreqTerms.cs" />
+ <Compile Include="Misc\IndexMergeTool.cs" />
+ <Compile Include="Misc\SweetSpotSimilarity.cs" />
+ <Compile Include="Misc\TermStats.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Store\NativePosixUtil.cs" />
+ <Compile Include="Store\NativeUnixDirectory.cs" />
+ <Compile Include="Store\WindowsDirectory.cs" />
+ <Compile Include="Util\Fst\ListOfOutputs.cs" />
+ <Compile Include="Util\Fst\UpToTwoPositiveIntOutputs.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Misc/GetTermInfo.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Misc/GetTermInfo.cs b/src/Lucene.Net.Misc/Misc/GetTermInfo.cs
new file mode 100644
index 0000000..9d56821
--- /dev/null
+++ b/src/Lucene.Net.Misc/Misc/GetTermInfo.cs
@@ -0,0 +1,74 @@
+using System;
+
+namespace org.apache.lucene.misc
+{
+
+ /*
+ * 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 Directory = org.apache.lucene.store.Directory;
+ using FSDirectory = org.apache.lucene.store.FSDirectory;
+ using DirectoryReader = org.apache.lucene.index.DirectoryReader;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using Term = org.apache.lucene.index.Term;
+
+ /// <summary>
+ /// Utility to get document frequency and total number of occurrences (sum of the tf for each doc) of a term.
+ /// </summary>
+ public class GetTermInfo
+ {
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public static void main(String[] args) throws Exception
+ public static void Main(string[] args)
+ {
+
+ FSDirectory dir = null;
+ string inputStr = null;
+ string field = null;
+
+ if (args.Length == 3)
+ {
+ dir = FSDirectory.open(new File(args[0]));
+ field = args[1];
+ inputStr = args[2];
+ }
+ else
+ {
+ usage();
+ Environment.Exit(1);
+ }
+
+ getTermInfo(dir,new Term(field, inputStr));
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public static void getTermInfo(org.apache.lucene.store.Directory dir, org.apache.lucene.index.Term term) throws Exception
+ public static void getTermInfo(Directory dir, Term term)
+ {
+ IndexReader reader = DirectoryReader.open(dir);
+ System.out.printf(Locale.ROOT, "%s:%s \t totalTF = %,d \t doc freq = %,d \n", term.field(), term.text(), reader.totalTermFreq(term), reader.docFreq(term));
+ }
+
+ private static void usage()
+ {
+//JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method:
+ Console.WriteLine("\n\nusage:\n\t" + "java " + typeof(GetTermInfo).FullName + " <index dir> field term \n\n");
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Misc/HighFreqTerms.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Misc/HighFreqTerms.cs b/src/Lucene.Net.Misc/Misc/HighFreqTerms.cs
new file mode 100644
index 0000000..dccb173
--- /dev/null
+++ b/src/Lucene.Net.Misc/Misc/HighFreqTerms.cs
@@ -0,0 +1,230 @@
+using System;
+using System.Collections.Generic;
+
+namespace org.apache.lucene.misc
+{
+
+ /*
+ * 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 DirectoryReader = org.apache.lucene.index.DirectoryReader;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using MultiFields = org.apache.lucene.index.MultiFields;
+ using Fields = org.apache.lucene.index.Fields;
+ using TermsEnum = org.apache.lucene.index.TermsEnum;
+ using Terms = org.apache.lucene.index.Terms;
+ using Directory = org.apache.lucene.store.Directory;
+ using FSDirectory = org.apache.lucene.store.FSDirectory;
+ using PriorityQueue = org.apache.lucene.util.PriorityQueue;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+ /// <summary>
+ /// <code>HighFreqTerms</code> class extracts the top n most frequent terms
+ /// (by document frequency) from an existing Lucene index and reports their
+ /// document frequency.
+ /// <para>
+ /// If the -t flag is given, both document frequency and total tf (total
+ /// number of occurrences) are reported, ordered by descending total tf.
+ ///
+ /// </para>
+ /// </summary>
+ public class HighFreqTerms
+ {
+
+ // The top numTerms will be displayed
+ public const int DEFAULT_NUMTERMS = 100;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public static void main(String[] args) throws Exception
+ public static void Main(string[] args)
+ {
+ string field = null;
+ int numTerms = DEFAULT_NUMTERMS;
+
+ if (args.Length == 0 || args.Length > 4)
+ {
+ usage();
+ Environment.Exit(1);
+ }
+
+ Directory dir = FSDirectory.open(new File(args[0]));
+
+ IComparer<TermStats> comparator = new DocFreqComparator();
+
+ for (int i = 1; i < args.Length; i++)
+ {
+ if (args[i].Equals("-t"))
+ {
+ comparator = new TotalTermFreqComparator();
+ }
+ else
+ {
+ try
+ {
+ numTerms = Convert.ToInt32(args[i]);
+ }
+ catch (NumberFormatException)
+ {
+ field = args[i];
+ }
+ }
+ }
+
+ IndexReader reader = DirectoryReader.open(dir);
+ TermStats[] terms = getHighFreqTerms(reader, numTerms, field, comparator);
+
+ for (int i = 0; i < terms.Length; i++)
+ {
+ System.out.printf(Locale.ROOT, "%s:%s \t totalTF = %,d \t docFreq = %,d \n", terms[i].field, terms[i].termtext.utf8ToString(), terms[i].totalTermFreq, terms[i].docFreq);
+ }
+ reader.close();
+ }
+
+ private static void usage()
+ {
+ Console.WriteLine("\n\n" + "java org.apache.lucene.misc.HighFreqTerms <index dir> [-t] [number_terms] [field]\n\t -t: order by totalTermFreq\n\n");
+ }
+
+ /// <summary>
+ /// Returns TermStats[] ordered by the specified comparator
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public static TermStats[] getHighFreqTerms(org.apache.lucene.index.IndexReader reader, int numTerms, String field, java.util.Comparator<TermStats> comparator) throws Exception
+ public static TermStats[] getHighFreqTerms(IndexReader reader, int numTerms, string field, IComparer<TermStats> comparator)
+ {
+ TermStatsQueue tiq = null;
+
+ if (field != null)
+ {
+ Fields fields = MultiFields.getFields(reader);
+ if (fields == null)
+ {
+ throw new Exception("field " + field + " not found");
+ }
+ Terms terms = fields.terms(field);
+ if (terms != null)
+ {
+ TermsEnum termsEnum = terms.iterator(null);
+ tiq = new TermStatsQueue(numTerms, comparator);
+ tiq.fill(field, termsEnum);
+ }
+ }
+ else
+ {
+ Fields fields = MultiFields.getFields(reader);
+ if (fields == null)
+ {
+ throw new Exception("no fields found for this index");
+ }
+ tiq = new TermStatsQueue(numTerms, comparator);
+ foreach (string fieldName in fields)
+ {
+ Terms terms = fields.terms(fieldName);
+ if (terms != null)
+ {
+ tiq.fill(fieldName, terms.iterator(null));
+ }
+ }
+ }
+
+ TermStats[] result = new TermStats[tiq.size()];
+ // we want highest first so we read the queue and populate the array
+ // starting at the end and work backwards
+ int count = tiq.size() - 1;
+ while (tiq.size() != 0)
+ {
+ result[count] = tiq.pop();
+ count--;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Compares terms by docTermFreq
+ /// </summary>
+ public sealed class DocFreqComparator : IComparer<TermStats>
+ {
+
+ public int Compare(TermStats a, TermStats b)
+ {
+ int res = long.compare(a.docFreq, b.docFreq);
+ if (res == 0)
+ {
+ res = a.field.CompareTo(b.field);
+ if (res == 0)
+ {
+ res = a.termtext.compareTo(b.termtext);
+ }
+ }
+ return res;
+ }
+ }
+
+ /// <summary>
+ /// Compares terms by totalTermFreq
+ /// </summary>
+ public sealed class TotalTermFreqComparator : IComparer<TermStats>
+ {
+
+ public int Compare(TermStats a, TermStats b)
+ {
+ int res = long.compare(a.totalTermFreq, b.totalTermFreq);
+ if (res == 0)
+ {
+ res = a.field.CompareTo(b.field);
+ if (res == 0)
+ {
+ res = a.termtext.compareTo(b.termtext);
+ }
+ }
+ return res;
+ }
+ }
+
+ /// <summary>
+ /// Priority queue for TermStats objects
+ ///
+ /// </summary>
+ internal sealed class TermStatsQueue : PriorityQueue<TermStats>
+ {
+ internal readonly IComparer<TermStats> comparator;
+
+ internal TermStatsQueue(int size, IComparer<TermStats> comparator) : base(size)
+ {
+ this.comparator = comparator;
+ }
+
+ protected internal override bool lessThan(TermStats termInfoA, TermStats termInfoB)
+ {
+ return comparator.Compare(termInfoA, termInfoB) < 0;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: protected void fill(String field, org.apache.lucene.index.TermsEnum termsEnum) throws java.io.IOException
+ protected internal void fill(string field, TermsEnum termsEnum)
+ {
+ BytesRef term = null;
+ while ((term = termsEnum.next()) != null)
+ {
+ insertWithOverflow(new TermStats(field, term, termsEnum.docFreq(), termsEnum.totalTermFreq()));
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Misc/IndexMergeTool.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Misc/IndexMergeTool.cs b/src/Lucene.Net.Misc/Misc/IndexMergeTool.cs
new file mode 100644
index 0000000..bba8704
--- /dev/null
+++ b/src/Lucene.Net.Misc/Misc/IndexMergeTool.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace org.apache.lucene.misc
+{
+
+ /// <summary>
+ /// Copyright 2005 The Apache Software Foundation
+ ///
+ /// Licensed 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.
+ /// </summary>
+
+ using IndexWriter = org.apache.lucene.index.IndexWriter;
+ using IndexWriterConfig = org.apache.lucene.index.IndexWriterConfig;
+ using OpenMode = org.apache.lucene.index.IndexWriterConfig.OpenMode;
+ using Directory = org.apache.lucene.store.Directory;
+ using FSDirectory = org.apache.lucene.store.FSDirectory;
+ using Version = org.apache.lucene.util.Version;
+
+
+ /// <summary>
+ /// Merges indices specified on the command line into the index
+ /// specified as the first command line argument.
+ /// </summary>
+ public class IndexMergeTool
+ {
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public static void main(String[] args) throws java.io.IOException
+ public static void Main(string[] args)
+ {
+ if (args.Length < 3)
+ {
+ Console.Error.WriteLine("Usage: IndexMergeTool <mergedIndex> <index1> <index2> [index3] ...");
+ Environment.Exit(1);
+ }
+ FSDirectory mergedIndex = FSDirectory.open(new File(args[0]));
+
+ IndexWriter writer = new IndexWriter(mergedIndex, new IndexWriterConfig(Version.LUCENE_CURRENT, null)
+ .setOpenMode(IndexWriterConfig.OpenMode.CREATE));
+
+ Directory[] indexes = new Directory[args.Length - 1];
+ for (int i = 1; i < args.Length; i++)
+ {
+ indexes[i - 1] = FSDirectory.open(new File(args[i]));
+ }
+
+ Console.WriteLine("Merging...");
+ writer.addIndexes(indexes);
+
+ Console.WriteLine("Full merge...");
+ writer.forceMerge(1);
+ writer.close();
+ Console.WriteLine("Done.");
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Misc/SweetSpotSimilarity.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Misc/SweetSpotSimilarity.cs b/src/Lucene.Net.Misc/Misc/SweetSpotSimilarity.cs
new file mode 100644
index 0000000..bc0386c
--- /dev/null
+++ b/src/Lucene.Net.Misc/Misc/SweetSpotSimilarity.cs
@@ -0,0 +1,238 @@
+using System;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.misc
+{
+
+ using DefaultSimilarity = org.apache.lucene.search.similarities.DefaultSimilarity;
+ using FieldInvertState = org.apache.lucene.index.FieldInvertState;
+
+ /// <summary>
+ /// <para>
+ /// A similarity with a lengthNorm that provides for a "plateau" of
+ /// equally good lengths, and tf helper functions.
+ /// </para>
+ /// <para>
+ /// For lengthNorm, A min/max can be specified to define the
+ /// plateau of lengths that should all have a norm of 1.0.
+ /// Below the min, and above the max the lengthNorm drops off in a
+ /// sqrt function.
+ /// </para>
+ /// <para>
+ /// For tf, baselineTf and hyperbolicTf functions are provided, which
+ /// subclasses can choose between.
+ /// </para>
+ /// </summary>
+ /// <seealso cref= <a href="doc-files/ss.gnuplot">A Gnuplot file used to generate some of the visualizations refrenced from each function.</a> </seealso>
+ public class SweetSpotSimilarity : DefaultSimilarity
+ {
+
+ private int ln_min = 1;
+ private int ln_max = 1;
+ private float ln_steep = 0.5f;
+
+ private float tf_base = 0.0f;
+ private float tf_min = 0.0f;
+
+ private float tf_hyper_min = 0.0f;
+ private float tf_hyper_max = 2.0f;
+ private double tf_hyper_base = 1.3d;
+ private float tf_hyper_xoffset = 10.0f;
+
+ public SweetSpotSimilarity() : base()
+ {
+ }
+
+ /// <summary>
+ /// Sets the baseline and minimum function variables for baselineTf
+ /// </summary>
+ /// <seealso cref= #baselineTf </seealso>
+ public virtual void setBaselineTfFactors(float @base, float min)
+ {
+ tf_min = min;
+ tf_base = @base;
+ }
+
+ /// <summary>
+ /// Sets the function variables for the hyperbolicTf functions
+ /// </summary>
+ /// <param name="min"> the minimum tf value to ever be returned (default: 0.0) </param>
+ /// <param name="max"> the maximum tf value to ever be returned (default: 2.0) </param>
+ /// <param name="base"> the base value to be used in the exponential for the hyperbolic function (default: 1.3) </param>
+ /// <param name="xoffset"> the midpoint of the hyperbolic function (default: 10.0) </param>
+ /// <seealso cref= #hyperbolicTf </seealso>
+ public virtual void setHyperbolicTfFactors(float min, float max, double @base, float xoffset)
+ {
+ tf_hyper_min = min;
+ tf_hyper_max = max;
+ tf_hyper_base = @base;
+ tf_hyper_xoffset = xoffset;
+ }
+
+ /// <summary>
+ /// Sets the default function variables used by lengthNorm when no field
+ /// specific variables have been set.
+ /// </summary>
+ /// <seealso cref= #computeLengthNorm </seealso>
+ public virtual void setLengthNormFactors(int min, int max, float steepness, bool discountOverlaps)
+ {
+ this.ln_min = min;
+ this.ln_max = max;
+ this.ln_steep = steepness;
+ this.discountOverlaps = discountOverlaps;
+ }
+
+ /// <summary>
+ /// Implemented as <code> state.getBoost() *
+ /// computeLengthNorm(numTokens) </code> where
+ /// numTokens does not count overlap tokens if
+ /// discountOverlaps is true by default or true for this
+ /// specific field.
+ /// </summary>
+ public override float lengthNorm(FieldInvertState state)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int numTokens;
+ int numTokens;
+
+ if (discountOverlaps)
+ {
+ numTokens = state.Length - state.NumOverlap;
+ }
+ else
+ {
+ numTokens = state.Length;
+ }
+
+ return state.Boost * computeLengthNorm(numTokens);
+ }
+
+ /// <summary>
+ /// Implemented as:
+ /// <code>
+ /// 1/sqrt( steepness * (abs(x-min) + abs(x-max) - (max-min)) + 1 )
+ /// </code>.
+ ///
+ /// <para>
+ /// This degrades to <code>1/sqrt(x)</code> when min and max are both 1 and
+ /// steepness is 0.5
+ /// </para>
+ ///
+ /// <para>
+ /// :TODO: potential optimization is to just flat out return 1.0f if numTerms
+ /// is between min and max.
+ /// </para>
+ /// </summary>
+ /// <seealso cref= #setLengthNormFactors </seealso>
+ /// <seealso cref= <a href="doc-files/ss.computeLengthNorm.svg">An SVG visualization of this function</a> </seealso>
+ public virtual float computeLengthNorm(int numTerms)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int l = ln_min;
+ int l = ln_min;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int h = ln_max;
+ int h = ln_max;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float s = ln_steep;
+ float s = ln_steep;
+
+ return (float)(1.0f / Math.Sqrt((s * (float)(Math.Abs(numTerms - l) + Math.Abs(numTerms - h) - (h - l))) + 1.0f));
+ }
+
+ /// <summary>
+ /// Delegates to baselineTf
+ /// </summary>
+ /// <seealso cref= #baselineTf </seealso>
+ public override float tf(float freq)
+ {
+ return baselineTf(freq);
+ }
+
+ /// <summary>
+ /// Implemented as:
+ /// <code>
+ /// (x <= min) ? base : sqrt(x+(base**2)-min)
+ /// </code>
+ /// ...but with a special case check for 0.
+ /// <para>
+ /// This degrates to <code>sqrt(x)</code> when min and base are both 0
+ /// </para>
+ /// </summary>
+ /// <seealso cref= #setBaselineTfFactors </seealso>
+ /// <seealso cref= <a href="doc-files/ss.baselineTf.svg">An SVG visualization of this function</a> </seealso>
+ public virtual float baselineTf(float freq)
+ {
+
+ if (0.0f == freq)
+ {
+ return 0.0f;
+ }
+
+ return (freq <= tf_min) ? tf_base : (float)Math.Sqrt(freq + (tf_base * tf_base) - tf_min);
+ }
+
+ /// <summary>
+ /// Uses a hyperbolic tangent function that allows for a hard max...
+ ///
+ /// <code>
+ /// tf(x)=min+(max-min)/2*(((base**(x-xoffset)-base**-(x-xoffset))/(base**(x-xoffset)+base**-(x-xoffset)))+1)
+ /// </code>
+ ///
+ /// <para>
+ /// This code is provided as a convenience for subclasses that want
+ /// to use a hyperbolic tf function.
+ /// </para>
+ /// </summary>
+ /// <seealso cref= #setHyperbolicTfFactors </seealso>
+ /// <seealso cref= <a href="doc-files/ss.hyperbolicTf.svg">An SVG visualization of this function</a> </seealso>
+ public virtual float hyperbolicTf(float freq)
+ {
+ if (0.0f == freq)
+ {
+ return 0.0f;
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float min = tf_hyper_min;
+ float min = tf_hyper_min;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float max = tf_hyper_max;
+ float max = tf_hyper_max;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final double base = tf_hyper_base;
+ double @base = tf_hyper_base;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float xoffset = tf_hyper_xoffset;
+ float xoffset = tf_hyper_xoffset;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final double x = (double)(freq - xoffset);
+ double x = (double)(freq - xoffset);
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float result = min + (float)((max-min) / 2.0f * (((Math.pow(base,x) - Math.pow(base,-x)) / (Math.pow(base,x) + Math.pow(base,-x))) + 1.0d));
+ float result = min + (float)((max - min) / 2.0f * (((Math.Pow(@base,x) - Math.Pow(@base,-x)) / (Math.Pow(@base,x) + Math.Pow(@base,-x))) + 1.0d));
+
+ return float.IsNaN(result) ? max : result;
+
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Misc/TermStats.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Misc/TermStats.cs b/src/Lucene.Net.Misc/Misc/TermStats.cs
new file mode 100644
index 0000000..061cca3
--- /dev/null
+++ b/src/Lucene.Net.Misc/Misc/TermStats.cs
@@ -0,0 +1,55 @@
+namespace org.apache.lucene.misc
+{
+
+ /*
+ * 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 BytesRef = org.apache.lucene.util.BytesRef;
+
+ /// <summary>
+ /// Holder for a term along with its statistics
+ /// (<seealso cref="#docFreq"/> and <seealso cref="#totalTermFreq"/>).
+ /// </summary>
+ public sealed class TermStats
+ {
+ public BytesRef termtext;
+ public string field;
+ public int docFreq;
+ public long totalTermFreq;
+
+ internal TermStats(string field, BytesRef termtext, int df, long tf)
+ {
+ this.termtext = BytesRef.deepCopyOf(termtext);
+ this.field = field;
+ this.docFreq = df;
+ this.totalTermFreq = tf;
+ }
+
+ internal string TermText
+ {
+ get
+ {
+ return termtext.utf8ToString();
+ }
+ }
+
+ public override string ToString()
+ {
+ return ("TermStats: term=" + termtext.utf8ToString() + " docFreq=" + docFreq + " totalTermFreq=" + totalTermFreq);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Properties/AssemblyInfo.cs b/src/Lucene.Net.Misc/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..39cfea7
--- /dev/null
+++ b/src/Lucene.Net.Misc/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Lucene.Net.Misc")]
+[assembly: AssemblyDescription("Index tools and other miscellaneous code")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Lucene.Net.Misc")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b2a3a8e1-a92a-4bd6-9f87-7747470615c3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Store/NativePosixUtil.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Store/NativePosixUtil.cs b/src/Lucene.Net.Misc/Store/NativePosixUtil.cs
new file mode 100644
index 0000000..3bb51d5
--- /dev/null
+++ b/src/Lucene.Net.Misc/Store/NativePosixUtil.cs
@@ -0,0 +1,64 @@
+using System;
+
+namespace org.apache.lucene.store
+{
+
+ /*
+ * 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.
+ */
+
+ ignore
+
+ /// <summary>
+ /// Provides JNI access to native methods such as madvise() for
+ /// <seealso cref="NativeUnixDirectory"/>
+ /// </summary>
+ public final class NativePosixUtil
+ {
+ public final static int NORMAL = 0;
+ public final static int SEQUENTIAL = 1;
+ public final static int RANDOM = 2;
+ public final static int WILLNEED = 3;
+ public final static int DONTNEED = 4;
+ public final static int NOREUSE = 5;
+
+//JAVA TO C# CONVERTER NOTE: This static initializer block is converted to a static constructor, but there is no current class:
+ static ImpliedClass()
+ {
+//JAVA TO C# CONVERTER TODO TASK: The library is specified in the 'DllImport' attribute for .NET:
+// System.loadLibrary("NativePosixUtil");
+ }
+
+ private static native int posix_fadvise(FileDescriptor fd, long offset, long len, int advise) throws IOException;
+ public static native int posix_madvise(ByteBuffer buf, int advise) throws IOException;
+ public static native int madvise(ByteBuffer buf, int advise) throws IOException;
+ public static native FileDescriptor open_direct(string filename, bool read) throws IOException;
+ public static native long pread(FileDescriptor fd, long pos, ByteBuffer byteBuf) throws IOException;
+
+ public static void advise(FileDescriptor fd, long offset, long len, int advise) throws IOException
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int code = posix_fadvise(fd, offset, len, advise);
+ int code = posix_fadvise(fd, offset, len, advise);
+ if (code != 0)
+ {
+ throw new Exception("posix_fadvise failed code=" + code);
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
[03/11] Skeleton porting of Lucene.Net.Queries
Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/SumFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/SumFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/SumFloatFunction.cs
new file mode 100644
index 0000000..fcd3e41
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/SumFloatFunction.cs
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ /// <summary>
+ /// <code>SumFloatFunction</code> returns the sum of it's components.
+ /// </summary>
+ public class SumFloatFunction : MultiFloatFunction
+ {
+ public SumFloatFunction(ValueSource[] sources) : base(sources)
+ {
+ }
+
+ protected internal override string name()
+ {
+ return "sum";
+ }
+
+ protected internal override float func(int doc, FunctionValues[] valsArr)
+ {
+ float val = 0.0f;
+ foreach (FunctionValues vals in valsArr)
+ {
+ val += vals.floatVal(doc);
+ }
+ return val;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/SumTotalTermFreqValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/SumTotalTermFreqValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/SumTotalTermFreqValueSource.cs
new file mode 100644
index 0000000..48a9600
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/SumTotalTermFreqValueSource.cs
@@ -0,0 +1,132 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using Fields = org.apache.lucene.index.Fields;
+ using Terms = org.apache.lucene.index.Terms;
+ using LongDocValues = org.apache.lucene.queries.function.docvalues.LongDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+ /// <summary>
+ /// <code>SumTotalTermFreqValueSource</code> returns the number of tokens.
+ /// (sum of term freqs across all documents, across all terms).
+ /// Returns -1 if frequencies were omitted for the field, or if
+ /// the codec doesn't support this statistic.
+ /// @lucene.internal
+ /// </summary>
+ public class SumTotalTermFreqValueSource : ValueSource
+ {
+ protected internal readonly string indexedField;
+
+ public SumTotalTermFreqValueSource(string indexedField)
+ {
+ this.indexedField = indexedField;
+ }
+
+ public virtual string name()
+ {
+ return "sumtotaltermfreq";
+ }
+
+ public override string description()
+ {
+ return name() + '(' + indexedField + ')';
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ return (FunctionValues)context[this];
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ long sumTotalTermFreq = 0;
+ foreach (AtomicReaderContext readerContext in searcher.TopReaderContext.leaves())
+ {
+ Fields fields = readerContext.reader().fields();
+ if (fields == null)
+ {
+ continue;
+ }
+ Terms terms = fields.terms(indexedField);
+ if (terms == null)
+ {
+ continue;
+ }
+ long v = terms.SumTotalTermFreq;
+ if (v == -1)
+ {
+ sumTotalTermFreq = -1;
+ break;
+ }
+ else
+ {
+ sumTotalTermFreq += v;
+ }
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long ttf = sumTotalTermFreq;
+ long ttf = sumTotalTermFreq;
+ context[this] = new LongDocValuesAnonymousInnerClassHelper(this, this, ttf);
+ }
+
+ private class LongDocValuesAnonymousInnerClassHelper : LongDocValues
+ {
+ private readonly SumTotalTermFreqValueSource outerInstance;
+
+ private long ttf;
+
+ public LongDocValuesAnonymousInnerClassHelper(SumTotalTermFreqValueSource outerInstance, org.apache.lucene.queries.function.valuesource.SumTotalTermFreqValueSource this, long ttf) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.ttf = ttf;
+ }
+
+ public override long longVal(int doc)
+ {
+ return ttf;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return this.GetType().GetHashCode() + indexedField.GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ SumTotalTermFreqValueSource other = (SumTotalTermFreqValueSource)o;
+ return this.indexedField.Equals(other.indexedField);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/TFValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/TFValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/TFValueSource.cs
new file mode 100644
index 0000000..e957cc8
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/TFValueSource.cs
@@ -0,0 +1,197 @@
+using System;
+using System.Collections;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ /*
+ * 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 org.apache.lucene.index;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using DocIdSetIterator = org.apache.lucene.search.DocIdSetIterator;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using TFIDFSimilarity = org.apache.lucene.search.similarities.TFIDFSimilarity;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+ /// <summary>
+ /// Function that returns <seealso cref="TFIDFSimilarity#tf(float)"/>
+ /// for every document.
+ /// <para>
+ /// Note that the configured Similarity for the field must be
+ /// a subclass of <seealso cref="TFIDFSimilarity"/>
+ /// @lucene.internal
+ /// </para>
+ /// </summary>
+ public class TFValueSource : TermFreqValueSource
+ {
+ public TFValueSource(string field, string val, string indexedField, BytesRef indexedBytes) : base(field, val, indexedField, indexedBytes)
+ {
+ }
+
+ public override string name()
+ {
+ return "tf";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ Fields fields = readerContext.reader().fields();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Terms terms = fields.terms(indexedField);
+ Terms terms = fields.terms(indexedField);
+ IndexSearcher searcher = (IndexSearcher)context["searcher"];
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.similarities.TFIDFSimilarity similarity = IDFValueSource.asTFIDF(searcher.getSimilarity(), indexedField);
+ TFIDFSimilarity similarity = IDFValueSource.asTFIDF(searcher.Similarity, indexedField);
+ if (similarity == null)
+ {
+ throw new System.NotSupportedException("requires a TFIDFSimilarity (such as DefaultSimilarity)");
+ }
+
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, terms, similarity);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly TFValueSource outerInstance;
+
+ private Terms terms;
+ private TFIDFSimilarity similarity;
+
+ public FloatDocValuesAnonymousInnerClassHelper(TFValueSource outerInstance, org.apache.lucene.queries.function.valuesource.TFValueSource this, Terms terms, TFIDFSimilarity similarity) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.terms = terms;
+ this.similarity = similarity;
+ lastDocRequested = -1;
+ }
+
+ internal DocsEnum docs;
+ internal int atDoc;
+ internal int lastDocRequested;
+
+//JAVA TO C# CONVERTER TODO TASK: Initialization blocks declared within anonymous inner classes are not converted:
+ // {
+ // reset();
+ // }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public void reset() throws java.io.IOException
+ public virtual void reset()
+ {
+ // no one should call us for deleted docs?
+
+ if (terms != null)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final TermsEnum termsEnum = terms.iterator(null);
+ TermsEnum termsEnum = terms.iterator(null);
+ if (termsEnum.seekExact(outerInstance.indexedBytes))
+ {
+ docs = termsEnum.docs(null, null);
+ }
+ else
+ {
+ docs = null;
+ }
+ }
+ else
+ {
+ docs = null;
+ }
+
+ if (docs == null)
+ {
+ docs = new DocsEnumAnonymousInnerClassHelper(this);
+ }
+ atDoc = -1;
+ }
+
+ private class DocsEnumAnonymousInnerClassHelper : DocsEnum
+ {
+ private readonly FloatDocValuesAnonymousInnerClassHelper outerInstance;
+
+ public DocsEnumAnonymousInnerClassHelper(FloatDocValuesAnonymousInnerClassHelper outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+ public override int freq()
+ {
+ return 0;
+ }
+
+ public override int docID()
+ {
+ return DocIdSetIterator.NO_MORE_DOCS;
+ }
+
+ public override int nextDoc()
+ {
+ return DocIdSetIterator.NO_MORE_DOCS;
+ }
+
+ public override int advance(int target)
+ {
+ return DocIdSetIterator.NO_MORE_DOCS;
+ }
+
+ public override long cost()
+ {
+ return 0;
+ }
+ }
+
+ public override float floatVal(int doc)
+ {
+ try
+ {
+ if (doc < lastDocRequested)
+ {
+ // out-of-order access.... reset
+ reset();
+ }
+ lastDocRequested = doc;
+
+ if (atDoc < doc)
+ {
+ atDoc = docs.advance(doc);
+ }
+
+ if (atDoc > doc)
+ {
+ // term doesn't match this document... either because we hit the
+ // end, or because the next doc is after this doc.
+ return similarity.tf(0);
+ }
+
+ // a match!
+ return similarity.tf(docs.freq());
+ }
+ catch (IOException e)
+ {
+ throw new Exception("caught exception in function " + outerInstance.description() + " : doc=" + doc, e);
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/TermFreqValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/TermFreqValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/TermFreqValueSource.cs
new file mode 100644
index 0000000..7e03f2b
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/TermFreqValueSource.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using org.apache.lucene.index;
+ using IntDocValues = org.apache.lucene.queries.function.docvalues.IntDocValues;
+ using DocIdSetIterator = org.apache.lucene.search.DocIdSetIterator;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+ /// <summary>
+ /// Function that returns <seealso cref="DocsEnum#freq()"/> for the
+ /// supplied term in every document.
+ /// <para>
+ /// If the term does not exist in the document, returns 0.
+ /// If frequencies are omitted, returns 1.
+ /// </para>
+ /// </summary>
+ public class TermFreqValueSource : DocFreqValueSource
+ {
+ public TermFreqValueSource(string field, string val, string indexedField, BytesRef indexedBytes) : base(field, val, indexedField, indexedBytes)
+ {
+ }
+
+ public override string name()
+ {
+ return "termfreq";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ Fields fields = readerContext.reader().fields();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Terms terms = fields.terms(indexedField);
+ Terms terms = fields.terms(indexedField);
+
+ return new IntDocValuesAnonymousInnerClassHelper(this, this, terms);
+ }
+
+ private class IntDocValuesAnonymousInnerClassHelper : IntDocValues
+ {
+ private readonly TermFreqValueSource outerInstance;
+
+ private Terms terms;
+
+ public IntDocValuesAnonymousInnerClassHelper(TermFreqValueSource outerInstance, org.apache.lucene.queries.function.valuesource.TermFreqValueSource this, Terms terms) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.terms = terms;
+ lastDocRequested = -1;
+ }
+
+ internal DocsEnum docs;
+ internal int atDoc;
+ internal int lastDocRequested;
+
+//JAVA TO C# CONVERTER TODO TASK: Initialization blocks declared within anonymous inner classes are not converted:
+ // {
+ // reset();
+ // }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public void reset() throws java.io.IOException
+ public virtual void reset()
+ {
+ // no one should call us for deleted docs?
+
+ if (terms != null)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final TermsEnum termsEnum = terms.iterator(null);
+ TermsEnum termsEnum = terms.iterator(null);
+ if (termsEnum.seekExact(outerInstance.indexedBytes))
+ {
+ docs = termsEnum.docs(null, null);
+ }
+ else
+ {
+ docs = null;
+ }
+ }
+ else
+ {
+ docs = null;
+ }
+
+ if (docs == null)
+ {
+ docs = new DocsEnumAnonymousInnerClassHelper(this);
+ }
+ atDoc = -1;
+ }
+
+ private class DocsEnumAnonymousInnerClassHelper : DocsEnum
+ {
+ private readonly IntDocValuesAnonymousInnerClassHelper outerInstance;
+
+ public DocsEnumAnonymousInnerClassHelper(IntDocValuesAnonymousInnerClassHelper outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+ public override int freq()
+ {
+ return 0;
+ }
+
+ public override int docID()
+ {
+ return DocIdSetIterator.NO_MORE_DOCS;
+ }
+
+ public override int nextDoc()
+ {
+ return DocIdSetIterator.NO_MORE_DOCS;
+ }
+
+ public override int advance(int target)
+ {
+ return DocIdSetIterator.NO_MORE_DOCS;
+ }
+
+ public override long cost()
+ {
+ return 0;
+ }
+ }
+
+ public override int intVal(int doc)
+ {
+ try
+ {
+ if (doc < lastDocRequested)
+ {
+ // out-of-order access.... reset
+ reset();
+ }
+ lastDocRequested = doc;
+
+ if (atDoc < doc)
+ {
+ atDoc = docs.advance(doc);
+ }
+
+ if (atDoc > doc)
+ {
+ // term doesn't match this document... either because we hit the
+ // end, or because the next doc is after this doc.
+ return 0;
+ }
+
+ // a match!
+ return docs.freq();
+ }
+ catch (IOException e)
+ {
+ throw new Exception("caught exception in function " + outerInstance.description() + " : doc=" + doc, e);
+ }
+ }
+ }
+ }
+
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/TotalTermFreqValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/TotalTermFreqValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/TotalTermFreqValueSource.cs
new file mode 100644
index 0000000..629d6c6
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/TotalTermFreqValueSource.cs
@@ -0,0 +1,127 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using Term = org.apache.lucene.index.Term;
+ using LongDocValues = org.apache.lucene.queries.function.docvalues.LongDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+ /// <summary>
+ /// <code>TotalTermFreqValueSource</code> returns the total term freq
+ /// (sum of term freqs across all documents).
+ /// Returns -1 if frequencies were omitted for the field, or if
+ /// the codec doesn't support this statistic.
+ /// @lucene.internal
+ /// </summary>
+ public class TotalTermFreqValueSource : ValueSource
+ {
+ protected internal readonly string field;
+ protected internal readonly string indexedField;
+ protected internal readonly string val;
+ protected internal readonly BytesRef indexedBytes;
+
+ public TotalTermFreqValueSource(string field, string val, string indexedField, BytesRef indexedBytes)
+ {
+ this.field = field;
+ this.val = val;
+ this.indexedField = indexedField;
+ this.indexedBytes = indexedBytes;
+ }
+
+ public virtual string name()
+ {
+ return "totaltermfreq";
+ }
+
+ public override string description()
+ {
+ return name() + '(' + field + ',' + val + ')';
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ return (FunctionValues)context[this];
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ long totalTermFreq = 0;
+ foreach (AtomicReaderContext readerContext in searcher.TopReaderContext.leaves())
+ {
+ long val = readerContext.reader().totalTermFreq(new Term(indexedField, indexedBytes));
+ if (val == -1)
+ {
+ totalTermFreq = -1;
+ break;
+ }
+ else
+ {
+ totalTermFreq += val;
+ }
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final long ttf = totalTermFreq;
+ long ttf = totalTermFreq;
+ context[this] = new LongDocValuesAnonymousInnerClassHelper(this, this, ttf);
+ }
+
+ private class LongDocValuesAnonymousInnerClassHelper : LongDocValues
+ {
+ private readonly TotalTermFreqValueSource outerInstance;
+
+ private long ttf;
+
+ public LongDocValuesAnonymousInnerClassHelper(TotalTermFreqValueSource outerInstance, org.apache.lucene.queries.function.valuesource.TotalTermFreqValueSource this, long ttf) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.ttf = ttf;
+ }
+
+ public override long longVal(int doc)
+ {
+ return ttf;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return this.GetType().GetHashCode() + indexedField.GetHashCode() * 29 + indexedBytes.GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ TotalTermFreqValueSource other = (TotalTermFreqValueSource)o;
+ return this.indexedField.Equals(other.indexedField) && this.indexedBytes.Equals(other.indexedBytes);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/VectorValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/VectorValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/VectorValueSource.cs
new file mode 100644
index 0000000..2668ac2
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/VectorValueSource.cs
@@ -0,0 +1,293 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+
+ /// <summary>
+ /// Converts individual ValueSource instances to leverage the FunctionValues *Val functions that work with multiple values,
+ /// i.e. <seealso cref="org.apache.lucene.queries.function.FunctionValues#doubleVal(int, double[])"/>
+ /// </summary>
+ //Not crazy about the name, but...
+ public class VectorValueSource : MultiValueSource
+ {
+ protected internal readonly IList<ValueSource> sources;
+
+
+ public VectorValueSource(IList<ValueSource> sources)
+ {
+ this.sources = sources;
+ }
+
+ public virtual IList<ValueSource> Sources
+ {
+ get
+ {
+ return sources;
+ }
+ }
+
+ public override int dimension()
+ {
+ return sources.Count;
+ }
+
+ public virtual string name()
+ {
+ return "vector";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ int size = sources.Count;
+
+ // special-case x,y and lat,lon since it's so common
+ if (size == 2)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues x = sources.get(0).getValues(context, readerContext);
+ FunctionValues x = sources[0].getValues(context, readerContext);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues y = sources.get(1).getValues(context, readerContext);
+ FunctionValues y = sources[1].getValues(context, readerContext);
+ return new FunctionValuesAnonymousInnerClassHelper(this, x, y);
+ }
+
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues[] valsArr = new org.apache.lucene.queries.function.FunctionValues[size];
+ FunctionValues[] valsArr = new FunctionValues[size];
+ for (int i = 0; i < size; i++)
+ {
+ valsArr[i] = sources[i].getValues(context, readerContext);
+ }
+
+ return new FunctionValuesAnonymousInnerClassHelper2(this, valsArr);
+ }
+
+ private class FunctionValuesAnonymousInnerClassHelper : FunctionValues
+ {
+ private readonly VectorValueSource outerInstance;
+
+ private FunctionValues x;
+ private FunctionValues y;
+
+ public FunctionValuesAnonymousInnerClassHelper(VectorValueSource outerInstance, FunctionValues x, FunctionValues y)
+ {
+ this.outerInstance = outerInstance;
+ this.x = x;
+ this.y = y;
+ }
+
+ public override void byteVal(int doc, sbyte[] vals)
+ {
+ vals[0] = x.byteVal(doc);
+ vals[1] = y.byteVal(doc);
+ }
+
+ public override void shortVal(int doc, short[] vals)
+ {
+ vals[0] = x.shortVal(doc);
+ vals[1] = y.shortVal(doc);
+ }
+ public override void intVal(int doc, int[] vals)
+ {
+ vals[0] = x.intVal(doc);
+ vals[1] = y.intVal(doc);
+ }
+ public override void longVal(int doc, long[] vals)
+ {
+ vals[0] = x.longVal(doc);
+ vals[1] = y.longVal(doc);
+ }
+ public override void floatVal(int doc, float[] vals)
+ {
+ vals[0] = x.floatVal(doc);
+ vals[1] = y.floatVal(doc);
+ }
+ public override void doubleVal(int doc, double[] vals)
+ {
+ vals[0] = x.doubleVal(doc);
+ vals[1] = y.doubleVal(doc);
+ }
+ public override void strVal(int doc, string[] vals)
+ {
+ vals[0] = x.strVal(doc);
+ vals[1] = y.strVal(doc);
+ }
+ public override string ToString(int doc)
+ {
+ return outerInstance.name() + "(" + x.ToString(doc) + "," + y.ToString(doc) + ")";
+ }
+ }
+
+ private class FunctionValuesAnonymousInnerClassHelper2 : FunctionValues
+ {
+ private readonly VectorValueSource outerInstance;
+
+ private FunctionValues[] valsArr;
+
+ public FunctionValuesAnonymousInnerClassHelper2(VectorValueSource outerInstance, FunctionValues[] valsArr)
+ {
+ this.outerInstance = outerInstance;
+ this.valsArr = valsArr;
+ }
+
+ public override void byteVal(int doc, sbyte[] vals)
+ {
+ for (int i = 0; i < valsArr.Length; i++)
+ {
+ vals[i] = valsArr[i].byteVal(doc);
+ }
+ }
+
+ public override void shortVal(int doc, short[] vals)
+ {
+ for (int i = 0; i < valsArr.Length; i++)
+ {
+ vals[i] = valsArr[i].shortVal(doc);
+ }
+ }
+
+ public override void floatVal(int doc, float[] vals)
+ {
+ for (int i = 0; i < valsArr.Length; i++)
+ {
+ vals[i] = valsArr[i].floatVal(doc);
+ }
+ }
+
+ public override void intVal(int doc, int[] vals)
+ {
+ for (int i = 0; i < valsArr.Length; i++)
+ {
+ vals[i] = valsArr[i].intVal(doc);
+ }
+ }
+
+ public override void longVal(int doc, long[] vals)
+ {
+ for (int i = 0; i < valsArr.Length; i++)
+ {
+ vals[i] = valsArr[i].longVal(doc);
+ }
+ }
+
+ public override void doubleVal(int doc, double[] vals)
+ {
+ for (int i = 0; i < valsArr.Length; i++)
+ {
+ vals[i] = valsArr[i].doubleVal(doc);
+ }
+ }
+
+ public override void strVal(int doc, string[] vals)
+ {
+ for (int i = 0; i < valsArr.Length; i++)
+ {
+ vals[i] = valsArr[i].strVal(doc);
+ }
+ }
+
+ public override string ToString(int doc)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(outerInstance.name()).Append('(');
+ bool firstTime = true;
+ foreach (FunctionValues vals in valsArr)
+ {
+ if (firstTime)
+ {
+ firstTime = false;
+ }
+ else
+ {
+ sb.Append(',');
+ }
+ sb.Append(vals.ToString(doc));
+ }
+ sb.Append(')');
+ return sb.ToString();
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ foreach (ValueSource source in sources)
+ {
+ source.createWeight(context, searcher);
+ }
+ }
+
+
+ public override string description()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(name()).Append('(');
+ bool firstTime = true;
+ foreach (ValueSource source in sources)
+ {
+ if (firstTime)
+ {
+ firstTime = false;
+ }
+ else
+ {
+ sb.Append(',');
+ }
+ sb.Append(source);
+ }
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (!(o is VectorValueSource))
+ {
+ return false;
+ }
+
+ VectorValueSource that = (VectorValueSource) o;
+
+ return sources.Equals(that.sources);
+
+ }
+
+ public override int GetHashCode()
+ {
+ return sources.GetHashCode();
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSourceScorer.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSourceScorer.cs b/src/Lucene.Net.Queries/Function/ValueSourceScorer.cs
new file mode 100644
index 0000000..fa79903
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSourceScorer.cs
@@ -0,0 +1,126 @@
+namespace org.apache.lucene.queries.function
+{
+
+ /*
+ * 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 IndexReader = org.apache.lucene.index.IndexReader;
+ using MultiFields = org.apache.lucene.index.MultiFields;
+ using Scorer = org.apache.lucene.search.Scorer;
+ using Bits = org.apache.lucene.util.Bits;
+
+ /// <summary>
+ /// <seealso cref="Scorer"/> which returns the result of <seealso cref="FunctionValues#floatVal(int)"/> as
+ /// the score for a document.
+ /// </summary>
+ public class ValueSourceScorer : Scorer
+ {
+ protected internal readonly IndexReader reader;
+ private int doc = -1;
+ protected internal readonly int maxDoc;
+ protected internal readonly FunctionValues values;
+ protected internal bool checkDeletes;
+ private readonly Bits liveDocs;
+
+ protected internal ValueSourceScorer(IndexReader reader, FunctionValues values) : base(null)
+ {
+ this.reader = reader;
+ this.maxDoc = reader.maxDoc();
+ this.values = values;
+ CheckDeletes = true;
+ this.liveDocs = MultiFields.getLiveDocs(reader);
+ }
+
+ public virtual IndexReader Reader
+ {
+ get
+ {
+ return reader;
+ }
+ }
+
+ public virtual bool CheckDeletes
+ {
+ set
+ {
+ this.checkDeletes = value && reader.hasDeletions();
+ }
+ }
+
+ public virtual bool matches(int doc)
+ {
+ return (!checkDeletes || liveDocs.get(doc)) && matchesValue(doc);
+ }
+
+ public virtual bool matchesValue(int doc)
+ {
+ return true;
+ }
+
+ public override int docID()
+ {
+ return doc;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int nextDoc() throws java.io.IOException
+ public override int nextDoc()
+ {
+ for (; ;)
+ {
+ doc++;
+ if (doc >= maxDoc)
+ {
+ return doc = NO_MORE_DOCS;
+ }
+ if (matches(doc))
+ {
+ return doc;
+ }
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int advance(int target) throws java.io.IOException
+ public override int advance(int target)
+ {
+ // also works fine when target==NO_MORE_DOCS
+ doc = target - 1;
+ return nextDoc();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public float score() throws java.io.IOException
+ public override float score()
+ {
+ return values.floatVal(doc);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int freq() throws java.io.IOException
+ public override int freq()
+ {
+ return 1;
+ }
+
+ public override long cost()
+ {
+ return maxDoc;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Lucene.Net.Queries.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Lucene.Net.Queries.csproj b/src/Lucene.Net.Queries/Lucene.Net.Queries.csproj
new file mode 100644
index 0000000..6856c74
--- /dev/null
+++ b/src/Lucene.Net.Queries/Lucene.Net.Queries.csproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{69D7956C-C2CC-4708-B399-A188FEC384C4}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Lucene.Net.Queries</RootNamespace>
+ <AssemblyName>Lucene.Net.Queries</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BooleanFilter.cs" />
+ <Compile Include="BoostingQuery.cs" />
+ <Compile Include="ChainedFilter.cs" />
+ <Compile Include="CommonTermsQuery.cs" />
+ <Compile Include="CustomScoreProvider.cs" />
+ <Compile Include="CustomScoreQuery.cs" />
+ <Compile Include="FilterClause.cs" />
+ <Compile Include="Function\BoostedQuery.cs" />
+ <Compile Include="Function\DocValues\BoolDocValues.cs" />
+ <Compile Include="Function\DocValues\DocTermsIndexDocValues.cs" />
+ <Compile Include="Function\DocValues\DoubleDocValues.cs" />
+ <Compile Include="Function\DocValues\FloatDocValues.cs" />
+ <Compile Include="Function\DocValues\IntDocValues.cs" />
+ <Compile Include="Function\DocValues\LongDocValues.cs" />
+ <Compile Include="Function\DocValues\StrDocValues.cs" />
+ <Compile Include="Function\FunctionQuery.cs" />
+ <Compile Include="Function\FunctionValues.cs" />
+ <Compile Include="Function\ValueSource.cs" />
+ <Compile Include="Function\ValueSourceScorer.cs" />
+ <Compile Include="Function\ValueSource\BoolFunction.cs" />
+ <Compile Include="Function\ValueSource\ByteFieldSource.cs" />
+ <Compile Include="Function\ValueSource\BytesRefFieldSource.cs" />
+ <Compile Include="Function\ValueSource\ConstNumberSource.cs" />
+ <Compile Include="Function\ValueSource\ConstValueSource.cs" />
+ <Compile Include="Function\ValueSource\DefFunction.cs" />
+ <Compile Include="Function\ValueSource\DivFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\DocFreqValueSource.cs" />
+ <Compile Include="Function\ValueSource\DoubleConstValueSource.cs" />
+ <Compile Include="Function\ValueSource\DoubleFieldSource.cs" />
+ <Compile Include="Function\ValueSource\DualFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\EnumFieldSource.cs" />
+ <Compile Include="Function\ValueSource\FieldCacheSource.cs" />
+ <Compile Include="Function\ValueSource\FloatFieldSource.cs" />
+ <Compile Include="Function\ValueSource\IDFValueSource.cs" />
+ <Compile Include="Function\ValueSource\IfFunction.cs" />
+ <Compile Include="Function\ValueSource\IntFieldSource.cs" />
+ <Compile Include="Function\ValueSource\JoinDocFreqValueSource.cs" />
+ <Compile Include="Function\ValueSource\LinearFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\LiteralValueSource.cs" />
+ <Compile Include="Function\ValueSource\LongFieldSource.cs" />
+ <Compile Include="Function\ValueSource\MaxDocValueSource.cs" />
+ <Compile Include="Function\ValueSource\MaxFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\MinFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\MultiBoolFunction.cs" />
+ <Compile Include="Function\ValueSource\MultiFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\MultiFunction.cs" />
+ <Compile Include="Function\ValueSource\MultiValueSource.cs" />
+ <Compile Include="Function\ValueSource\NormValueSource.cs" />
+ <Compile Include="Function\ValueSource\NumDocsValueSource.cs" />
+ <Compile Include="Function\ValueSource\OrdFieldSource.cs" />
+ <Compile Include="Function\ValueSource\PowFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\ProductFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\QueryValueSource.cs" />
+ <Compile Include="Function\ValueSource\RangeMapFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\ReciprocalFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\ReverseOrdFieldSource.cs" />
+ <Compile Include="Function\ValueSource\ScaleFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\ShortFieldSource.cs" />
+ <Compile Include="Function\ValueSource\SimpleBoolFunction.cs" />
+ <Compile Include="Function\ValueSource\SimpleFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\SingleFunction.cs" />
+ <Compile Include="Function\ValueSource\SumFloatFunction.cs" />
+ <Compile Include="Function\ValueSource\SumTotalTermFreqValueSource.cs" />
+ <Compile Include="Function\ValueSource\TermFreqValueSource.cs" />
+ <Compile Include="Function\ValueSource\TFValueSource.cs" />
+ <Compile Include="Function\ValueSource\TotalTermFreqValueSource.cs" />
+ <Compile Include="Function\ValueSource\VectorValueSource.cs" />
+ <Compile Include="Mlt\MoreLikeThis.cs" />
+ <Compile Include="Mlt\MoreLikeThisQuery.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TermFilter.cs" />
+ <Compile Include="TermsFilter.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Lucene.Net.Core\Lucene.Net.csproj">
+ <Project>{5d4ad9be-1ffb-41ab-9943-25737971bf57}</Project>
+ <Name>Lucene.Net</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Mlt/MoreLikeThis.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Mlt/MoreLikeThis.cs b/src/Lucene.Net.Queries/Mlt/MoreLikeThis.cs
new file mode 100644
index 0000000..1a25108
--- /dev/null
+++ b/src/Lucene.Net.Queries/Mlt/MoreLikeThis.cs
@@ -0,0 +1,981 @@
+using System.Collections.Generic;
+using System.Text;
+
+/// <summary>
+/// Copyright 2004-2005 The Apache Software Foundation.
+///
+/// Licensed 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.
+/// </summary>
+namespace org.apache.lucene.queries.mlt
+{
+
+
+ using Analyzer = org.apache.lucene.analysis.Analyzer;
+ using TokenStream = org.apache.lucene.analysis.TokenStream;
+ using CharTermAttribute = org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+ using Document = org.apache.lucene.document.Document;
+ using Fields = org.apache.lucene.index.Fields;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using IndexableField = org.apache.lucene.index.IndexableField;
+ using MultiFields = org.apache.lucene.index.MultiFields;
+ using Term = org.apache.lucene.index.Term;
+ using Terms = org.apache.lucene.index.Terms;
+ using TermsEnum = org.apache.lucene.index.TermsEnum;
+ using org.apache.lucene.search;
+ using DefaultSimilarity = org.apache.lucene.search.similarities.DefaultSimilarity;
+ using TFIDFSimilarity = org.apache.lucene.search.similarities.TFIDFSimilarity;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+ using CharsRef = org.apache.lucene.util.CharsRef;
+ using IOUtils = org.apache.lucene.util.IOUtils;
+ using PriorityQueue = org.apache.lucene.util.PriorityQueue;
+ using UnicodeUtil = org.apache.lucene.util.UnicodeUtil;
+
+
+ /// <summary>
+ /// Generate "more like this" similarity queries.
+ /// Based on this mail:
+ /// <code><pre>
+ /// Lucene does let you access the document frequency of terms, with IndexReader.docFreq().
+ /// Term frequencies can be computed by re-tokenizing the text, which, for a single document,
+ /// is usually fast enough. But looking up the docFreq() of every term in the document is
+ /// probably too slow.
+ /// <p/>
+ /// You can use some heuristics to prune the set of terms, to avoid calling docFreq() too much,
+ /// or at all. Since you're trying to maximize a tf*idf score, you're probably most interested
+ /// in terms with a high tf. Choosing a tf threshold even as low as two or three will radically
+ /// reduce the number of terms under consideration. Another heuristic is that terms with a
+ /// high idf (i.e., a low df) tend to be longer. So you could threshold the terms by the
+ /// number of characters, not selecting anything less than, e.g., six or seven characters.
+ /// With these sorts of heuristics you can usually find small set of, e.g., ten or fewer terms
+ /// that do a pretty good job of characterizing a document.
+ /// <p/>
+ /// It all depends on what you're trying to do. If you're trying to eek out that last percent
+ /// of precision and recall regardless of computational difficulty so that you can win a TREC
+ /// competition, then the techniques I mention above are useless. But if you're trying to
+ /// provide a "more like this" button on a search results page that does a decent job and has
+ /// good performance, such techniques might be useful.
+ /// <p/>
+ /// An efficient, effective "more-like-this" query generator would be a great contribution, if
+ /// anyone's interested. I'd imagine that it would take a Reader or a String (the document's
+ /// text), analyzer Analyzer, and return a set of representative terms using heuristics like those
+ /// above. The frequency and length thresholds could be parameters, etc.
+ /// <p/>
+ /// Doug
+ /// </pre></code>
+ /// <p/>
+ /// <p/>
+ /// <p/>
+ /// <h3>Initial Usage</h3>
+ /// <p/>
+ /// This class has lots of options to try to make it efficient and flexible.
+ /// The simplest possible usage is as follows. The bold
+ /// fragment is specific to this class.
+ /// <p/>
+ /// <pre class="prettyprint">
+ /// <p/>
+ /// IndexReader ir = ...
+ /// IndexSearcher is = ...
+ /// <p/>
+ /// MoreLikeThis mlt = new MoreLikeThis(ir);
+ /// Reader target = ... // orig source of doc you want to find similarities to
+ /// Query query = mlt.like( target);
+ /// <p/>
+ /// Hits hits = is.search(query);
+ /// // now the usual iteration thru 'hits' - the only thing to watch for is to make sure
+ /// //you ignore the doc if it matches your 'target' document, as it should be similar to itself
+ /// <p/>
+ /// </pre>
+ /// <p/>
+ /// Thus you:
+ /// <ol>
+ /// <li> do your normal, Lucene setup for searching,
+ /// <li> create a MoreLikeThis,
+ /// <li> get the text of the doc you want to find similarities to
+ /// <li> then call one of the like() calls to generate a similarity query
+ /// <li> call the searcher to find the similar docs
+ /// </ol>
+ /// <p/>
+ /// <h3>More Advanced Usage</h3>
+ /// <p/>
+ /// You may want to use <seealso cref="#setFieldNames setFieldNames(...)"/> so you can examine
+ /// multiple fields (e.g. body and title) for similarity.
+ /// <p/>
+ /// <p/>
+ /// Depending on the size of your index and the size and makeup of your documents you
+ /// may want to call the other set methods to control how the similarity queries are
+ /// generated:
+ /// <ul>
+ /// <li> <seealso cref="#setMinTermFreq setMinTermFreq(...)"/>
+ /// <li> <seealso cref="#setMinDocFreq setMinDocFreq(...)"/>
+ /// <li> <seealso cref="#setMaxDocFreq setMaxDocFreq(...)"/>
+ /// <li> <seealso cref="#setMaxDocFreqPct setMaxDocFreqPct(...)"/>
+ /// <li> <seealso cref="#setMinWordLen setMinWordLen(...)"/>
+ /// <li> <seealso cref="#setMaxWordLen setMaxWordLen(...)"/>
+ /// <li> <seealso cref="#setMaxQueryTerms setMaxQueryTerms(...)"/>
+ /// <li> <seealso cref="#setMaxNumTokensParsed setMaxNumTokensParsed(...)"/>
+ /// <li> <seealso cref="#setStopWords setStopWord(...)"/>
+ /// </ul>
+ /// <p/>
+ /// <hr>
+ /// <pre>
+ /// Changes: Mark Harwood 29/02/04
+ /// Some bugfixing, some refactoring, some optimisation.
+ /// - bugfix: retrieveTerms(int docNum) was not working for indexes without a termvector -added missing code
+ /// - bugfix: No significant terms being created for fields with a termvector - because
+ /// was only counting one occurrence per term/field pair in calculations(ie not including frequency info from TermVector)
+ /// - refactor: moved common code into isNoiseWord()
+ /// - optimise: when no termvector support available - used maxNumTermsParsed to limit amount of tokenization
+ /// </pre>
+ /// </summary>
+ public sealed class MoreLikeThis
+ {
+
+ /// <summary>
+ /// Default maximum number of tokens to parse in each example doc field that is not stored with TermVector support.
+ /// </summary>
+ /// <seealso cref= #getMaxNumTokensParsed </seealso>
+ public const int DEFAULT_MAX_NUM_TOKENS_PARSED = 5000;
+
+ /// <summary>
+ /// Ignore terms with less than this frequency in the source doc.
+ /// </summary>
+ /// <seealso cref= #getMinTermFreq </seealso>
+ /// <seealso cref= #setMinTermFreq </seealso>
+ public const int DEFAULT_MIN_TERM_FREQ = 2;
+
+ /// <summary>
+ /// Ignore words which do not occur in at least this many docs.
+ /// </summary>
+ /// <seealso cref= #getMinDocFreq </seealso>
+ /// <seealso cref= #setMinDocFreq </seealso>
+ public const int DEFAULT_MIN_DOC_FREQ = 5;
+
+ /// <summary>
+ /// Ignore words which occur in more than this many docs.
+ /// </summary>
+ /// <seealso cref= #getMaxDocFreq </seealso>
+ /// <seealso cref= #setMaxDocFreq </seealso>
+ /// <seealso cref= #setMaxDocFreqPct </seealso>
+ public static readonly int DEFAULT_MAX_DOC_FREQ = int.MaxValue;
+
+ /// <summary>
+ /// Boost terms in query based on score.
+ /// </summary>
+ /// <seealso cref= #isBoost </seealso>
+ /// <seealso cref= #setBoost </seealso>
+ public const bool DEFAULT_BOOST = false;
+
+ /// <summary>
+ /// Default field names. Null is used to specify that the field names should be looked
+ /// up at runtime from the provided reader.
+ /// </summary>
+ public static readonly string[] DEFAULT_FIELD_NAMES = new string[]{"contents"};
+
+ /// <summary>
+ /// Ignore words less than this length or if 0 then this has no effect.
+ /// </summary>
+ /// <seealso cref= #getMinWordLen </seealso>
+ /// <seealso cref= #setMinWordLen </seealso>
+ public const int DEFAULT_MIN_WORD_LENGTH = 0;
+
+ /// <summary>
+ /// Ignore words greater than this length or if 0 then this has no effect.
+ /// </summary>
+ /// <seealso cref= #getMaxWordLen </seealso>
+ /// <seealso cref= #setMaxWordLen </seealso>
+ public const int DEFAULT_MAX_WORD_LENGTH = 0;
+
+ /// <summary>
+ /// Default set of stopwords.
+ /// If null means to allow stop words.
+ /// </summary>
+ /// <seealso cref= #setStopWords </seealso>
+ /// <seealso cref= #getStopWords </seealso>
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: public static final Set<?> DEFAULT_STOP_WORDS = null;
+ public const HashSet<?> DEFAULT_STOP_WORDS = null;
+
+ /// <summary>
+ /// Current set of stop words.
+ /// </summary>
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: private Set<?> stopWords = DEFAULT_STOP_WORDS;
+ private HashSet<?> stopWords = DEFAULT_STOP_WORDS;
+
+ /// <summary>
+ /// Return a Query with no more than this many terms.
+ /// </summary>
+ /// <seealso cref= BooleanQuery#getMaxClauseCount </seealso>
+ /// <seealso cref= #getMaxQueryTerms </seealso>
+ /// <seealso cref= #setMaxQueryTerms </seealso>
+ public const int DEFAULT_MAX_QUERY_TERMS = 25;
+
+ /// <summary>
+ /// Analyzer that will be used to parse the doc.
+ /// </summary>
+ private Analyzer analyzer = null;
+
+ /// <summary>
+ /// Ignore words less frequent that this.
+ /// </summary>
+ private int minTermFreq = DEFAULT_MIN_TERM_FREQ;
+
+ /// <summary>
+ /// Ignore words which do not occur in at least this many docs.
+ /// </summary>
+ private int minDocFreq = DEFAULT_MIN_DOC_FREQ;
+
+ /// <summary>
+ /// Ignore words which occur in more than this many docs.
+ /// </summary>
+ private int maxDocFreq = DEFAULT_MAX_DOC_FREQ;
+
+ /// <summary>
+ /// Should we apply a boost to the Query based on the scores?
+ /// </summary>
+ private bool boost = DEFAULT_BOOST;
+
+ /// <summary>
+ /// Field name we'll analyze.
+ /// </summary>
+ private string[] fieldNames = DEFAULT_FIELD_NAMES;
+
+ /// <summary>
+ /// The maximum number of tokens to parse in each example doc field that is not stored with TermVector support
+ /// </summary>
+ private int maxNumTokensParsed = DEFAULT_MAX_NUM_TOKENS_PARSED;
+
+ /// <summary>
+ /// Ignore words if less than this len.
+ /// </summary>
+ private int minWordLen = DEFAULT_MIN_WORD_LENGTH;
+
+ /// <summary>
+ /// Ignore words if greater than this len.
+ /// </summary>
+ private int maxWordLen = DEFAULT_MAX_WORD_LENGTH;
+
+ /// <summary>
+ /// Don't return a query longer than this.
+ /// </summary>
+ private int maxQueryTerms = DEFAULT_MAX_QUERY_TERMS;
+
+ /// <summary>
+ /// For idf() calculations.
+ /// </summary>
+ private TFIDFSimilarity similarity; // = new DefaultSimilarity();
+
+ /// <summary>
+ /// IndexReader to use
+ /// </summary>
+ private readonly IndexReader ir;
+
+ /// <summary>
+ /// Boost factor to use when boosting the terms
+ /// </summary>
+ private float boostFactor = 1;
+
+ /// <summary>
+ /// Returns the boost factor used when boosting terms
+ /// </summary>
+ /// <returns> the boost factor used when boosting terms </returns>
+ /// <seealso cref= #setBoostFactor(float) </seealso>
+ public float BoostFactor
+ {
+ get
+ {
+ return boostFactor;
+ }
+ set
+ {
+ this.boostFactor = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Constructor requiring an IndexReader.
+ /// </summary>
+ public MoreLikeThis(IndexReader ir) : this(ir, new DefaultSimilarity())
+ {
+ }
+
+ public MoreLikeThis(IndexReader ir, TFIDFSimilarity sim)
+ {
+ this.ir = ir;
+ this.similarity = sim;
+ }
+
+
+ public TFIDFSimilarity Similarity
+ {
+ get
+ {
+ return similarity;
+ }
+ set
+ {
+ this.similarity = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Returns an analyzer that will be used to parse source doc with. The default analyzer
+ /// is not set.
+ /// </summary>
+ /// <returns> the analyzer that will be used to parse source doc with. </returns>
+ public Analyzer Analyzer
+ {
+ get
+ {
+ return analyzer;
+ }
+ set
+ {
+ this.analyzer = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Returns the frequency below which terms will be ignored in the source doc. The default
+ /// frequency is the <seealso cref="#DEFAULT_MIN_TERM_FREQ"/>.
+ /// </summary>
+ /// <returns> the frequency below which terms will be ignored in the source doc. </returns>
+ public int MinTermFreq
+ {
+ get
+ {
+ return minTermFreq;
+ }
+ set
+ {
+ this.minTermFreq = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Returns the frequency at which words will be ignored which do not occur in at least this
+ /// many docs. The default frequency is <seealso cref="#DEFAULT_MIN_DOC_FREQ"/>.
+ /// </summary>
+ /// <returns> the frequency at which words will be ignored which do not occur in at least this
+ /// many docs. </returns>
+ public int MinDocFreq
+ {
+ get
+ {
+ return minDocFreq;
+ }
+ set
+ {
+ this.minDocFreq = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Returns the maximum frequency in which words may still appear.
+ /// Words that appear in more than this many docs will be ignored. The default frequency is
+ /// <seealso cref="#DEFAULT_MAX_DOC_FREQ"/>.
+ /// </summary>
+ /// <returns> get the maximum frequency at which words are still allowed,
+ /// words which occur in more docs than this are ignored. </returns>
+ public int MaxDocFreq
+ {
+ get
+ {
+ return maxDocFreq;
+ }
+ set
+ {
+ this.maxDocFreq = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Set the maximum percentage in which words may still appear. Words that appear
+ /// in more than this many percent of all docs will be ignored.
+ /// </summary>
+ /// <param name="maxPercentage"> the maximum percentage of documents (0-100) that a term may appear
+ /// in to be still considered relevant </param>
+ public int MaxDocFreqPct
+ {
+ set
+ {
+ this.maxDocFreq = value * ir.numDocs() / 100;
+ }
+ }
+
+
+ /// <summary>
+ /// Returns whether to boost terms in query based on "score" or not. The default is
+ /// <seealso cref="#DEFAULT_BOOST"/>.
+ /// </summary>
+ /// <returns> whether to boost terms in query based on "score" or not. </returns>
+ /// <seealso cref= #setBoost </seealso>
+ public bool Boost
+ {
+ get
+ {
+ return boost;
+ }
+ set
+ {
+ this.boost = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Returns the field names that will be used when generating the 'More Like This' query.
+ /// The default field names that will be used is <seealso cref="#DEFAULT_FIELD_NAMES"/>.
+ /// </summary>
+ /// <returns> the field names that will be used when generating the 'More Like This' query. </returns>
+ public string[] FieldNames
+ {
+ get
+ {
+ return fieldNames;
+ }
+ set
+ {
+ this.fieldNames = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Returns the minimum word length below which words will be ignored. Set this to 0 for no
+ /// minimum word length. The default is <seealso cref="#DEFAULT_MIN_WORD_LENGTH"/>.
+ /// </summary>
+ /// <returns> the minimum word length below which words will be ignored. </returns>
+ public int MinWordLen
+ {
+ get
+ {
+ return minWordLen;
+ }
+ set
+ {
+ this.minWordLen = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Returns the maximum word length above which words will be ignored. Set this to 0 for no
+ /// maximum word length. The default is <seealso cref="#DEFAULT_MAX_WORD_LENGTH"/>.
+ /// </summary>
+ /// <returns> the maximum word length above which words will be ignored. </returns>
+ public int MaxWordLen
+ {
+ get
+ {
+ return maxWordLen;
+ }
+ set
+ {
+ this.maxWordLen = value;
+ }
+ }
+
+
+ /// <summary>
+ /// Set the set of stopwords.
+ /// Any word in this set is considered "uninteresting" and ignored.
+ /// Even if your Analyzer allows stopwords, you might want to tell the MoreLikeThis code to ignore them, as
+ /// for the purposes of document similarity it seems reasonable to assume that "a stop word is never interesting".
+ /// </summary>
+ /// <param name="stopWords"> set of stopwords, if null it means to allow stop words </param>
+ /// <seealso cref= #getStopWords </seealso>
+ public HashSet<T1> StopWords<T1>
+ {
+ set
+ {
+ this.stopWords = value;
+ }
+ get
+ {
+ return stopWords;
+ }
+ }
+
+
+
+ /// <summary>
+ /// Returns the maximum number of query terms that will be included in any generated query.
+ /// The default is <seealso cref="#DEFAULT_MAX_QUERY_TERMS"/>.
+ /// </summary>
+ /// <returns> the maximum number of query terms that will be included in any generated query. </returns>
+ public int MaxQueryTerms
+ {
+ get
+ {
+ return maxQueryTerms;
+ }
+ set
+ {
+ this.maxQueryTerms = value;
+ }
+ }
+
+
+ /// <returns> The maximum number of tokens to parse in each example doc field that is not stored with TermVector support </returns>
+ /// <seealso cref= #DEFAULT_MAX_NUM_TOKENS_PARSED </seealso>
+ public int MaxNumTokensParsed
+ {
+ get
+ {
+ return maxNumTokensParsed;
+ }
+ set
+ {
+ maxNumTokensParsed = value;
+ }
+ }
+
+
+
+ /// <summary>
+ /// Return a query that will return docs like the passed lucene document ID.
+ /// </summary>
+ /// <param name="docNum"> the documentID of the lucene doc to generate the 'More Like This" query for. </param>
+ /// <returns> a query that will return docs like the passed lucene document ID. </returns>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public Query like(int docNum) throws IOException
+ public Query like(int docNum)
+ {
+ if (fieldNames == null)
+ {
+ // gather list of valid fields from lucene
+ ICollection<string> fields = MultiFields.getIndexedFields(ir);
+ fieldNames = fields.toArray(new string[fields.Count]);
+ }
+
+ return createQuery(retrieveTerms(docNum));
+ }
+
+ /// <summary>
+ /// Return a query that will return docs like the passed Reader.
+ /// </summary>
+ /// <returns> a query that will return docs like the passed Reader. </returns>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public Query like(Reader r, String fieldName) throws IOException
+ public Query like(Reader r, string fieldName)
+ {
+ return createQuery(retrieveTerms(r, fieldName));
+ }
+
+ /// <summary>
+ /// Create the More like query from a PriorityQueue
+ /// </summary>
+ private Query createQuery(PriorityQueue<object[]> q)
+ {
+ BooleanQuery query = new BooleanQuery();
+ object cur;
+ int qterms = 0;
+ float bestScore = 0;
+
+ while ((cur = q.pop()) != null)
+ {
+ object[] ar = (object[]) cur;
+ TermQuery tq = new TermQuery(new Term((string) ar[1], (string) ar[0]));
+
+ if (boost)
+ {
+ if (qterms == 0)
+ {
+ bestScore = ((float?) ar[2]);
+ }
+ float myScore = ((float?) ar[2]);
+
+ tq.Boost = boostFactor * myScore / bestScore;
+ }
+
+ try
+ {
+ query.add(tq, BooleanClause.Occur.SHOULD);
+ }
+ catch (BooleanQuery.TooManyClauses)
+ {
+ break;
+ }
+
+ qterms++;
+ if (maxQueryTerms > 0 && qterms >= maxQueryTerms)
+ {
+ break;
+ }
+ }
+
+ return query;
+ }
+
+ /// <summary>
+ /// Create a PriorityQueue from a word->tf map.
+ /// </summary>
+ /// <param name="words"> a map of words keyed on the word(String) with Int objects as the values. </param>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private org.apache.lucene.util.PriorityQueue<Object[]> createQueue(Map<String, Int> words) throws IOException
+ private PriorityQueue<object[]> createQueue(IDictionary<string, Int> words)
+ {
+ // have collected all words in doc and their freqs
+ int numDocs = ir.numDocs();
+ FreqQ res = new FreqQ(words.Count); // will order words by score
+
+ foreach (string word in words.Keys) // for every word
+ {
+ int tf = words[word].x; // term freq in the source doc
+ if (minTermFreq > 0 && tf < minTermFreq)
+ {
+ continue; // filter out words that don't occur enough times in the source
+ }
+
+ // go through all the fields and find the largest document frequency
+ string topField = fieldNames[0];
+ int docFreq = 0;
+ foreach (string fieldName in fieldNames)
+ {
+ int freq = ir.docFreq(new Term(fieldName, word));
+ topField = (freq > docFreq) ? fieldName : topField;
+ docFreq = (freq > docFreq) ? freq : docFreq;
+ }
+
+ if (minDocFreq > 0 && docFreq < minDocFreq)
+ {
+ continue; // filter out words that don't occur in enough docs
+ }
+
+ if (docFreq > maxDocFreq)
+ {
+ continue; // filter out words that occur in too many docs
+ }
+
+ if (docFreq == 0)
+ {
+ continue; // index update problem?
+ }
+
+ float idf = similarity.idf(docFreq, numDocs);
+ float score = tf * idf;
+
+ // only really need 1st 3 entries, other ones are for troubleshooting
+ res.insertWithOverflow(new object[]{word, topField, score, idf, docFreq, tf}); // freq in all docs - idf - overall score - the top field - the word
+ }
+ return res;
+ }
+
+ /// <summary>
+ /// Describe the parameters that control how the "more like this" query is formed.
+ /// </summary>
+ public string describeParams()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("\t").Append("maxQueryTerms : ").Append(maxQueryTerms).Append("\n");
+ sb.Append("\t").Append("minWordLen : ").Append(minWordLen).Append("\n");
+ sb.Append("\t").Append("maxWordLen : ").Append(maxWordLen).Append("\n");
+ sb.Append("\t").Append("fieldNames : ");
+ string delim = "";
+ foreach (string fieldName in fieldNames)
+ {
+ sb.Append(delim).Append(fieldName);
+ delim = ", ";
+ }
+ sb.Append("\n");
+ sb.Append("\t").Append("boost : ").Append(boost).Append("\n");
+ sb.Append("\t").Append("minTermFreq : ").Append(minTermFreq).Append("\n");
+ sb.Append("\t").Append("minDocFreq : ").Append(minDocFreq).Append("\n");
+ return sb.ToString();
+ }
+
+ /// <summary>
+ /// Find words for a more-like-this query former.
+ /// </summary>
+ /// <param name="docNum"> the id of the lucene document from which to find terms </param>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public org.apache.lucene.util.PriorityQueue<Object[]> retrieveTerms(int docNum) throws IOException
+ public PriorityQueue<object[]> retrieveTerms(int docNum)
+ {
+ IDictionary<string, Int> termFreqMap = new Dictionary<string, Int>();
+ foreach (string fieldName in fieldNames)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.Fields vectors = ir.getTermVectors(docNum);
+ Fields vectors = ir.getTermVectors(docNum);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.Terms vector;
+ Terms vector;
+ if (vectors != null)
+ {
+ vector = vectors.terms(fieldName);
+ }
+ else
+ {
+ vector = null;
+ }
+
+ // field does not store term vector info
+ if (vector == null)
+ {
+ Document d = ir.document(docNum);
+ IndexableField[] fields = d.getFields(fieldName);
+ foreach (IndexableField field in fields)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final String stringValue = field.stringValue();
+ string stringValue = field.stringValue();
+ if (stringValue != null)
+ {
+ addTermFrequencies(new StringReader(stringValue), termFreqMap, fieldName);
+ }
+ }
+ }
+ else
+ {
+ addTermFrequencies(termFreqMap, vector);
+ }
+ }
+
+ return createQueue(termFreqMap);
+ }
+
+ /// <summary>
+ /// Adds terms and frequencies found in vector into the Map termFreqMap
+ /// </summary>
+ /// <param name="termFreqMap"> a Map of terms and their frequencies </param>
+ /// <param name="vector"> List of terms and their frequencies for a doc/field </param>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private void addTermFrequencies(Map<String, Int> termFreqMap, org.apache.lucene.index.Terms vector) throws IOException
+ private void addTermFrequencies(IDictionary<string, Int> termFreqMap, Terms vector)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.TermsEnum termsEnum = vector.iterator(null);
+ TermsEnum termsEnum = vector.iterator(null);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.CharsRef spare = new org.apache.lucene.util.CharsRef();
+ CharsRef spare = new CharsRef();
+ BytesRef text;
+ while ((text = termsEnum.next()) != null)
+ {
+ UnicodeUtil.UTF8toUTF16(text, spare);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final String term = spare.toString();
+ string term = spare.ToString();
+ if (isNoiseWord(term))
+ {
+ continue;
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int freq = (int) termsEnum.totalTermFreq();
+ int freq = (int) termsEnum.totalTermFreq();
+
+ // increment frequency
+ Int cnt = termFreqMap[term];
+ if (cnt == null)
+ {
+ cnt = new Int();
+ termFreqMap[term] = cnt;
+ cnt.x = freq;
+ }
+ else
+ {
+ cnt.x += freq;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Adds term frequencies found by tokenizing text from reader into the Map words
+ /// </summary>
+ /// <param name="r"> a source of text to be tokenized </param>
+ /// <param name="termFreqMap"> a Map of terms and their frequencies </param>
+ /// <param name="fieldName"> Used by analyzer for any special per-field analysis </param>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private void addTermFrequencies(Reader r, Map<String, Int> termFreqMap, String fieldName) throws IOException
+ private void addTermFrequencies(Reader r, IDictionary<string, Int> termFreqMap, string fieldName)
+ {
+ if (analyzer == null)
+ {
+ throw new System.NotSupportedException("To use MoreLikeThis without " + "term vectors, you must provide an Analyzer");
+ }
+ TokenStream ts = analyzer.tokenStream(fieldName, r);
+ try
+ {
+ int tokenCount = 0;
+ // for every token
+ CharTermAttribute termAtt = ts.addAttribute(typeof(CharTermAttribute));
+ ts.reset();
+ while (ts.incrementToken())
+ {
+ string word = termAtt.ToString();
+ tokenCount++;
+ if (tokenCount > maxNumTokensParsed)
+ {
+ break;
+ }
+ if (isNoiseWord(word))
+ {
+ continue;
+ }
+
+ // increment frequency
+ Int cnt = termFreqMap[word];
+ if (cnt == null)
+ {
+ termFreqMap[word] = new Int();
+ }
+ else
+ {
+ cnt.x++;
+ }
+ }
+ ts.end();
+ }
+ finally
+ {
+ IOUtils.closeWhileHandlingException(ts);
+ }
+ }
+
+
+ /// <summary>
+ /// determines if the passed term is likely to be of interest in "more like" comparisons
+ /// </summary>
+ /// <param name="term"> The word being considered </param>
+ /// <returns> true if should be ignored, false if should be used in further analysis </returns>
+ private bool isNoiseWord(string term)
+ {
+ int len = term.Length;
+ if (minWordLen > 0 && len < minWordLen)
+ {
+ return true;
+ }
+ if (maxWordLen > 0 && len > maxWordLen)
+ {
+ return true;
+ }
+ return stopWords != null && stopWords.Contains(term);
+ }
+
+
+ /// <summary>
+ /// Find words for a more-like-this query former.
+ /// The result is a priority queue of arrays with one entry for <b>every word</b> in the document.
+ /// Each array has 6 elements.
+ /// The elements are:
+ /// <ol>
+ /// <li> The word (String)
+ /// <li> The top field that this word comes from (String)
+ /// <li> The score for this word (Float)
+ /// <li> The IDF value (Float)
+ /// <li> The frequency of this word in the index (Integer)
+ /// <li> The frequency of this word in the source document (Integer)
+ /// </ol>
+ /// This is a somewhat "advanced" routine, and in general only the 1st entry in the array is of interest.
+ /// This method is exposed so that you can identify the "interesting words" in a document.
+ /// For an easier method to call see <seealso cref="#retrieveInterestingTerms retrieveInterestingTerms()"/>.
+ /// </summary>
+ /// <param name="r"> the reader that has the content of the document </param>
+ /// <param name="fieldName"> field passed to the analyzer to use when analyzing the content </param>
+ /// <returns> the most interesting words in the document ordered by score, with the highest scoring, or best entry, first </returns>
+ /// <seealso cref= #retrieveInterestingTerms </seealso>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public org.apache.lucene.util.PriorityQueue<Object[]> retrieveTerms(Reader r, String fieldName) throws IOException
+ public PriorityQueue<object[]> retrieveTerms(Reader r, string fieldName)
+ {
+ IDictionary<string, Int> words = new Dictionary<string, Int>();
+ addTermFrequencies(r, words, fieldName);
+ return createQueue(words);
+ }
+
+ /// <seealso cref= #retrieveInterestingTerms(java.io.Reader, String) </seealso>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public String[] retrieveInterestingTerms(int docNum) throws IOException
+ public string[] retrieveInterestingTerms(int docNum)
+ {
+ List<object> al = new List<object>(maxQueryTerms);
+ PriorityQueue<object[]> pq = retrieveTerms(docNum);
+ object cur;
+ int lim = maxQueryTerms; // have to be careful, retrieveTerms returns all words but that's probably not useful to our caller...
+ // we just want to return the top words
+ while (((cur = pq.pop()) != null) && lim-- > 0)
+ {
+ object[] ar = (object[]) cur;
+ al.Add(ar[0]); // the 1st entry is the interesting word
+ }
+ string[] res = new string[al.Count];
+ return al.toArray(res);
+ }
+
+ /// <summary>
+ /// Convenience routine to make it easy to return the most interesting words in a document.
+ /// More advanced users will call <seealso cref="#retrieveTerms(Reader, String) retrieveTerms()"/> directly.
+ /// </summary>
+ /// <param name="r"> the source document </param>
+ /// <param name="fieldName"> field passed to analyzer to use when analyzing the content </param>
+ /// <returns> the most interesting words in the document </returns>
+ /// <seealso cref= #retrieveTerms(java.io.Reader, String) </seealso>
+ /// <seealso cref= #setMaxQueryTerms </seealso>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public String[] retrieveInterestingTerms(Reader r, String fieldName) throws IOException
+ public string[] retrieveInterestingTerms(Reader r, string fieldName)
+ {
+ List<object> al = new List<object>(maxQueryTerms);
+ PriorityQueue<object[]> pq = retrieveTerms(r, fieldName);
+ object cur;
+ int lim = maxQueryTerms; // have to be careful, retrieveTerms returns all words but that's probably not useful to our caller...
+ // we just want to return the top words
+ while (((cur = pq.pop()) != null) && lim-- > 0)
+ {
+ object[] ar = (object[]) cur;
+ al.Add(ar[0]); // the 1st entry is the interesting word
+ }
+ string[] res = new string[al.Count];
+ return al.toArray(res);
+ }
+
+ /// <summary>
+ /// PriorityQueue that orders words by score.
+ /// </summary>
+ private class FreqQ : PriorityQueue<object[]>
+ {
+ internal FreqQ(int s) : base(s)
+ {
+ }
+
+ protected internal override bool lessThan(object[] aa, object[] bb)
+ {
+ float? fa = (float?) aa[2];
+ float? fb = (float?) bb[2];
+ return fa > fb;
+ }
+ }
+
+ /// <summary>
+ /// Use for frequencies and to avoid renewing Integers.
+ /// </summary>
+ private class Int
+ {
+ internal int x;
+
+ internal Int()
+ {
+ x = 1;
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Mlt/MoreLikeThisQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Mlt/MoreLikeThisQuery.cs b/src/Lucene.Net.Queries/Mlt/MoreLikeThisQuery.cs
new file mode 100644
index 0000000..d397720
--- /dev/null
+++ b/src/Lucene.Net.Queries/Mlt/MoreLikeThisQuery.cs
@@ -0,0 +1,297 @@
+using System.Collections.Generic;
+
+/*
+ * Created on 25-Jan-2006
+ */
+namespace org.apache.lucene.queries.mlt
+{
+
+ /*
+ * 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 Analyzer = org.apache.lucene.analysis.Analyzer;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using BooleanClause = org.apache.lucene.search.BooleanClause;
+ using BooleanQuery = org.apache.lucene.search.BooleanQuery;
+ using Query = org.apache.lucene.search.Query;
+
+
+ /// <summary>
+ /// A simple wrapper for MoreLikeThis for use in scenarios where a Query object is required eg
+ /// in custom QueryParser extensions. At query.rewrite() time the reader is used to construct the
+ /// actual MoreLikeThis object and obtain the real Query object.
+ /// </summary>
+ public class MoreLikeThisQuery : Query
+ {
+
+ private string likeText;
+ private string[] moreLikeFields;
+ private Analyzer analyzer;
+ private readonly string fieldName;
+ private float percentTermsToMatch = 0.3f;
+ private int minTermFrequency = 1;
+ private int maxQueryTerms = 5;
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: private java.util.Set<?> stopWords = null;
+ private HashSet<?> stopWords = null;
+ private int minDocFreq = -1;
+
+ /// <param name="moreLikeFields"> fields used for similarity measure </param>
+ public MoreLikeThisQuery(string likeText, string[] moreLikeFields, Analyzer analyzer, string fieldName)
+ {
+ this.likeText = likeText;
+ this.moreLikeFields = moreLikeFields;
+ this.analyzer = analyzer;
+ this.fieldName = fieldName;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.Query rewrite(org.apache.lucene.index.IndexReader reader) throws java.io.IOException
+ public override Query rewrite(IndexReader reader)
+ {
+ MoreLikeThis mlt = new MoreLikeThis(reader);
+
+ mlt.FieldNames = moreLikeFields;
+ mlt.Analyzer = analyzer;
+ mlt.MinTermFreq = minTermFrequency;
+ if (minDocFreq >= 0)
+ {
+ mlt.MinDocFreq = minDocFreq;
+ }
+ mlt.MaxQueryTerms = maxQueryTerms;
+ mlt.StopWords = stopWords;
+ BooleanQuery bq = (BooleanQuery) mlt.like(new StringReader(likeText), fieldName);
+ BooleanClause[] clauses = bq.Clauses;
+ //make at least half the terms match
+ bq.MinimumNumberShouldMatch = (int)(clauses.Length * percentTermsToMatch);
+ return bq;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.lucene.search.Query#toString(java.lang.String)
+ */
+ public override string ToString(string field)
+ {
+ return "like:" + likeText;
+ }
+
+ public virtual float PercentTermsToMatch
+ {
+ get
+ {
+ return percentTermsToMatch;
+ }
+ set
+ {
+ this.percentTermsToMatch = value;
+ }
+ }
+
+
+ public virtual Analyzer Analyzer
+ {
+ get
+ {
+ return analyzer;
+ }
+ set
+ {
+ this.analyzer = value;
+ }
+ }
+
+
+ public virtual string LikeText
+ {
+ get
+ {
+ return likeText;
+ }
+ set
+ {
+ this.likeText = value;
+ }
+ }
+
+
+ public virtual int MaxQueryTerms
+ {
+ get
+ {
+ return maxQueryTerms;
+ }
+ set
+ {
+ this.maxQueryTerms = value;
+ }
+ }
+
+
+ public virtual int MinTermFrequency
+ {
+ get
+ {
+ return minTermFrequency;
+ }
+ set
+ {
+ this.minTermFrequency = value;
+ }
+ }
+
+
+ public virtual string[] MoreLikeFields
+ {
+ get
+ {
+ return moreLikeFields;
+ }
+ set
+ {
+ this.moreLikeFields = value;
+ }
+ }
+
+
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: public java.util.Set<?> getStopWords()
+ public virtual HashSet<?> StopWords
+ {
+ get
+ {
+ return stopWords;
+ }
+ set
+ {
+ this.stopWords = value;
+ }
+ }
+
+
+ public virtual int MinDocFreq
+ {
+ get
+ {
+ return minDocFreq;
+ }
+ set
+ {
+ this.minDocFreq = value;
+ }
+ }
+
+
+ public override int GetHashCode()
+ {
+ const int prime = 31;
+ int result = base.GetHashCode();
+ result = prime * result + ((analyzer == null) ? 0 : analyzer.GetHashCode());
+ result = prime * result + ((fieldName == null) ? 0 : fieldName.GetHashCode());
+ result = prime * result + ((likeText == null) ? 0 : likeText.GetHashCode());
+ result = prime * result + maxQueryTerms;
+ result = prime * result + minDocFreq;
+ result = prime * result + minTermFrequency;
+ result = prime * result + Arrays.GetHashCode(moreLikeFields);
+ result = prime * result + float.floatToIntBits(percentTermsToMatch);
+ result = prime * result + ((stopWords == null) ? 0 : stopWords.GetHashCode());
+ return result;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!base.Equals(obj))
+ {
+ return false;
+ }
+ if (this.GetType() != obj.GetType())
+ {
+ return false;
+ }
+ MoreLikeThisQuery other = (MoreLikeThisQuery) obj;
+ if (analyzer == null)
+ {
+ if (other.analyzer != null)
+ {
+ return false;
+ }
+ }
+ else if (!analyzer.Equals(other.analyzer))
+ {
+ return false;
+ }
+ if (fieldName == null)
+ {
+ if (other.fieldName != null)
+ {
+ return false;
+ }
+ }
+ else if (!fieldName.Equals(other.fieldName))
+ {
+ return false;
+ }
+ if (likeText == null)
+ {
+ if (other.likeText != null)
+ {
+ return false;
+ }
+ }
+ else if (!likeText.Equals(other.likeText))
+ {
+ return false;
+ }
+ if (maxQueryTerms != other.maxQueryTerms)
+ {
+ return false;
+ }
+ if (minDocFreq != other.minDocFreq)
+ {
+ return false;
+ }
+ if (minTermFrequency != other.minTermFrequency)
+ {
+ return false;
+ }
+ if (!Arrays.Equals(moreLikeFields, other.moreLikeFields))
+ {
+ return false;
+ }
+ if (float.floatToIntBits(percentTermsToMatch) != float.floatToIntBits(other.percentTermsToMatch))
+ {
+ return false;
+ }
+ if (stopWords == null)
+ {
+ if (other.stopWords != null)
+ {
+ return false;
+ }
+ }
+ else if (!stopWords.Equals(other.stopWords))
+ {
+ return false;
+ }
+ return true;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Properties/AssemblyInfo.cs b/src/Lucene.Net.Queries/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d8e310e
--- /dev/null
+++ b/src/Lucene.Net.Queries/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Lucene.Net.Queries")]
+[assembly: AssemblyDescription("Filters and Queries that add to core Lucene")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Lucene.Net.Queries")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("76a14bc5-8f0f-4de4-b501-423d4c1a20a5")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
[07/11] git commit: Skeleton porting of Lucene.Net.Queries
Posted by sy...@apache.org.
Skeleton porting of Lucene.Net.Queries
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/882f487d
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/882f487d
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/882f487d
Branch: refs/heads/master
Commit: 882f487db71361a68ed4c78308f02bd0f82cf75b
Parents: 895be41
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Tue Sep 16 01:34:54 2014 +0300
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Tue Sep 16 01:34:54 2014 +0300
----------------------------------------------------------------------
src/Lucene.Net.Queries/BooleanFilter.cs | 204 ++++
src/Lucene.Net.Queries/BoostingQuery.cs | 178 ++++
src/Lucene.Net.Queries/ChainedFilter.cs | 285 ++++++
src/Lucene.Net.Queries/CommonTermsQuery.cs | 526 ++++++++++
src/Lucene.Net.Queries/CustomScoreProvider.cs | 192 ++++
src/Lucene.Net.Queries/CustomScoreQuery.cs | 490 +++++++++
src/Lucene.Net.Queries/FilterClause.cs | 97 ++
src/Lucene.Net.Queries/Function/BoostedQuery.cs | 287 ++++++
.../Function/DocValues/BoolDocValues.cs | 122 +++
.../DocValues/DocTermsIndexDocValues.cs | 234 +++++
.../Function/DocValues/DoubleDocValues.cs | 256 +++++
.../Function/DocValues/FloatDocValues.cs | 117 +++
.../Function/DocValues/IntDocValues.cs | 183 ++++
.../Function/DocValues/LongDocValues.cs | 193 ++++
.../Function/DocValues/StrDocValues.cs | 89 ++
.../Function/FunctionQuery.cs | 270 +++++
.../Function/FunctionValues.cs | 362 +++++++
src/Lucene.Net.Queries/Function/ValueSource.cs | 223 +++++
.../Function/ValueSource/BoolFunction.cs | 30 +
.../Function/ValueSource/ByteFieldSource.cs | 142 +++
.../Function/ValueSource/BytesRefFieldSource.cs | 140 +++
.../Function/ValueSource/ConstNumberSource.cs | 34 +
.../Function/ValueSource/ConstValueSource.cs | 156 +++
.../Function/ValueSource/DefFunction.cs | 153 +++
.../Function/ValueSource/DivFloatFunction.cs | 44 +
.../Function/ValueSource/DocFreqValueSource.cs | 186 ++++
.../ValueSource/DoubleConstValueSource.cs | 166 ++++
.../Function/ValueSource/DoubleFieldSource.cs | 149 +++
.../Function/ValueSource/DualFloatFunction.cs | 121 +++
.../Function/ValueSource/EnumFieldSource.cs | 343 +++++++
.../Function/ValueSource/FieldCacheSource.cs | 77 ++
.../Function/ValueSource/FloatFieldSource.cs | 152 +++
.../Function/ValueSource/IDFValueSource.cs | 85 ++
.../Function/ValueSource/IfFunction.cs | 186 ++++
.../Function/ValueSource/IntFieldSource.cs | 183 ++++
.../ValueSource/JoinDocFreqValueSource.cs | 134 +++
.../Function/ValueSource/LinearFloatFunction.cs | 113 +++
.../Function/ValueSource/LiteralValueSource.cs | 117 +++
.../Function/ValueSource/LongFieldSource.cs | 184 ++++
.../Function/ValueSource/MaxDocValueSource.cs | 70 ++
.../Function/ValueSource/MaxFloatFunction.cs | 53 +
.../Function/ValueSource/MinFloatFunction.cs | 53 +
.../Function/ValueSource/MultiBoolFunction.cs | 148 +++
.../Function/ValueSource/MultiFloatFunction.cs | 146 +++
.../Function/ValueSource/MultiFunction.cs | 161 +++
.../Function/ValueSource/MultiValueSource.cs | 32 +
.../Function/ValueSource/NormValueSource.cs | 125 +++
.../Function/ValueSource/NumDocsValueSource.cs | 63 ++
.../Function/ValueSource/OrdFieldSource.cs | 175 ++++
.../Function/ValueSource/PowFloatFunction.cs | 48 +
.../ValueSource/ProductFloatFunction.cs | 47 +
.../Function/ValueSource/QueryValueSource.cs | 328 +++++++
.../ValueSource/RangeMapFloatFunction.cs | 138 +++
.../ValueSource/ReciprocalFloatFunction.cs | 130 +++
.../ValueSource/ReverseOrdFieldSource.cs | 135 +++
.../Function/ValueSource/ScaleFloatFunction.cs | 200 ++++
.../Function/ValueSource/ShortFieldSource.cs | 137 +++
.../Function/ValueSource/SimpleBoolFunction.cs | 108 ++
.../Function/ValueSource/SimpleFloatFunction.cs | 71 ++
.../Function/ValueSource/SingleFunction.cs | 67 ++
.../Function/ValueSource/SumFloatFunction.cs | 46 +
.../ValueSource/SumTotalTermFreqValueSource.cs | 132 +++
.../Function/ValueSource/TFValueSource.cs | 197 ++++
.../Function/ValueSource/TermFreqValueSource.cs | 186 ++++
.../ValueSource/TotalTermFreqValueSource.cs | 127 +++
.../Function/ValueSource/VectorValueSource.cs | 293 ++++++
.../Function/ValueSourceScorer.cs | 126 +++
.../Lucene.Net.Queries.csproj | 129 +++
src/Lucene.Net.Queries/Mlt/MoreLikeThis.cs | 981 +++++++++++++++++++
src/Lucene.Net.Queries/Mlt/MoreLikeThisQuery.cs | 297 ++++++
.../Properties/AssemblyInfo.cs | 35 +
src/Lucene.Net.Queries/TermFilter.cs | 139 +++
src/Lucene.Net.Queries/TermsFilter.cs | 439 +++++++++
73 files changed, 12765 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/BooleanFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/BooleanFilter.cs b/src/Lucene.Net.Queries/BooleanFilter.cs
new file mode 100644
index 0000000..bcbc6fb
--- /dev/null
+++ b/src/Lucene.Net.Queries/BooleanFilter.cs
@@ -0,0 +1,204 @@
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using org.apache.lucene.queries;
+
+namespace Lucene.Net.Queries
+{
+
+ /*
+ * 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.
+ */
+ /// <summary>
+ /// A container Filter that allows Boolean composition of Filters.
+ /// Filters are allocated into one of three logical constructs;
+ /// SHOULD, MUST NOT, MUST
+ /// The results Filter BitSet is constructed as follows:
+ /// SHOULD Filters are OR'd together
+ /// The resulting Filter is NOT'd with the NOT Filters
+ /// The resulting Filter is AND'd with the MUST Filters
+ /// </summary>
+ public class BooleanFilter : Filter, IEnumerable<FilterClause>
+ {
+
+ private readonly IList<FilterClause> clauses_Renamed = new List<FilterClause>();
+
+ /// <summary>
+ /// Returns the a DocIdSetIterator representing the Boolean composition
+ /// of the filters that have been added.
+ /// </summary>
+ public override DocIdSet GetDocIdSet(AtomicReaderContext context, Bits acceptDocs)
+ {
+ FixedBitSet res = null;
+ AtomicReader reader = context.reader();
+
+ bool hasShouldClauses = false;
+ foreach (FilterClause fc in clauses_Renamed)
+ {
+ if (fc.Occur == BooleanClause.Occur.SHOULD)
+ {
+ hasShouldClauses = true;
+ DocIdSetIterator disi = getDISI(fc.Filter, context);
+ if (disi == null)
+ {
+ continue;
+ }
+ if (res == null)
+ {
+ res = new FixedBitSet(reader.MaxDoc());
+ }
+ res.or(disi);
+ }
+ }
+ if (hasShouldClauses && res == null)
+ {
+ return null;
+ }
+
+ foreach (FilterClause fc in clauses_Renamed)
+ {
+ if (fc.Occur == BooleanClause.Occur.MUST_NOT)
+ {
+ if (res == null)
+ {
+ Debug.Assert(!hasShouldClauses);
+ res = new FixedBitSet(reader.MaxDoc());
+ res.Set(0, reader.MaxDoc()); // NOTE: may set bits on deleted docs
+ }
+
+ DocIdSetIterator disi = GetDISI(fc.Filter, context);
+ if (disi != null)
+ {
+ res.AndNot(disi);
+ }
+ }
+ }
+
+ foreach (FilterClause fc in clauses_Renamed)
+ {
+ if (fc.Occur == BooleanClause.Occur.MUST)
+ {
+ DocIdSetIterator disi = GetDISI(fc.Filter, context);
+ if (disi == null)
+ {
+ return null; // no documents can match
+ }
+ if (res == null)
+ {
+ res = new FixedBitSet(reader.maxDoc());
+ res.or(disi);
+ }
+ else
+ {
+ res.and(disi);
+ }
+ }
+ }
+
+ return BitsFilteredDocIdSet.wrap(res, acceptDocs);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private static org.apache.lucene.search.DocIdSetIterator getDISI(org.apache.lucene.search.Filter filter, org.apache.lucene.index.AtomicReaderContext context) throws java.io.IOException
+ private static DocIdSetIterator GetDISI(Filter filter, AtomicReaderContext context)
+ {
+ // we dont pass acceptDocs, we will filter at the end using an additional filter
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.DocIdSet set = filter.getDocIdSet(context, null);
+ DocIdSet set = filter.GetDocIdSet(context, null);
+ return set == null ? null : set.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Adds a new FilterClause to the Boolean Filter container </summary>
+ /// <param name="filterClause"> A FilterClause object containing a Filter and an Occur parameter </param>
+ public virtual void Add(FilterClause filterClause)
+ {
+ clauses_Renamed.Add(filterClause);
+ }
+
+ public void Add(Filter filter, BooleanClause.Occur occur)
+ {
+ Add(new FilterClause(filter, occur));
+ }
+
+ /// <summary>
+ /// Returns the list of clauses
+ /// </summary>
+ public virtual IList<FilterClause> clauses()
+ {
+ return clauses_Renamed;
+ }
+
+ /// <summary>
+ /// Returns an iterator on the clauses in this query. It implements the <seealso cref="Iterable"/> interface to
+ /// make it possible to do:
+ /// <pre class="prettyprint">for (FilterClause clause : booleanFilter) {}</pre>
+ /// </summary>
+ public IEnumerator<FilterClause> GetEnumerator()
+ {
+ return clauses().GetEnumerator();
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+
+ if ((obj == null) || (obj.GetType() != this.GetType()))
+ {
+ return false;
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final BooleanFilter other = (BooleanFilter)obj;
+ BooleanFilter other = (BooleanFilter)obj;
+ return clauses_Renamed.Equals(other.clauses_Renamed);
+ }
+
+ public override int GetHashCode()
+ {
+ return 657153718 ^ clauses_Renamed.GetHashCode();
+ }
+
+ /// <summary>
+ /// Prints a user-readable version of this Filter. </summary>
+ public override string ToString()
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final StringBuilder buffer = new StringBuilder("BooleanFilter(");
+ StringBuilder buffer = new StringBuilder("BooleanFilter(");
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int minLen = buffer.length();
+ int minLen = buffer.Length;
+ foreach (FilterClause c in clauses_Renamed)
+ {
+ if (buffer.Length > minLen)
+ {
+ buffer.Append(' ');
+ }
+ buffer.Append(c);
+ }
+ return buffer.Append(')').ToString();
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/BoostingQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/BoostingQuery.cs b/src/Lucene.Net.Queries/BoostingQuery.cs
new file mode 100644
index 0000000..203a2ae
--- /dev/null
+++ b/src/Lucene.Net.Queries/BoostingQuery.cs
@@ -0,0 +1,178 @@
+namespace org.apache.lucene.queries
+{
+
+ /*
+ * 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 IndexReader = org.apache.lucene.index.IndexReader;
+ using org.apache.lucene.search;
+
+ /// <summary>
+ /// The BoostingQuery class can be used to effectively demote results that match a given query.
+ /// Unlike the "NOT" clause, this still selects documents that contain undesirable terms,
+ /// but reduces their overall score:
+ ///
+ /// Query balancedQuery = new BoostingQuery(positiveQuery, negativeQuery, 0.01f);
+ /// In this scenario the positiveQuery contains the mandatory, desirable criteria which is used to
+ /// select all matching documents, and the negativeQuery contains the undesirable elements which
+ /// are simply used to lessen the scores. Documents that match the negativeQuery have their score
+ /// multiplied by the supplied "boost" parameter, so this should be less than 1 to achieve a
+ /// demoting effect
+ ///
+ /// This code was originally made available here: [WWW] http://marc.theaimsgroup.com/?l=lucene-user&m=108058407130459&w=2
+ /// and is documented here: http://wiki.apache.org/lucene-java/CommunityContributions
+ /// </summary>
+ public class BoostingQuery : Query
+ {
+ private readonly float boost; // the amount to boost by
+ private readonly Query match; // query to match
+ private readonly Query context; // boost when matches too
+
+ public BoostingQuery(Query match, Query context, float boost)
+ {
+ this.match = match;
+ this.context = context.clone(); // clone before boost
+ this.boost = boost;
+ this.context.Boost = 0.0f; // ignore context-only matches
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Query rewrite(org.apache.lucene.index.IndexReader reader) throws java.io.IOException
+ public override Query rewrite(IndexReader reader)
+ {
+ BooleanQuery result = new BooleanQueryAnonymousInnerClassHelper(this);
+
+ result.add(match, BooleanClause.Occur.MUST);
+ result.add(context, BooleanClause.Occur.SHOULD);
+
+ return result;
+ }
+
+ private class BooleanQueryAnonymousInnerClassHelper : BooleanQuery
+ {
+ private readonly BoostingQuery outerInstance;
+
+ public BooleanQueryAnonymousInnerClassHelper(BoostingQuery outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Weight createWeight(IndexSearcher searcher) throws java.io.IOException
+ public override Weight createWeight(IndexSearcher searcher)
+ {
+ return new BooleanWeightAnonymousInnerClassHelper(this, searcher);
+ }
+
+ private class BooleanWeightAnonymousInnerClassHelper : BooleanWeight
+ {
+ private readonly BooleanQueryAnonymousInnerClassHelper outerInstance;
+
+ public BooleanWeightAnonymousInnerClassHelper(BooleanQueryAnonymousInnerClassHelper outerInstance, IndexSearcher searcher) : base(searcher, false)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+
+ public override float coord(int overlap, int max)
+ {
+ switch (overlap)
+ {
+
+ case 1: // matched only one clause
+ return 1.0f; // use the score as-is
+
+ case 2: // matched both clauses
+ return outerInstance.outerInstance.boost; // multiply by boost
+
+ default:
+ return 0.0f;
+
+ }
+ }
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ const int prime = 31;
+ int result = base.GetHashCode();
+ result = prime * result + float.floatToIntBits(boost);
+ result = prime * result + ((context == null) ? 0 : context.GetHashCode());
+ result = prime * result + ((match == null) ? 0 : match.GetHashCode());
+ return result;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (this.GetType() != obj.GetType())
+ {
+ return false;
+ }
+
+ if (!base.Equals(obj))
+ {
+ return false;
+ }
+
+ BoostingQuery other = (BoostingQuery) obj;
+ if (float.floatToIntBits(boost) != float.floatToIntBits(other.boost))
+ {
+ return false;
+ }
+
+ if (context == null)
+ {
+ if (other.context != null)
+ {
+ return false;
+ }
+ }
+ else if (!context.Equals(other.context))
+ {
+ return false;
+ }
+
+ if (match == null)
+ {
+ if (other.match != null)
+ {
+ return false;
+ }
+ }
+ else if (!match.Equals(other.match))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public override string ToString(string field)
+ {
+ return match.ToString(field) + "/" + context.ToString(field);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/ChainedFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/ChainedFilter.cs b/src/Lucene.Net.Queries/ChainedFilter.cs
new file mode 100644
index 0000000..c6aec63
--- /dev/null
+++ b/src/Lucene.Net.Queries/ChainedFilter.cs
@@ -0,0 +1,285 @@
+using System.Text;
+
+namespace org.apache.lucene.queries
+{
+
+ /*
+ * 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 AtomicReader = org.apache.lucene.index.AtomicReader;
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using BitsFilteredDocIdSet = org.apache.lucene.search.BitsFilteredDocIdSet;
+ using DocIdSet = org.apache.lucene.search.DocIdSet;
+ using DocIdSetIterator = org.apache.lucene.search.DocIdSetIterator;
+ using Filter = org.apache.lucene.search.Filter;
+ using Bits = org.apache.lucene.util.Bits;
+ using FixedBitSet = org.apache.lucene.util.FixedBitSet;
+
+ /// <summary>
+ /// <para>
+ /// Allows multiple <seealso cref="Filter"/>s to be chained.
+ /// Logical operations such as <b>NOT</b> and <b>XOR</b>
+ /// are applied between filters. One operation can be used
+ /// for all filters, or a specific operation can be declared
+ /// for each filter.
+ /// </para>
+ /// <para>
+ /// Order in which filters are called depends on
+ /// the position of the filter in the chain. It's probably
+ /// more efficient to place the most restrictive filters
+ /// /least computationally-intensive filters first.
+ /// </para>
+ /// </summary>
+ public class ChainedFilter : Filter
+ {
+
+ public const int OR = 0;
+ public const int AND = 1;
+ public const int ANDNOT = 2;
+ public const int XOR = 3;
+ /// <summary>
+ /// Logical operation when none is declared. Defaults to OR.
+ /// </summary>
+ public const int DEFAULT = OR;
+
+ /// <summary>
+ /// The filter chain
+ /// </summary>
+ private Filter[] chain = null;
+
+ private int[] logicArray;
+
+ private int logic = -1;
+
+ /// <summary>
+ /// Ctor.
+ /// </summary>
+ /// <param name="chain"> The chain of filters </param>
+ public ChainedFilter(Filter[] chain)
+ {
+ this.chain = chain;
+ }
+
+ /// <summary>
+ /// Ctor.
+ /// </summary>
+ /// <param name="chain"> The chain of filters </param>
+ /// <param name="logicArray"> Logical operations to apply between filters </param>
+ public ChainedFilter(Filter[] chain, int[] logicArray)
+ {
+ this.chain = chain;
+ this.logicArray = logicArray;
+ }
+
+ /// <summary>
+ /// Ctor.
+ /// </summary>
+ /// <param name="chain"> The chain of filters </param>
+ /// <param name="logic"> Logical operation to apply to ALL filters </param>
+ public ChainedFilter(Filter[] chain, int logic)
+ {
+ this.chain = chain;
+ this.logic = logic;
+ }
+
+ /// <summary>
+ /// <seealso cref="Filter#getDocIdSet"/>.
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.DocIdSet getDocIdSet(org.apache.lucene.index.AtomicReaderContext context, org.apache.lucene.util.Bits acceptDocs) throws java.io.IOException
+ public override DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs)
+ {
+ int[] index = new int[1]; // use array as reference to modifiable int;
+ index[0] = 0; // an object attribute would not be thread safe.
+ if (logic != -1)
+ {
+ return BitsFilteredDocIdSet.wrap(getDocIdSet(context, logic, index), acceptDocs);
+ }
+ else if (logicArray != null)
+ {
+ return BitsFilteredDocIdSet.wrap(getDocIdSet(context, logicArray, index), acceptDocs);
+ }
+
+ return BitsFilteredDocIdSet.wrap(getDocIdSet(context, DEFAULT, index), acceptDocs);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private org.apache.lucene.search.DocIdSetIterator getDISI(org.apache.lucene.search.Filter filter, org.apache.lucene.index.AtomicReaderContext context) throws java.io.IOException
+ private DocIdSetIterator getDISI(Filter filter, AtomicReaderContext context)
+ {
+ // we dont pass acceptDocs, we will filter at the end using an additional filter
+ DocIdSet docIdSet = filter.getDocIdSet(context, null);
+ if (docIdSet == null)
+ {
+ return DocIdSetIterator.empty();
+ }
+ else
+ {
+ DocIdSetIterator iter = docIdSet.GetEnumerator();
+ if (iter == null)
+ {
+ return DocIdSetIterator.empty();
+ }
+ else
+ {
+ return iter;
+ }
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private org.apache.lucene.util.FixedBitSet initialResult(org.apache.lucene.index.AtomicReaderContext context, int logic, int[] index) throws java.io.IOException
+ private FixedBitSet initialResult(AtomicReaderContext context, int logic, int[] index)
+ {
+ AtomicReader reader = context.reader();
+ FixedBitSet result = new FixedBitSet(reader.maxDoc());
+ if (logic == AND)
+ {
+ result.or(getDISI(chain[index[0]], context));
+ ++index[0];
+ }
+ else if (logic == ANDNOT)
+ {
+ result.or(getDISI(chain[index[0]], context));
+ result.flip(0, reader.maxDoc()); // NOTE: may set bits for deleted docs.
+ ++index[0];
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Delegates to each filter in the chain.
+ /// </summary>
+ /// <param name="context"> AtomicReaderContext </param>
+ /// <param name="logic"> Logical operation </param>
+ /// <returns> DocIdSet </returns>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private org.apache.lucene.search.DocIdSet getDocIdSet(org.apache.lucene.index.AtomicReaderContext context, int logic, int[] index) throws java.io.IOException
+ private DocIdSet getDocIdSet(AtomicReaderContext context, int logic, int[] index)
+ {
+ FixedBitSet result = initialResult(context, logic, index);
+ for (; index[0] < chain.Length; index[0]++)
+ {
+ // we dont pass acceptDocs, we will filter at the end using an additional filter
+ doChain(result, logic, chain[index[0]].getDocIdSet(context, null));
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Delegates to each filter in the chain.
+ /// </summary>
+ /// <param name="context"> AtomicReaderContext </param>
+ /// <param name="logic"> Logical operation </param>
+ /// <returns> DocIdSet </returns>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private org.apache.lucene.search.DocIdSet getDocIdSet(org.apache.lucene.index.AtomicReaderContext context, int[] logic, int[] index) throws java.io.IOException
+ private DocIdSet getDocIdSet(AtomicReaderContext context, int[] logic, int[] index)
+ {
+ if (logic.Length != chain.Length)
+ {
+ throw new System.ArgumentException("Invalid number of elements in logic array");
+ }
+
+ FixedBitSet result = initialResult(context, logic[0], index);
+ for (; index[0] < chain.Length; index[0]++)
+ {
+ // we dont pass acceptDocs, we will filter at the end using an additional filter
+ doChain(result, logic[index[0]], chain[index[0]].getDocIdSet(context, null));
+ }
+ return result;
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("ChainedFilter: [");
+ foreach (Filter aChain in chain)
+ {
+ sb.Append(aChain);
+ sb.Append(' ');
+ }
+ sb.Append(']');
+ return sb.ToString();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private void doChain(org.apache.lucene.util.FixedBitSet result, int logic, org.apache.lucene.search.DocIdSet dis) throws java.io.IOException
+ private void doChain(FixedBitSet result, int logic, DocIdSet dis)
+ {
+ if (dis is FixedBitSet)
+ {
+ // optimized case for FixedBitSets
+ switch (logic)
+ {
+ case OR:
+ result.or((FixedBitSet) dis);
+ break;
+ case AND:
+ result.and((FixedBitSet) dis);
+ break;
+ case ANDNOT:
+ result.andNot((FixedBitSet) dis);
+ break;
+ case XOR:
+ result.xor((FixedBitSet) dis);
+ break;
+ default:
+ doChain(result, DEFAULT, dis);
+ break;
+ }
+ }
+ else
+ {
+ DocIdSetIterator disi;
+ if (dis == null)
+ {
+ disi = DocIdSetIterator.empty();
+ }
+ else
+ {
+ disi = dis.GetEnumerator();
+ if (disi == null)
+ {
+ disi = DocIdSetIterator.empty();
+ }
+ }
+
+ switch (logic)
+ {
+ case OR:
+ result.or(disi);
+ break;
+ case AND:
+ result.and(disi);
+ break;
+ case ANDNOT:
+ result.andNot(disi);
+ break;
+ case XOR:
+ result.xor(disi);
+ break;
+ default:
+ doChain(result, DEFAULT, dis);
+ break;
+ }
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/CommonTermsQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/CommonTermsQuery.cs b/src/Lucene.Net.Queries/CommonTermsQuery.cs
new file mode 100644
index 0000000..0d78a68
--- /dev/null
+++ b/src/Lucene.Net.Queries/CommonTermsQuery.cs
@@ -0,0 +1,526 @@
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Text;
+
+namespace org.apache.lucene.queries
+{
+
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using Fields = org.apache.lucene.index.Fields;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using Term = org.apache.lucene.index.Term;
+ using TermContext = org.apache.lucene.index.TermContext;
+ using Terms = org.apache.lucene.index.Terms;
+ using TermsEnum = org.apache.lucene.index.TermsEnum;
+ using BooleanClause = org.apache.lucene.search.BooleanClause;
+ using Occur = org.apache.lucene.search.BooleanClause.Occur;
+ using BooleanQuery = org.apache.lucene.search.BooleanQuery;
+ using Query = org.apache.lucene.search.Query;
+ using TermQuery = org.apache.lucene.search.TermQuery;
+ using Similarity = org.apache.lucene.search.similarities.Similarity;
+ using ToStringUtils = org.apache.lucene.util.ToStringUtils;
+
+
+ /// <summary>
+ /// A query that executes high-frequency terms in a optional sub-query to prevent
+ /// slow queries due to "common" terms like stopwords. This query
+ /// builds 2 queries off the <seealso cref="#add(Term) added"/> terms: low-frequency
+ /// terms are added to a required boolean clause and high-frequency terms are
+ /// added to an optional boolean clause. The optional clause is only executed if
+ /// the required "low-frequency" clause matches. Scores produced by this query
+ /// will be slightly different than plain <seealso cref="BooleanQuery"/> scorer mainly due to
+ /// differences in the <seealso cref="Similarity#coord(int,int) number of leaf queries"/>
+ /// in the required boolean clause. In most cases, high-frequency terms are
+ /// unlikely to significantly contribute to the document score unless at least
+ /// one of the low-frequency terms are matched. This query can improve
+ /// query execution times significantly if applicable.
+ /// <para>
+ /// <seealso cref="CommonTermsQuery"/> has several advantages over stopword filtering at
+ /// index or query time since a term can be "classified" based on the actual
+ /// document frequency in the index and can prevent slow queries even across
+ /// domains without specialized stopword files.
+ /// </para>
+ /// <para>
+ /// <b>Note:</b> if the query only contains high-frequency terms the query is
+ /// rewritten into a plain conjunction query ie. all high-frequency terms need to
+ /// match in order to match a document.
+ /// </para>
+ /// </summary>
+ public class CommonTermsQuery : Query
+ {
+ /*
+ * TODO maybe it would make sense to abstract this even further and allow to
+ * rewrite to dismax rather than boolean. Yet, this can already be subclassed
+ * to do so.
+ */
+ protected internal readonly IList<Term> terms = new List<Term>();
+ protected internal readonly bool disableCoord;
+ protected internal readonly float maxTermFrequency;
+ protected internal readonly BooleanClause.Occur lowFreqOccur;
+ protected internal readonly BooleanClause.Occur highFreqOccur;
+ protected internal float lowFreqBoost = 1.0f;
+ protected internal float highFreqBoost = 1.0f;
+ protected internal float lowFreqMinNrShouldMatch = 0;
+ protected internal float highFreqMinNrShouldMatch = 0;
+
+ /// <summary>
+ /// Creates a new <seealso cref="CommonTermsQuery"/>
+ /// </summary>
+ /// <param name="highFreqOccur">
+ /// <seealso cref="Occur"/> used for high frequency terms </param>
+ /// <param name="lowFreqOccur">
+ /// <seealso cref="Occur"/> used for low frequency terms </param>
+ /// <param name="maxTermFrequency">
+ /// a value in [0..1) (or absolute number >=1) representing the
+ /// maximum threshold of a terms document frequency to be considered a
+ /// low frequency term. </param>
+ /// <exception cref="IllegalArgumentException">
+ /// if <seealso cref="Occur#MUST_NOT"/> is pass as lowFreqOccur or
+ /// highFreqOccur </exception>
+ public CommonTermsQuery(BooleanClause.Occur highFreqOccur, BooleanClause.Occur lowFreqOccur, float maxTermFrequency) : this(highFreqOccur, lowFreqOccur, maxTermFrequency, false)
+ {
+ }
+
+ /// <summary>
+ /// Creates a new <seealso cref="CommonTermsQuery"/>
+ /// </summary>
+ /// <param name="highFreqOccur">
+ /// <seealso cref="Occur"/> used for high frequency terms </param>
+ /// <param name="lowFreqOccur">
+ /// <seealso cref="Occur"/> used for low frequency terms </param>
+ /// <param name="maxTermFrequency">
+ /// a value in [0..1) (or absolute number >=1) representing the
+ /// maximum threshold of a terms document frequency to be considered a
+ /// low frequency term. </param>
+ /// <param name="disableCoord">
+ /// disables <seealso cref="Similarity#coord(int,int)"/> in scoring for the low
+ /// / high frequency sub-queries </param>
+ /// <exception cref="IllegalArgumentException">
+ /// if <seealso cref="Occur#MUST_NOT"/> is pass as lowFreqOccur or
+ /// highFreqOccur </exception>
+ public CommonTermsQuery(BooleanClause.Occur highFreqOccur, BooleanClause.Occur lowFreqOccur, float maxTermFrequency, bool disableCoord)
+ {
+ if (highFreqOccur == BooleanClause.Occur.MUST_NOT)
+ {
+ throw new System.ArgumentException("highFreqOccur should be MUST or SHOULD but was MUST_NOT");
+ }
+ if (lowFreqOccur == BooleanClause.Occur.MUST_NOT)
+ {
+ throw new System.ArgumentException("lowFreqOccur should be MUST or SHOULD but was MUST_NOT");
+ }
+ this.disableCoord = disableCoord;
+ this.highFreqOccur = highFreqOccur;
+ this.lowFreqOccur = lowFreqOccur;
+ this.maxTermFrequency = maxTermFrequency;
+ }
+
+ /// <summary>
+ /// Adds a term to the <seealso cref="CommonTermsQuery"/>
+ /// </summary>
+ /// <param name="term">
+ /// the term to add </param>
+ public virtual void add(Term term)
+ {
+ if (term == null)
+ {
+ throw new System.ArgumentException("Term must not be null");
+ }
+ this.terms.Add(term);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.Query rewrite(org.apache.lucene.index.IndexReader reader) throws java.io.IOException
+ public override Query rewrite(IndexReader reader)
+ {
+ if (this.terms.Count == 0)
+ {
+ return new BooleanQuery();
+ }
+ else if (this.terms.Count == 1)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.Query tq = newTermQuery(this.terms.get(0), null);
+ Query tq = newTermQuery(this.terms[0], null);
+ tq.Boost = Boost;
+ return tq;
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final java.util.List<org.apache.lucene.index.AtomicReaderContext> leaves = reader.leaves();
+ IList<AtomicReaderContext> leaves = reader.leaves();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int maxDoc = reader.maxDoc();
+ int maxDoc = reader.maxDoc();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.TermContext[] contextArray = new org.apache.lucene.index.TermContext[terms.size()];
+ TermContext[] contextArray = new TermContext[terms.Count];
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.Term[] queryTerms = this.terms.toArray(new org.apache.lucene.index.Term[0]);
+ Term[] queryTerms = this.terms.ToArray();
+ collectTermContext(reader, leaves, contextArray, queryTerms);
+ return buildQuery(maxDoc, contextArray, queryTerms);
+ }
+
+ protected internal virtual int calcLowFreqMinimumNumberShouldMatch(int numOptional)
+ {
+ return minNrShouldMatch(lowFreqMinNrShouldMatch, numOptional);
+ }
+
+ protected internal virtual int calcHighFreqMinimumNumberShouldMatch(int numOptional)
+ {
+ return minNrShouldMatch(highFreqMinNrShouldMatch, numOptional);
+ }
+
+ private int minNrShouldMatch(float minNrShouldMatch, int numOptional)
+ {
+ if (minNrShouldMatch >= 1.0f || minNrShouldMatch == 0.0f)
+ {
+ return (int) minNrShouldMatch;
+ }
+ return Math.Round(minNrShouldMatch * numOptional);
+ }
+
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: protected org.apache.lucene.search.Query buildQuery(final int maxDoc, final org.apache.lucene.index.TermContext[] contextArray, final org.apache.lucene.index.Term[] queryTerms)
+ protected internal virtual Query buildQuery(int maxDoc, TermContext[] contextArray, Term[] queryTerms)
+ {
+ BooleanQuery lowFreq = new BooleanQuery(disableCoord);
+ BooleanQuery highFreq = new BooleanQuery(disableCoord);
+ highFreq.Boost = highFreqBoost;
+ lowFreq.Boost = lowFreqBoost;
+ BooleanQuery query = new BooleanQuery(true);
+ for (int i = 0; i < queryTerms.Length; i++)
+ {
+ TermContext termContext = contextArray[i];
+ if (termContext == null)
+ {
+ lowFreq.add(newTermQuery(queryTerms[i], null), lowFreqOccur);
+ }
+ else
+ {
+ if ((maxTermFrequency >= 1f && termContext.docFreq() > maxTermFrequency) || (termContext.docFreq() > (int) Math.Ceiling(maxTermFrequency * (float) maxDoc)))
+ {
+ highFreq.add(newTermQuery(queryTerms[i], termContext), highFreqOccur);
+ }
+ else
+ {
+ lowFreq.add(newTermQuery(queryTerms[i], termContext), lowFreqOccur);
+ }
+ }
+
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int numLowFreqClauses = lowFreq.clauses().size();
+ int numLowFreqClauses = lowFreq.clauses().size();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int numHighFreqClauses = highFreq.clauses().size();
+ int numHighFreqClauses = highFreq.clauses().size();
+ if (lowFreqOccur == BooleanClause.Occur.SHOULD && numLowFreqClauses > 0)
+ {
+ int minMustMatch = calcLowFreqMinimumNumberShouldMatch(numLowFreqClauses);
+ lowFreq.MinimumNumberShouldMatch = minMustMatch;
+ }
+ if (highFreqOccur == BooleanClause.Occur.SHOULD && numHighFreqClauses > 0)
+ {
+ int minMustMatch = calcHighFreqMinimumNumberShouldMatch(numHighFreqClauses);
+ highFreq.MinimumNumberShouldMatch = minMustMatch;
+ }
+ if (lowFreq.clauses().Empty)
+ {
+ /*
+ * if lowFreq is empty we rewrite the high freq terms in a conjunction to
+ * prevent slow queries.
+ */
+ if (highFreq.MinimumNumberShouldMatch == 0 && highFreqOccur != BooleanClause.Occur.MUST)
+ {
+ foreach (BooleanClause booleanClause in highFreq)
+ {
+ booleanClause.Occur = BooleanClause.Occur.MUST;
+ }
+ }
+ highFreq.Boost = Boost;
+ return highFreq;
+ }
+ else if (highFreq.clauses().Empty)
+ {
+ // only do low freq terms - we don't have high freq terms
+ lowFreq.Boost = Boost;
+ return lowFreq;
+ }
+ else
+ {
+ query.add(highFreq, BooleanClause.Occur.SHOULD);
+ query.add(lowFreq, BooleanClause.Occur.MUST);
+ query.Boost = Boost;
+ return query;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public void collectTermContext(org.apache.lucene.index.IndexReader reader, java.util.List<org.apache.lucene.index.AtomicReaderContext> leaves, org.apache.lucene.index.TermContext[] contextArray, org.apache.lucene.index.Term[] queryTerms) throws java.io.IOException
+ public virtual void collectTermContext(IndexReader reader, IList<AtomicReaderContext> leaves, TermContext[] contextArray, Term[] queryTerms)
+ {
+ TermsEnum termsEnum = null;
+ foreach (AtomicReaderContext context in leaves)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.Fields fields = context.reader().fields();
+ Fields fields = context.reader().fields();
+ if (fields == null)
+ {
+ // reader has no fields
+ continue;
+ }
+ for (int i = 0; i < queryTerms.Length; i++)
+ {
+ Term term = queryTerms[i];
+ TermContext termContext = contextArray[i];
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.Terms terms = fields.terms(term.field());
+ Terms terms = fields.terms(term.field());
+ if (terms == null)
+ {
+ // field does not exist
+ continue;
+ }
+ termsEnum = terms.iterator(termsEnum);
+ Debug.Assert(termsEnum != null);
+
+ if (termsEnum == TermsEnum.EMPTY)
+ {
+ continue;
+ }
+ if (termsEnum.seekExact(term.bytes()))
+ {
+ if (termContext == null)
+ {
+ contextArray[i] = new TermContext(reader.Context, termsEnum.termState(), context.ord, termsEnum.docFreq(), termsEnum.totalTermFreq());
+ }
+ else
+ {
+ termContext.register(termsEnum.termState(), context.ord, termsEnum.docFreq(), termsEnum.totalTermFreq());
+ }
+
+ }
+
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns true iff <seealso cref="Similarity#coord(int,int)"/> is disabled in scoring
+ /// for the high and low frequency query instance. The top level query will
+ /// always disable coords.
+ /// </summary>
+ public virtual bool CoordDisabled
+ {
+ get
+ {
+ return disableCoord;
+ }
+ }
+
+ /// <summary>
+ /// Specifies a minimum number of the low frequent optional BooleanClauses which must be
+ /// satisfied in order to produce a match on the low frequency terms query
+ /// part. This method accepts a float value in the range [0..1) as a fraction
+ /// of the actual query terms in the low frequent clause or a number
+ /// <tt>>=1</tt> as an absolut number of clauses that need to match.
+ ///
+ /// <para>
+ /// By default no optional clauses are necessary for a match (unless there are
+ /// no required clauses). If this method is used, then the specified number of
+ /// clauses is required.
+ /// </para>
+ /// </summary>
+ /// <param name="min">
+ /// the number of optional clauses that must match </param>
+ public virtual float LowFreqMinimumNumberShouldMatch
+ {
+ set
+ {
+ this.lowFreqMinNrShouldMatch = value;
+ }
+ get
+ {
+ return lowFreqMinNrShouldMatch;
+ }
+ }
+
+
+ /// <summary>
+ /// Specifies a minimum number of the high frequent optional BooleanClauses which must be
+ /// satisfied in order to produce a match on the low frequency terms query
+ /// part. This method accepts a float value in the range [0..1) as a fraction
+ /// of the actual query terms in the low frequent clause or a number
+ /// <tt>>=1</tt> as an absolut number of clauses that need to match.
+ ///
+ /// <para>
+ /// By default no optional clauses are necessary for a match (unless there are
+ /// no required clauses). If this method is used, then the specified number of
+ /// clauses is required.
+ /// </para>
+ /// </summary>
+ /// <param name="min">
+ /// the number of optional clauses that must match </param>
+ public virtual float HighFreqMinimumNumberShouldMatch
+ {
+ set
+ {
+ this.highFreqMinNrShouldMatch = value;
+ }
+ get
+ {
+ return highFreqMinNrShouldMatch;
+ }
+ }
+
+
+ public override void extractTerms(HashSet<Term> terms)
+ {
+ terms.addAll(this.terms);
+ }
+
+ public override string ToString(string field)
+ {
+ StringBuilder buffer = new StringBuilder();
+ bool needParens = (Boost != 1.0) || (LowFreqMinimumNumberShouldMatch > 0);
+ if (needParens)
+ {
+ buffer.Append("(");
+ }
+ for (int i = 0; i < terms.Count; i++)
+ {
+ Term t = terms[i];
+ buffer.Append(newTermQuery(t, null).ToString());
+
+ if (i != terms.Count - 1)
+ {
+ buffer.Append(", ");
+ }
+ }
+ if (needParens)
+ {
+ buffer.Append(")");
+ }
+ if (LowFreqMinimumNumberShouldMatch > 0 || HighFreqMinimumNumberShouldMatch > 0)
+ {
+ buffer.Append('~');
+ buffer.Append("(");
+ buffer.Append(LowFreqMinimumNumberShouldMatch);
+ buffer.Append(HighFreqMinimumNumberShouldMatch);
+ buffer.Append(")");
+ }
+ if (Boost != 1.0f)
+ {
+ buffer.Append(ToStringUtils.boost(Boost));
+ }
+ return buffer.ToString();
+ }
+
+ public override int GetHashCode()
+ {
+ const int prime = 31;
+ int result = base.GetHashCode();
+ result = prime * result + (disableCoord ? 1231 : 1237);
+ result = prime * result + float.floatToIntBits(highFreqBoost);
+ result = prime * result + ((highFreqOccur == null) ? 0 : highFreqOccur.GetHashCode());
+ result = prime * result + float.floatToIntBits(lowFreqBoost);
+ result = prime * result + ((lowFreqOccur == null) ? 0 : lowFreqOccur.GetHashCode());
+ result = prime * result + float.floatToIntBits(maxTermFrequency);
+ result = prime * result + float.floatToIntBits(lowFreqMinNrShouldMatch);
+ result = prime * result + float.floatToIntBits(highFreqMinNrShouldMatch);
+ result = prime * result + ((terms == null) ? 0 : terms.GetHashCode());
+ return result;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!base.Equals(obj))
+ {
+ return false;
+ }
+ if (this.GetType() != obj.GetType())
+ {
+ return false;
+ }
+ CommonTermsQuery other = (CommonTermsQuery) obj;
+ if (disableCoord != other.disableCoord)
+ {
+ return false;
+ }
+ if (float.floatToIntBits(highFreqBoost) != float.floatToIntBits(other.highFreqBoost))
+ {
+ return false;
+ }
+ if (highFreqOccur != other.highFreqOccur)
+ {
+ return false;
+ }
+ if (float.floatToIntBits(lowFreqBoost) != float.floatToIntBits(other.lowFreqBoost))
+ {
+ return false;
+ }
+ if (lowFreqOccur != other.lowFreqOccur)
+ {
+ return false;
+ }
+ if (float.floatToIntBits(maxTermFrequency) != float.floatToIntBits(other.maxTermFrequency))
+ {
+ return false;
+ }
+ if (lowFreqMinNrShouldMatch != other.lowFreqMinNrShouldMatch)
+ {
+ return false;
+ }
+ if (highFreqMinNrShouldMatch != other.highFreqMinNrShouldMatch)
+ {
+ return false;
+ }
+ if (terms == null)
+ {
+ if (other.terms != null)
+ {
+ return false;
+ }
+ }
+ else if (!terms.Equals(other.terms))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Builds a new TermQuery instance.
+ /// <para>This is intended for subclasses that wish to customize the generated queries.</para> </summary>
+ /// <param name="term"> term </param>
+ /// <param name="context"> the TermContext to be used to create the low level term query. Can be <code>null</code>. </param>
+ /// <returns> new TermQuery instance </returns>
+ protected internal virtual Query newTermQuery(Term term, TermContext context)
+ {
+ return context == null ? new TermQuery(term) : new TermQuery(term, context);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/CustomScoreProvider.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/CustomScoreProvider.cs b/src/Lucene.Net.Queries/CustomScoreProvider.cs
new file mode 100644
index 0000000..5491c86
--- /dev/null
+++ b/src/Lucene.Net.Queries/CustomScoreProvider.cs
@@ -0,0 +1,192 @@
+namespace org.apache.lucene.queries
+{
+
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader; // for javadocs
+ using FunctionQuery = org.apache.lucene.queries.function.FunctionQuery;
+ using Explanation = org.apache.lucene.search.Explanation;
+ using FieldCache = org.apache.lucene.search.FieldCache; // for javadocs
+
+ /// <summary>
+ /// An instance of this subclass should be returned by
+ /// <seealso cref="CustomScoreQuery#getCustomScoreProvider"/>, if you want
+ /// to modify the custom score calculation of a <seealso cref="CustomScoreQuery"/>.
+ /// <para>Since Lucene 2.9, queries operate on each segment of an index separately,
+ /// so the protected <seealso cref="#context"/> field can be used to resolve doc IDs,
+ /// as the supplied <code>doc</code> ID is per-segment and without knowledge
+ /// of the IndexReader you cannot access the document or <seealso cref="FieldCache"/>.
+ ///
+ /// @lucene.experimental
+ /// @since 2.9.2
+ /// </para>
+ /// </summary>
+ public class CustomScoreProvider
+ {
+
+ protected internal readonly AtomicReaderContext context;
+
+ /// <summary>
+ /// Creates a new instance of the provider class for the given <seealso cref="IndexReader"/>.
+ /// </summary>
+ public CustomScoreProvider(AtomicReaderContext context)
+ {
+ this.context = context;
+ }
+
+ /// <summary>
+ /// Compute a custom score by the subQuery score and a number of
+ /// <seealso cref="org.apache.lucene.queries.function.FunctionQuery"/> scores.
+ /// <para>
+ /// Subclasses can override this method to modify the custom score.
+ /// </para>
+ /// <para>
+ /// If your custom scoring is different than the default herein you
+ /// should override at least one of the two customScore() methods.
+ /// If the number of <seealso cref="FunctionQuery function queries"/> is always < 2 it is
+ /// sufficient to override the other
+ /// <seealso cref="#customScore(int, float, float) customScore()"/>
+ /// method, which is simpler.
+ /// </para>
+ /// <para>
+ /// The default computation herein is a multiplication of given scores:
+ /// <pre>
+ /// ModifiedScore = valSrcScore * valSrcScores[0] * valSrcScores[1] * ...
+ /// </pre>
+ ///
+ /// </para>
+ /// </summary>
+ /// <param name="doc"> id of scored doc. </param>
+ /// <param name="subQueryScore"> score of that doc by the subQuery. </param>
+ /// <param name="valSrcScores"> scores of that doc by the <seealso cref="FunctionQuery"/>. </param>
+ /// <returns> custom score. </returns>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public float customScore(int doc, float subQueryScore, float valSrcScores[]) throws java.io.IOException
+ public virtual float customScore(int doc, float subQueryScore, float[] valSrcScores)
+ {
+ if (valSrcScores.Length == 1)
+ {
+ return customScore(doc, subQueryScore, valSrcScores[0]);
+ }
+ if (valSrcScores.Length == 0)
+ {
+ return customScore(doc, subQueryScore, 1);
+ }
+ float score = subQueryScore;
+ foreach (float valSrcScore in valSrcScores)
+ {
+ score *= valSrcScore;
+ }
+ return score;
+ }
+
+ /// <summary>
+ /// Compute a custom score by the subQuery score and the <seealso cref="FunctionQuery"/> score.
+ /// <para>
+ /// Subclasses can override this method to modify the custom score.
+ /// </para>
+ /// <para>
+ /// If your custom scoring is different than the default herein you
+ /// should override at least one of the two customScore() methods.
+ /// If the number of <seealso cref="FunctionQuery function queries"/> is always < 2 it is
+ /// sufficient to override this customScore() method, which is simpler.
+ /// </para>
+ /// <para>
+ /// The default computation herein is a multiplication of the two scores:
+ /// <pre>
+ /// ModifiedScore = subQueryScore * valSrcScore
+ /// </pre>
+ ///
+ /// </para>
+ /// </summary>
+ /// <param name="doc"> id of scored doc. </param>
+ /// <param name="subQueryScore"> score of that doc by the subQuery. </param>
+ /// <param name="valSrcScore"> score of that doc by the <seealso cref="FunctionQuery"/>. </param>
+ /// <returns> custom score. </returns>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public float customScore(int doc, float subQueryScore, float valSrcScore) throws java.io.IOException
+ public virtual float customScore(int doc, float subQueryScore, float valSrcScore)
+ {
+ return subQueryScore * valSrcScore;
+ }
+
+ /// <summary>
+ /// Explain the custom score.
+ /// Whenever overriding <seealso cref="#customScore(int, float, float[])"/>,
+ /// this method should also be overridden to provide the correct explanation
+ /// for the part of the custom scoring.
+ /// </summary>
+ /// <param name="doc"> doc being explained. </param>
+ /// <param name="subQueryExpl"> explanation for the sub-query part. </param>
+ /// <param name="valSrcExpls"> explanation for the value source part. </param>
+ /// <returns> an explanation for the custom score </returns>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public org.apache.lucene.search.Explanation customExplain(int doc, org.apache.lucene.search.Explanation subQueryExpl, org.apache.lucene.search.Explanation valSrcExpls[]) throws java.io.IOException
+ public virtual Explanation customExplain(int doc, Explanation subQueryExpl, Explanation[] valSrcExpls)
+ {
+ if (valSrcExpls.Length == 1)
+ {
+ return customExplain(doc, subQueryExpl, valSrcExpls[0]);
+ }
+ if (valSrcExpls.Length == 0)
+ {
+ return subQueryExpl;
+ }
+ float valSrcScore = 1;
+ foreach (Explanation valSrcExpl in valSrcExpls)
+ {
+ valSrcScore *= valSrcExpl.Value;
+ }
+ Explanation exp = new Explanation(valSrcScore * subQueryExpl.Value, "custom score: product of:");
+ exp.addDetail(subQueryExpl);
+ foreach (Explanation valSrcExpl in valSrcExpls)
+ {
+ exp.addDetail(valSrcExpl);
+ }
+ return exp;
+ }
+
+ /// <summary>
+ /// Explain the custom score.
+ /// Whenever overriding <seealso cref="#customScore(int, float, float)"/>,
+ /// this method should also be overridden to provide the correct explanation
+ /// for the part of the custom scoring.
+ /// </summary>
+ /// <param name="doc"> doc being explained. </param>
+ /// <param name="subQueryExpl"> explanation for the sub-query part. </param>
+ /// <param name="valSrcExpl"> explanation for the value source part. </param>
+ /// <returns> an explanation for the custom score </returns>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public org.apache.lucene.search.Explanation customExplain(int doc, org.apache.lucene.search.Explanation subQueryExpl, org.apache.lucene.search.Explanation valSrcExpl) throws java.io.IOException
+ public virtual Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl)
+ {
+ float valSrcScore = 1;
+ if (valSrcExpl != null)
+ {
+ valSrcScore *= valSrcExpl.Value;
+ }
+ Explanation exp = new Explanation(valSrcScore * subQueryExpl.Value, "custom score: product of:");
+ exp.addDetail(subQueryExpl);
+ exp.addDetail(valSrcExpl);
+ return exp;
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/CustomScoreQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/CustomScoreQuery.cs b/src/Lucene.Net.Queries/CustomScoreQuery.cs
new file mode 100644
index 0000000..91c2597
--- /dev/null
+++ b/src/Lucene.Net.Queries/CustomScoreQuery.cs
@@ -0,0 +1,490 @@
+using System.Collections.Generic;
+using System.Text;
+
+namespace org.apache.lucene.queries
+{
+
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using Term = org.apache.lucene.index.Term;
+ using FunctionQuery = org.apache.lucene.queries.function.FunctionQuery;
+ using ValueSource = org.apache.lucene.queries.function.ValueSource;
+ using ComplexExplanation = org.apache.lucene.search.ComplexExplanation;
+ using Explanation = org.apache.lucene.search.Explanation;
+ using Query = org.apache.lucene.search.Query;
+ using Weight = org.apache.lucene.search.Weight;
+ using Scorer = org.apache.lucene.search.Scorer;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using Bits = org.apache.lucene.util.Bits;
+ using ToStringUtils = org.apache.lucene.util.ToStringUtils;
+
+ /// <summary>
+ /// Query that sets document score as a programmatic function of several (sub) scores:
+ /// <ol>
+ /// <li>the score of its subQuery (any query)</li>
+ /// <li>(optional) the score of its <seealso cref="FunctionQuery"/> (or queries).</li>
+ /// </ol>
+ /// Subclasses can modify the computation by overriding <seealso cref="#getCustomScoreProvider"/>.
+ ///
+ /// @lucene.experimental
+ /// </summary>
+ public class CustomScoreQuery : Query
+ {
+
+ private Query subQuery;
+ private Query[] scoringQueries; // never null (empty array if there are no valSrcQueries).
+ private bool strict = false; // if true, valueSource part of query does not take part in weights normalization.
+
+ /// <summary>
+ /// Create a CustomScoreQuery over input subQuery. </summary>
+ /// <param name="subQuery"> the sub query whose scored is being customized. Must not be null. </param>
+ public CustomScoreQuery(Query subQuery) : this(subQuery, new FunctionQuery[0])
+ {
+ }
+
+ /// <summary>
+ /// Create a CustomScoreQuery over input subQuery and a <seealso cref="org.apache.lucene.queries.function.FunctionQuery"/>. </summary>
+ /// <param name="subQuery"> the sub query whose score is being customized. Must not be null. </param>
+ /// <param name="scoringQuery"> a value source query whose scores are used in the custom score
+ /// computation. This parameter is optional - it can be null. </param>
+ public CustomScoreQuery(Query subQuery, FunctionQuery scoringQuery) : this(subQuery, scoringQuery != null ? new FunctionQuery[] {scoringQuery} : new FunctionQuery[0]); / / don't want an array that contains a single null..
+ {
+ }
+
+ /// <summary>
+ /// Create a CustomScoreQuery over input subQuery and a <seealso cref="org.apache.lucene.queries.function.FunctionQuery"/>. </summary>
+ /// <param name="subQuery"> the sub query whose score is being customized. Must not be null. </param>
+ /// <param name="scoringQueries"> value source queries whose scores are used in the custom score
+ /// computation. This parameter is optional - it can be null or even an empty array. </param>
+ public CustomScoreQuery(Query subQuery, params FunctionQuery[] scoringQueries)
+ {
+ this.subQuery = subQuery;
+ this.scoringQueries = scoringQueries != null? scoringQueries : new Query[0];
+ if (subQuery == null)
+ {
+ throw new System.ArgumentException("<subquery> must not be null!");
+ }
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.Query rewrite(org.apache.lucene.index.IndexReader reader) throws java.io.IOException
+ public override Query rewrite(IndexReader reader)
+ {
+ CustomScoreQuery clone = null;
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.Query sq = subQuery.rewrite(reader);
+ Query sq = subQuery.rewrite(reader);
+ if (sq != subQuery)
+ {
+ clone = clone();
+ clone.subQuery = sq;
+ }
+
+ for (int i = 0; i < scoringQueries.Length; i++)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.Query v = scoringQueries[i].rewrite(reader);
+ Query v = scoringQueries[i].rewrite(reader);
+ if (v != scoringQueries[i])
+ {
+ if (clone == null)
+ {
+ clone = clone();
+ }
+ clone.scoringQueries[i] = v;
+ }
+ }
+
+ return (clone == null) ? this : clone;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#extractTerms(java.util.Set) */
+ public override void extractTerms(HashSet<Term> terms)
+ {
+ subQuery.extractTerms(terms);
+ foreach (Query scoringQuery in scoringQueries)
+ {
+ scoringQuery.extractTerms(terms);
+ }
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#clone() */
+ public override CustomScoreQuery clone()
+ {
+ CustomScoreQuery clone = (CustomScoreQuery)base.clone();
+ clone.subQuery = subQuery.clone();
+ clone.scoringQueries = new Query[scoringQueries.Length];
+ for (int i = 0; i < scoringQueries.Length; i++)
+ {
+ clone.scoringQueries[i] = scoringQueries[i].clone();
+ }
+ return clone;
+ }
+
+ /* (non-Javadoc) @see org.apache.lucene.search.Query#toString(java.lang.String) */
+ public override string ToString(string field)
+ {
+ StringBuilder sb = (new StringBuilder(name())).Append("(");
+ sb.Append(subQuery.ToString(field));
+ foreach (Query scoringQuery in scoringQueries)
+ {
+ sb.Append(", ").Append(scoringQuery.ToString(field));
+ }
+ sb.Append(")");
+ sb.Append(strict?" STRICT" : "");
+ return sb.ToString() + ToStringUtils.boost(Boost);
+ }
+
+ /// <summary>
+ /// Returns true if <code>o</code> is equal to this. </summary>
+ public override bool Equals(object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (!base.Equals(o))
+ {
+ return false;
+ }
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ CustomScoreQuery other = (CustomScoreQuery)o;
+ if (this.Boost != other.Boost || !this.subQuery.Equals(other.subQuery) || this.strict != other.strict || this.scoringQueries.Length != other.scoringQueries.Length)
+ {
+ return false;
+ }
+ return Arrays.Equals(scoringQueries, other.scoringQueries);
+ }
+
+ /// <summary>
+ /// Returns a hash code value for this object. </summary>
+ public override int GetHashCode()
+ {
+ return (this.GetType().GetHashCode() + subQuery.GetHashCode() + Arrays.GetHashCode(scoringQueries)) ^ float.floatToIntBits(Boost) ^ (strict ? 1234 : 4321);
+ }
+
+ /// <summary>
+ /// Returns a <seealso cref="CustomScoreProvider"/> that calculates the custom scores
+ /// for the given <seealso cref="IndexReader"/>. The default implementation returns a default
+ /// implementation as specified in the docs of <seealso cref="CustomScoreProvider"/>.
+ /// @since 2.9.2
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: protected CustomScoreProvider getCustomScoreProvider(org.apache.lucene.index.AtomicReaderContext context) throws java.io.IOException
+ protected internal virtual CustomScoreProvider getCustomScoreProvider(AtomicReaderContext context)
+ {
+ return new CustomScoreProvider(context);
+ }
+
+ //=========================== W E I G H T ============================
+
+ private class CustomWeight : Weight
+ {
+ private readonly CustomScoreQuery outerInstance;
+
+ internal Weight subQueryWeight;
+ internal Weight[] valSrcWeights;
+ internal bool qStrict;
+ internal float queryWeight;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public CustomWeight(org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public CustomWeight(CustomScoreQuery outerInstance, IndexSearcher searcher)
+ {
+ this.outerInstance = outerInstance;
+ this.subQueryWeight = outerInstance.subQuery.createWeight(searcher);
+ this.valSrcWeights = new Weight[outerInstance.scoringQueries.Length];
+ for (int i = 0; i < outerInstance.scoringQueries.Length; i++)
+ {
+ this.valSrcWeights[i] = outerInstance.scoringQueries[i].createWeight(searcher);
+ }
+ this.qStrict = outerInstance.strict;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#getQuery() */
+ public override Query Query
+ {
+ get
+ {
+ return outerInstance;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public float getValueForNormalization() throws java.io.IOException
+ public override float ValueForNormalization
+ {
+ get
+ {
+ float sum = subQueryWeight.ValueForNormalization;
+ foreach (Weight valSrcWeight in valSrcWeights)
+ {
+ if (qStrict)
+ {
+ valSrcWeight.ValueForNormalization; // do not include ValueSource part in the query normalization
+ }
+ else
+ {
+ sum += valSrcWeight.ValueForNormalization;
+ }
+ }
+ return sum;
+ }
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#normalize(float) */
+ public override void normalize(float norm, float topLevelBoost)
+ {
+ // note we DONT incorporate our boost, nor pass down any topLevelBoost
+ // (e.g. from outer BQ), as there is no guarantee that the CustomScoreProvider's
+ // function obeys the distributive law... it might call sqrt() on the subQuery score
+ // or some other arbitrary function other than multiplication.
+ // so, instead boosts are applied directly in score()
+ subQueryWeight.normalize(norm, 1f);
+ foreach (Weight valSrcWeight in valSrcWeights)
+ {
+ if (qStrict)
+ {
+ valSrcWeight.normalize(1, 1); // do not normalize the ValueSource part
+ }
+ else
+ {
+ valSrcWeight.normalize(norm, 1f);
+ }
+ }
+ queryWeight = topLevelBoost * Boost;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.Scorer scorer(org.apache.lucene.index.AtomicReaderContext context, org.apache.lucene.util.Bits acceptDocs) throws java.io.IOException
+ public override Scorer scorer(AtomicReaderContext context, Bits acceptDocs)
+ {
+ Scorer subQueryScorer = subQueryWeight.scorer(context, acceptDocs);
+ if (subQueryScorer == null)
+ {
+ return null;
+ }
+ Scorer[] valSrcScorers = new Scorer[valSrcWeights.Length];
+ for (int i = 0; i < valSrcScorers.Length; i++)
+ {
+ valSrcScorers[i] = valSrcWeights[i].scorer(context, acceptDocs);
+ }
+ return new CustomScorer(outerInstance, outerInstance.getCustomScoreProvider(context), this, queryWeight, subQueryScorer, valSrcScorers);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.Explanation explain(org.apache.lucene.index.AtomicReaderContext context, int doc) throws java.io.IOException
+ public override Explanation explain(AtomicReaderContext context, int doc)
+ {
+ Explanation explain = doExplain(context, doc);
+ return explain == null ? new Explanation(0.0f, "no matching docs") : explain;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private org.apache.lucene.search.Explanation doExplain(org.apache.lucene.index.AtomicReaderContext info, int doc) throws java.io.IOException
+ internal virtual Explanation doExplain(AtomicReaderContext info, int doc)
+ {
+ Explanation subQueryExpl = subQueryWeight.explain(info, doc);
+ if (!subQueryExpl.Match)
+ {
+ return subQueryExpl;
+ }
+ // match
+ Explanation[] valSrcExpls = new Explanation[valSrcWeights.Length];
+ for (int i = 0; i < valSrcWeights.Length; i++)
+ {
+ valSrcExpls[i] = valSrcWeights[i].explain(info, doc);
+ }
+ Explanation customExp = outerInstance.getCustomScoreProvider(info).customExplain(doc,subQueryExpl,valSrcExpls);
+ float sc = Boost * customExp.Value;
+ Explanation res = new ComplexExplanation(true, sc, outerInstance.ToString() + ", product of:");
+ res.addDetail(customExp);
+ res.addDetail(new Explanation(Boost, "queryBoost")); // actually using the q boost as q weight (== weight value)
+ return res;
+ }
+
+ public override bool scoresDocsOutOfOrder()
+ {
+ return false;
+ }
+
+ }
+
+
+ //=========================== S C O R E R ============================
+
+ /// <summary>
+ /// A scorer that applies a (callback) function on scores of the subQuery.
+ /// </summary>
+ private class CustomScorer : Scorer
+ {
+ private readonly CustomScoreQuery outerInstance;
+
+ internal readonly float qWeight;
+ internal readonly Scorer subQueryScorer;
+ internal readonly Scorer[] valSrcScorers;
+ internal readonly CustomScoreProvider provider;
+ internal readonly float[] vScores; // reused in score() to avoid allocating this array for each doc
+
+ // constructor
+ internal CustomScorer(CustomScoreQuery outerInstance, CustomScoreProvider provider, CustomWeight w, float qWeight, Scorer subQueryScorer, Scorer[] valSrcScorers) : base(w)
+ {
+ this.outerInstance = outerInstance;
+ this.qWeight = qWeight;
+ this.subQueryScorer = subQueryScorer;
+ this.valSrcScorers = valSrcScorers;
+ this.vScores = new float[valSrcScorers.Length];
+ this.provider = provider;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int nextDoc() throws java.io.IOException
+ public override int nextDoc()
+ {
+ int doc = subQueryScorer.nextDoc();
+ if (doc != NO_MORE_DOCS)
+ {
+ foreach (Scorer valSrcScorer in valSrcScorers)
+ {
+ valSrcScorer.advance(doc);
+ }
+ }
+ return doc;
+ }
+
+ public override int docID()
+ {
+ return subQueryScorer.docID();
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public float score() throws java.io.IOException
+ public override float score()
+ {
+ for (int i = 0; i < valSrcScorers.Length; i++)
+ {
+ vScores[i] = valSrcScorers[i].score();
+ }
+ return qWeight * provider.customScore(subQueryScorer.docID(), subQueryScorer.score(), vScores);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int freq() throws java.io.IOException
+ public override int freq()
+ {
+ return subQueryScorer.freq();
+ }
+
+ public override ICollection<ChildScorer> Children
+ {
+ get
+ {
+ return Collections.singleton(new ChildScorer(subQueryScorer, "CUSTOM"));
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int advance(int target) throws java.io.IOException
+ public override int advance(int target)
+ {
+ int doc = subQueryScorer.advance(target);
+ if (doc != NO_MORE_DOCS)
+ {
+ foreach (Scorer valSrcScorer in valSrcScorers)
+ {
+ valSrcScorer.advance(doc);
+ }
+ }
+ return doc;
+ }
+
+ public override long cost()
+ {
+ return subQueryScorer.cost();
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.Weight createWeight(org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override Weight createWeight(IndexSearcher searcher)
+ {
+ return new CustomWeight(this, searcher);
+ }
+
+ /// <summary>
+ /// Checks if this is strict custom scoring.
+ /// In strict custom scoring, the <seealso cref="ValueSource"/> part does not participate in weight normalization.
+ /// This may be useful when one wants full control over how scores are modified, and does
+ /// not care about normalizing by the <seealso cref="ValueSource"/> part.
+ /// One particular case where this is useful if for testing this query.
+ /// <P>
+ /// Note: only has effect when the <seealso cref="ValueSource"/> part is not null.
+ /// </summary>
+ public virtual bool Strict
+ {
+ get
+ {
+ return strict;
+ }
+ set
+ {
+ this.strict = value;
+ }
+ }
+
+
+ /// <summary>
+ /// The sub-query that CustomScoreQuery wraps, affecting both the score and which documents match. </summary>
+ public virtual Query SubQuery
+ {
+ get
+ {
+ return subQuery;
+ }
+ }
+
+ /// <summary>
+ /// The scoring queries that only affect the score of CustomScoreQuery. </summary>
+ public virtual Query[] ScoringQueries
+ {
+ get
+ {
+ return scoringQueries;
+ }
+ }
+
+ /// <summary>
+ /// A short name of this query, used in <seealso cref="#toString(String)"/>.
+ /// </summary>
+ public virtual string name()
+ {
+ return "custom";
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/FilterClause.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/FilterClause.cs b/src/Lucene.Net.Queries/FilterClause.cs
new file mode 100644
index 0000000..cbfe284
--- /dev/null
+++ b/src/Lucene.Net.Queries/FilterClause.cs
@@ -0,0 +1,97 @@
+namespace org.apache.lucene.queries
+{
+
+ /*
+ * 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 Occur = org.apache.lucene.search.BooleanClause.Occur;
+ using Filter = org.apache.lucene.search.Filter;
+
+ /// <summary>
+ /// A Filter that wrapped with an indication of how that filter
+ /// is used when composed with another filter.
+ /// (Follows the boolean logic in BooleanClause for composition
+ /// of queries.)
+ /// </summary>
+ public sealed class FilterClause
+ {
+
+ private readonly Occur occur;
+ private readonly Filter filter;
+
+ /// <summary>
+ /// Create a new FilterClause </summary>
+ /// <param name="filter"> A Filter object containing a BitSet </param>
+ /// <param name="occur"> A parameter implementation indicating SHOULD, MUST or MUST NOT </param>
+
+ public FilterClause(Filter filter, Occur occur)
+ {
+ this.occur = occur;
+ this.filter = filter;
+ }
+
+ /// <summary>
+ /// Returns this FilterClause's filter </summary>
+ /// <returns> A Filter object </returns>
+ public Filter Filter
+ {
+ get
+ {
+ return filter;
+ }
+ }
+
+ /// <summary>
+ /// Returns this FilterClause's occur parameter </summary>
+ /// <returns> An Occur object </returns>
+ public Occur Occur
+ {
+ get
+ {
+ return occur;
+ }
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+ if (o == null || !(o is FilterClause))
+ {
+ return false;
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final FilterClause other = (FilterClause)o;
+ FilterClause other = (FilterClause)o;
+ return this.filter.Equals(other.filter) && this.occur == other.occur;
+ }
+
+ public override int GetHashCode()
+ {
+ return filter.GetHashCode() ^ occur.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return occur.ToString() + filter.ToString();
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/BoostedQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/BoostedQuery.cs b/src/Lucene.Net.Queries/Function/BoostedQuery.cs
new file mode 100644
index 0000000..928db91
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/BoostedQuery.cs
@@ -0,0 +1,287 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+namespace org.apache.lucene.queries.function
+{
+
+ /*
+ * 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 org.apache.lucene.search;
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using Term = org.apache.lucene.index.Term;
+ using Bits = org.apache.lucene.util.Bits;
+ using ToStringUtils = org.apache.lucene.util.ToStringUtils;
+
+
+ /// <summary>
+ /// Query that is boosted by a ValueSource
+ /// </summary>
+ // TODO: BoostedQuery and BoostingQuery in the same module?
+ // something has to give
+ public class BoostedQuery : Query
+ {
+ private Query q;
+ private readonly ValueSource boostVal; // optional, can be null
+
+ public BoostedQuery(Query subQuery, ValueSource boostVal)
+ {
+ this.q = subQuery;
+ this.boostVal = boostVal;
+ }
+
+ public virtual Query Query
+ {
+ get
+ {
+ return q;
+ }
+ }
+ public virtual ValueSource ValueSource
+ {
+ get
+ {
+ return boostVal;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Query rewrite(org.apache.lucene.index.IndexReader reader) throws java.io.IOException
+ public override Query rewrite(IndexReader reader)
+ {
+ Query newQ = q.rewrite(reader);
+ if (newQ == q)
+ {
+ return this;
+ }
+ BoostedQuery bq = (BoostedQuery)this.MemberwiseClone();
+ bq.q = newQ;
+ return bq;
+ }
+
+ public override void extractTerms(HashSet<Term> terms)
+ {
+ q.extractTerms(terms);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Weight createWeight(IndexSearcher searcher) throws java.io.IOException
+ public override Weight createWeight(IndexSearcher searcher)
+ {
+ return new BoostedQuery.BoostedWeight(this, searcher);
+ }
+
+ private class BoostedWeight : Weight
+ {
+ private readonly BoostedQuery outerInstance;
+
+ internal readonly IndexSearcher searcher;
+ internal Weight qWeight;
+ internal IDictionary fcontext;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public BoostedWeight(IndexSearcher searcher) throws java.io.IOException
+ public BoostedWeight(BoostedQuery outerInstance, IndexSearcher searcher)
+ {
+ this.outerInstance = outerInstance;
+ this.searcher = searcher;
+ this.qWeight = outerInstance.q.createWeight(searcher);
+ this.fcontext = ValueSource.newContext(searcher);
+ outerInstance.boostVal.createWeight(fcontext,searcher);
+ }
+
+ public override Query Query
+ {
+ get
+ {
+ return outerInstance;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public float getValueForNormalization() throws java.io.IOException
+ public override float ValueForNormalization
+ {
+ get
+ {
+ float sum = qWeight.ValueForNormalization;
+ sum *= Boost * Boost;
+ return sum;
+ }
+ }
+
+ public override void normalize(float norm, float topLevelBoost)
+ {
+ topLevelBoost *= Boost;
+ qWeight.normalize(norm, topLevelBoost);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Scorer scorer(org.apache.lucene.index.AtomicReaderContext context, org.apache.lucene.util.Bits acceptDocs) throws java.io.IOException
+ public override Scorer scorer(AtomicReaderContext context, Bits acceptDocs)
+ {
+ Scorer subQueryScorer = qWeight.scorer(context, acceptDocs);
+ if (subQueryScorer == null)
+ {
+ return null;
+ }
+ return new BoostedQuery.CustomScorer(outerInstance, context, this, Boost, subQueryScorer, outerInstance.boostVal);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public Explanation explain(org.apache.lucene.index.AtomicReaderContext readerContext, int doc) throws java.io.IOException
+ public override Explanation explain(AtomicReaderContext readerContext, int doc)
+ {
+ Explanation subQueryExpl = qWeight.explain(readerContext,doc);
+ if (!subQueryExpl.Match)
+ {
+ return subQueryExpl;
+ }
+ FunctionValues vals = outerInstance.boostVal.getValues(fcontext, readerContext);
+ float sc = subQueryExpl.Value * vals.floatVal(doc);
+ Explanation res = new ComplexExplanation(true, sc, outerInstance.ToString() + ", product of:");
+ res.addDetail(subQueryExpl);
+ res.addDetail(vals.explain(doc));
+ return res;
+ }
+ }
+
+
+ private class CustomScorer : Scorer
+ {
+ private readonly BoostedQuery outerInstance;
+
+ internal readonly BoostedQuery.BoostedWeight weight;
+ internal readonly float qWeight;
+ internal readonly Scorer scorer;
+ internal readonly FunctionValues vals;
+ internal readonly AtomicReaderContext readerContext;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private CustomScorer(org.apache.lucene.index.AtomicReaderContext readerContext, BoostedQuery.BoostedWeight w, float qWeight, Scorer scorer, ValueSource vs) throws java.io.IOException
+ internal CustomScorer(BoostedQuery outerInstance, AtomicReaderContext readerContext, BoostedQuery.BoostedWeight w, float qWeight, Scorer scorer, ValueSource vs) : base(w)
+ {
+ this.outerInstance = outerInstance;
+ this.weight = w;
+ this.qWeight = qWeight;
+ this.scorer = scorer;
+ this.readerContext = readerContext;
+ this.vals = vs.getValues(weight.fcontext, readerContext);
+ }
+
+ public override int docID()
+ {
+ return scorer.docID();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int advance(int target) throws java.io.IOException
+ public override int advance(int target)
+ {
+ return scorer.advance(target);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int nextDoc() throws java.io.IOException
+ public override int nextDoc()
+ {
+ return scorer.nextDoc();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public float score() throws java.io.IOException
+ public override float score()
+ {
+ float score = qWeight * scorer.score() * vals.floatVal(scorer.docID());
+
+ // Current Lucene priority queues can't handle NaN and -Infinity, so
+ // map to -Float.MAX_VALUE. This conditional handles both -infinity
+ // and NaN since comparisons with NaN are always false.
+ return score > float.NegativeInfinity ? score : -float.MaxValue;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int freq() throws java.io.IOException
+ public override int freq()
+ {
+ return scorer.freq();
+ }
+
+ public override ICollection<ChildScorer> Children
+ {
+ get
+ {
+ return Collections.singleton(new ChildScorer(scorer, "CUSTOM"));
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public Explanation explain(int doc) throws java.io.IOException
+ public virtual Explanation explain(int doc)
+ {
+ Explanation subQueryExpl = weight.qWeight.explain(readerContext,doc);
+ if (!subQueryExpl.Match)
+ {
+ return subQueryExpl;
+ }
+ float sc = subQueryExpl.Value * vals.floatVal(doc);
+ Explanation res = new ComplexExplanation(true, sc, outerInstance.ToString() + ", product of:");
+ res.addDetail(subQueryExpl);
+ res.addDetail(vals.explain(doc));
+ return res;
+ }
+
+ public override long cost()
+ {
+ return scorer.cost();
+ }
+ }
+
+
+ public override string ToString(string field)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("boost(").Append(q.ToString(field)).Append(',').Append(boostVal).Append(')');
+ sb.Append(ToStringUtils.boost(Boost));
+ return sb.ToString();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (!base.Equals(o))
+ {
+ return false;
+ }
+ BoostedQuery other = (BoostedQuery)o;
+ return this.q.Equals(other.q) && this.boostVal.Equals(other.boostVal);
+ }
+
+ public override int GetHashCode()
+ {
+ int h = q.GetHashCode();
+ h ^= (h << 17) | ((int)((uint)h >> 16));
+ h += boostVal.GetHashCode();
+ h ^= (h << 8) | ((int)((uint)h >> 25));
+ h += float.floatToIntBits(Boost);
+ return h;
+ }
+
+ }
+
+}
\ No newline at end of file
[10/11] git commit: Skeleton porting of Lucene.Net.Misc
Posted by sy...@apache.org.
Skeleton porting of Lucene.Net.Misc
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/674f0cb9
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/674f0cb9
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/674f0cb9
Branch: refs/heads/master
Commit: 674f0cb97dfae0961d5f9622f49f17d891be08bc
Parents: 882f487
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Tue Sep 16 01:39:08 2014 +0300
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Tue Sep 16 01:39:08 2014 +0300
----------------------------------------------------------------------
src/Lucene.Net.Misc/ByteBuffer.cs | 325 ++++++
src/Lucene.Net.Misc/Document/LazyDocument.cs | 226 ++++
.../Index/CompoundFileExtractor.cs | 165 +++
src/Lucene.Net.Misc/Index/IndexSplitter.cs | 200 ++++
.../Index/MultiPassIndexSplitter.cs | 329 ++++++
src/Lucene.Net.Misc/Index/PKIndexSplitter.cs | 220 ++++
.../Index/Sorter/BlockJoinComparatorSource.cs | 321 ++++++
.../Sorter/EarlyTerminatingSortingCollector.cs | 147 +++
src/Lucene.Net.Misc/Index/Sorter/Sorter.cs | 404 +++++++
.../Index/Sorter/SortingAtomicReader.cs | 1081 ++++++++++++++++++
.../Index/Sorter/SortingMergePolicy.cs | 309 +++++
src/Lucene.Net.Misc/Lucene.Net.Misc.csproj | 73 ++
src/Lucene.Net.Misc/Misc/GetTermInfo.cs | 74 ++
src/Lucene.Net.Misc/Misc/HighFreqTerms.cs | 230 ++++
src/Lucene.Net.Misc/Misc/IndexMergeTool.cs | 66 ++
src/Lucene.Net.Misc/Misc/SweetSpotSimilarity.cs | 238 ++++
src/Lucene.Net.Misc/Misc/TermStats.cs | 55 +
src/Lucene.Net.Misc/Properties/AssemblyInfo.cs | 35 +
src/Lucene.Net.Misc/Store/NativePosixUtil.cs | 64 ++
.../Store/NativeUnixDirectory.cs | 527 +++++++++
src/Lucene.Net.Misc/Store/WindowsDirectory.cs | 181 +++
src/Lucene.Net.Misc/Util/Fst/ListOfOutputs.cs | 246 ++++
.../Util/Fst/UpToTwoPositiveIntOutputs.cs | 328 ++++++
23 files changed, 5844 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/ByteBuffer.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/ByteBuffer.cs b/src/Lucene.Net.Misc/ByteBuffer.cs
new file mode 100644
index 0000000..204f7de
--- /dev/null
+++ b/src/Lucene.Net.Misc/ByteBuffer.cs
@@ -0,0 +1,325 @@
+//-------------------------------------------------------------------------------------------
+// Copyright © 2007 - 2014 Tangible Software Solutions Inc.
+// This class can be used by anyone provided that the copyright notice remains intact.
+//
+// This class is used to simulate the java.nio.ByteBuffer class in C#.
+//
+// Instances are only obtainable via the static 'allocate' method.
+//
+// Some methods are not available:
+// Methods which create shared views of the buffer, such as: array,
+// asCharBuffer, asDoubleBuffer, asFloatBuffer, asIntBuffer, asLongBuffer,
+// asReadOnlyBuffer, asShortBuffer, duplicate, slice, & wrap.
+//
+// Methods mark, reset, isReadOnly, order, compareTo, arrayOffset, & limit (setter).
+//-------------------------------------------------------------------------------------------
+public class ByteBuffer
+{
+ //'Mode' is only used to determine whether to return data length or capacity from the 'limit' method:
+ private enum Mode
+ {
+ Read,
+ Write
+ }
+ private Mode mode;
+
+ private System.IO.MemoryStream stream;
+ private System.IO.BinaryReader reader;
+ private System.IO.BinaryWriter writer;
+
+ private ByteBuffer()
+ {
+ stream = new System.IO.MemoryStream();
+ reader = new System.IO.BinaryReader(stream);
+ writer = new System.IO.BinaryWriter(stream);
+ }
+
+ ~ByteBuffer()
+ {
+ reader.Close();
+ writer.Close();
+ stream.Close();
+ stream.Dispose();
+ }
+
+ public static ByteBuffer allocate(int capacity)
+ {
+ ByteBuffer buffer = new ByteBuffer();
+ buffer.stream.Capacity = capacity;
+ buffer.mode = Mode.Write;
+ return buffer;
+ }
+
+ public static ByteBuffer allocateDirect(int capacity)
+ {
+ //this wrapper class makes no distinction between 'allocate' & 'allocateDirect'
+ return allocate(capacity);
+ }
+
+ public int capacity()
+ {
+ return stream.Capacity;
+ }
+
+ public ByteBuffer flip()
+ {
+ mode = Mode.Read;
+ stream.SetLength(stream.Position);
+ stream.Position = 0;
+ return this;
+ }
+
+ public ByteBuffer clear()
+ {
+ mode = Mode.Write;
+ stream.Position = 0;
+ return this;
+ }
+
+ public ByteBuffer compact()
+ {
+ mode = Mode.Write;
+ System.IO.MemoryStream newStream = new System.IO.MemoryStream(stream.Capacity);
+ stream.CopyTo(newStream);
+ stream = newStream;
+ return this;
+ }
+
+ public ByteBuffer rewind()
+ {
+ stream.Position = 0;
+ return this;
+ }
+
+ public long limit()
+ {
+ if (mode == Mode.Write)
+ return stream.Capacity;
+ else
+ return stream.Length;
+ }
+
+ public long position()
+ {
+ return stream.Position;
+ }
+
+ public ByteBuffer position(long newPosition)
+ {
+ stream.Position = newPosition;
+ return this;
+ }
+
+ public long remaining()
+ {
+ return this.limit() - this.position();
+ }
+
+ public bool hasRemaining()
+ {
+ return this.remaining() > 0;
+ }
+
+ public int get()
+ {
+ return stream.ReadByte();
+ }
+
+ public ByteBuffer get(byte[] dst, int offset, int length)
+ {
+ stream.Read(dst, offset, length);
+ return this;
+ }
+
+ public ByteBuffer put(byte b)
+ {
+ stream.WriteByte(b);
+ return this;
+ }
+
+ public ByteBuffer put(byte[] src, int offset, int length)
+ {
+ stream.Write(src, offset, length);
+ return this;
+ }
+
+ public bool Equals(ByteBuffer other)
+ {
+ if (other != null && this.remaining() == other.remaining())
+ {
+ long thisOriginalPosition = this.position();
+ long otherOriginalPosition = other.position();
+
+ bool differenceFound = false;
+ while (stream.Position < stream.Length)
+ {
+ if (this.get() != other.get())
+ {
+ differenceFound = true;
+ break;
+ }
+ }
+
+ this.position(thisOriginalPosition);
+ other.position(otherOriginalPosition);
+
+ return ! differenceFound;
+ }
+ else
+ return false;
+ }
+
+ //methods using the internal BinaryReader:
+ public char getChar()
+ {
+ return reader.ReadChar();
+ }
+ public char getChar(int index)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ char value = reader.ReadChar();
+ stream.Position = originalPosition;
+ return value;
+ }
+ public double getDouble()
+ {
+ return reader.ReadDouble();
+ }
+ public double getDouble(int index)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ double value = reader.ReadDouble();
+ stream.Position = originalPosition;
+ return value;
+ }
+ public float getFloat()
+ {
+ return reader.ReadSingle();
+ }
+ public float getFloat(int index)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ float value = reader.ReadSingle();
+ stream.Position = originalPosition;
+ return value;
+ }
+ public int getInt()
+ {
+ return reader.ReadInt32();
+ }
+ public int getInt(int index)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ int value = reader.ReadInt32();
+ stream.Position = originalPosition;
+ return value;
+ }
+ public long getLong()
+ {
+ return reader.ReadInt64();
+ }
+ public long getLong(int index)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ long value = reader.ReadInt64();
+ stream.Position = originalPosition;
+ return value;
+ }
+ public short getShort()
+ {
+ return reader.ReadInt16();
+ }
+ public short getShort(int index)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ short value = reader.ReadInt16();
+ stream.Position = originalPosition;
+ return value;
+ }
+
+ //methods using the internal BinaryWriter:
+ public ByteBuffer putChar(char value)
+ {
+ writer.Write(value);
+ return this;
+ }
+ public ByteBuffer putChar(int index, char value)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ writer.Write(value);
+ stream.Position = originalPosition;
+ return this;
+ }
+ public ByteBuffer putDouble(double value)
+ {
+ writer.Write(value);
+ return this;
+ }
+ public ByteBuffer putDouble(int index, double value)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ writer.Write(value);
+ stream.Position = originalPosition;
+ return this;
+ }
+ public ByteBuffer putFloat(float value)
+ {
+ writer.Write(value);
+ return this;
+ }
+ public ByteBuffer putFloat(int index, float value)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ writer.Write(value);
+ stream.Position = originalPosition;
+ return this;
+ }
+ public ByteBuffer putInt(int value)
+ {
+ writer.Write(value);
+ return this;
+ }
+ public ByteBuffer putInt(int index, int value)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ writer.Write(value);
+ stream.Position = originalPosition;
+ return this;
+ }
+ public ByteBuffer putLong(long value)
+ {
+ writer.Write(value);
+ return this;
+ }
+ public ByteBuffer putLong(int index, long value)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ writer.Write(value);
+ stream.Position = originalPosition;
+ return this;
+ }
+ public ByteBuffer putShort(short value)
+ {
+ writer.Write(value);
+ return this;
+ }
+ public ByteBuffer putShort(int index, short value)
+ {
+ long originalPosition = stream.Position;
+ stream.Position = index;
+ writer.Write(value);
+ stream.Position = originalPosition;
+ return this;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Document/LazyDocument.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Document/LazyDocument.cs b/src/Lucene.Net.Misc/Document/LazyDocument.cs
new file mode 100644
index 0000000..6faed94
--- /dev/null
+++ b/src/Lucene.Net.Misc/Document/LazyDocument.cs
@@ -0,0 +1,226 @@
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace org.apache.lucene.document
+{
+
+ /// <summary>
+ /// Copyright 2004 The Apache Software Foundation
+ ///
+ /// Licensed 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.
+ /// </summary>
+
+ using Analyzer = org.apache.lucene.analysis.Analyzer;
+ using TokenStream = org.apache.lucene.analysis.TokenStream;
+ using FieldInfo = org.apache.lucene.index.FieldInfo;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using IndexableField = org.apache.lucene.index.IndexableField;
+ using IndexableFieldType = org.apache.lucene.index.IndexableFieldType;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+ /// <summary>
+ /// Defers actually loading a field's value until you ask
+ /// for it. You must not use the returned Field instances
+ /// after the provided reader has been closed. </summary>
+ /// <seealso cref= #getField </seealso>
+ public class LazyDocument
+ {
+ private readonly IndexReader reader;
+ private readonly int docID;
+
+ // null until first field is loaded
+ private Document doc;
+
+ private IDictionary<int?, IList<LazyField>> fields = new Dictionary<int?, IList<LazyField>>();
+ private HashSet<string> fieldNames = new HashSet<string>();
+
+ public LazyDocument(IndexReader reader, int docID)
+ {
+ this.reader = reader;
+ this.docID = docID;
+ }
+
+ /// <summary>
+ /// Creates an IndexableField whose value will be lazy loaded if and
+ /// when it is used.
+ /// <para>
+ /// <b>NOTE:</b> This method must be called once for each value of the field
+ /// name specified in sequence that the values exist. This method may not be
+ /// used to generate multiple, lazy, IndexableField instances refering to
+ /// the same underlying IndexableField instance.
+ /// </para>
+ /// <para>
+ /// The lazy loading of field values from all instances of IndexableField
+ /// objects returned by this method are all backed by a single Document
+ /// per LazyDocument instance.
+ /// </para>
+ /// </summary>
+ public virtual IndexableField getField(FieldInfo fieldInfo)
+ {
+
+ fieldNames.Add(fieldInfo.name);
+ IList<LazyField> values = fields[fieldInfo.number];
+ if (null == values)
+ {
+ values = new List<>();
+ fields[fieldInfo.number] = values;
+ }
+
+ LazyField value = new LazyField(this, fieldInfo.name, fieldInfo.number);
+ values.Add(value);
+
+ lock (this)
+ {
+ // edge case: if someone asks this LazyDoc for more LazyFields
+ // after other LazyFields from the same LazyDoc have been
+ // actuallized, we need to force the doc to be re-fetched
+ // so the new LazyFields are also populated.
+ doc = null;
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// non-private for test only access
+ /// @lucene.internal
+ /// </summary>
+ internal virtual Document Document
+ {
+ get
+ {
+ lock (this)
+ {
+ if (doc == null)
+ {
+ try
+ {
+ doc = reader.document(docID, fieldNames);
+ }
+ catch (IOException ioe)
+ {
+ throw new IllegalStateException("unable to load document", ioe);
+ }
+ }
+ return doc;
+ }
+ }
+ }
+
+ // :TODO: synchronize to prevent redundent copying? (sync per field name?)
+ private void fetchRealValues(string name, int fieldNum)
+ {
+ Document d = Document;
+
+ IList<LazyField> lazyValues = fields[fieldNum];
+ IndexableField[] realValues = d.getFields(name);
+
+ Debug.Assert(realValues.Length <= lazyValues.Count, "More lazy values then real values for field: " + name);
+
+ for (int i = 0; i < lazyValues.Count; i++)
+ {
+ LazyField f = lazyValues[i];
+ if (null != f)
+ {
+ f.realValue = realValues[i];
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// @lucene.internal
+ /// </summary>
+ public class LazyField : IndexableField
+ {
+ private readonly LazyDocument outerInstance;
+
+ internal string name_Renamed;
+ internal int fieldNum;
+ internal volatile IndexableField realValue = null;
+
+ internal LazyField(LazyDocument outerInstance, string name, int fieldNum)
+ {
+ this.outerInstance = outerInstance;
+ this.name_Renamed = name;
+ this.fieldNum = fieldNum;
+ }
+
+ /// <summary>
+ /// non-private for test only access
+ /// @lucene.internal
+ /// </summary>
+ public virtual bool hasBeenLoaded()
+ {
+ return null != realValue;
+ }
+
+ internal virtual IndexableField RealValue
+ {
+ get
+ {
+ if (null == realValue)
+ {
+ outerInstance.fetchRealValues(name_Renamed, fieldNum);
+ }
+ Debug.Assert(hasBeenLoaded(), "field value was not lazy loaded");
+ Debug.Assert(realValue.name().Equals(name()), "realvalue name != name: " + realValue.name() + " != " + name());
+
+ return realValue;
+ }
+ }
+
+ public override string name()
+ {
+ return name_Renamed;
+ }
+
+ public override float boost()
+ {
+ return 1.0f;
+ }
+
+ public override BytesRef binaryValue()
+ {
+ return RealValue.binaryValue();
+ }
+
+ public override string stringValue()
+ {
+ return RealValue.stringValue();
+ }
+
+ public override Reader readerValue()
+ {
+ return RealValue.readerValue();
+ }
+
+ public override Number numericValue()
+ {
+ return RealValue.numericValue();
+ }
+
+ public override IndexableFieldType fieldType()
+ {
+ return RealValue.fieldType();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.analysis.TokenStream tokenStream(org.apache.lucene.analysis.Analyzer analyzer) throws java.io.IOException
+ public override TokenStream tokenStream(Analyzer analyzer)
+ {
+ return RealValue.tokenStream(analyzer);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Index/CompoundFileExtractor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Index/CompoundFileExtractor.cs b/src/Lucene.Net.Misc/Index/CompoundFileExtractor.cs
new file mode 100644
index 0000000..855b6f3
--- /dev/null
+++ b/src/Lucene.Net.Misc/Index/CompoundFileExtractor.cs
@@ -0,0 +1,165 @@
+using System;
+
+namespace org.apache.lucene.index
+{
+
+ /*
+ * 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.
+ */
+
+ /// <summary>
+ /// Prints the filename and size of each file within a given compound file.
+ /// Add the -extract flag to extract files to the current working directory.
+ /// In order to make the extracted version of the index work, you have to copy
+ /// the segments file from the compound index into the directory where the extracted files are stored. </summary>
+ /// <param name="args"> Usage: org.apache.lucene.index.IndexReader [-extract] <cfsfile> </param>
+
+
+ using CompoundFileDirectory = org.apache.lucene.store.CompoundFileDirectory;
+ using Directory = org.apache.lucene.store.Directory;
+ using FSDirectory = org.apache.lucene.store.FSDirectory;
+ using IOContext = org.apache.lucene.store.IOContext;
+ using IndexInput = org.apache.lucene.store.IndexInput;
+ using ArrayUtil = org.apache.lucene.util.ArrayUtil;
+ using CommandLineUtil = org.apache.lucene.util.CommandLineUtil;
+
+ /// <summary>
+ /// Command-line tool for extracting sub-files out of a compound file.
+ /// </summary>
+ public class CompoundFileExtractor
+ {
+
+ public static void Main(string[] args)
+ {
+ string filename = null;
+ bool extract = false;
+ string dirImpl = null;
+
+ int j = 0;
+ while (j < args.Length)
+ {
+ string arg = args[j];
+ if ("-extract".Equals(arg))
+ {
+ extract = true;
+ }
+ else if ("-dir-impl".Equals(arg))
+ {
+ if (j == args.Length - 1)
+ {
+ Console.WriteLine("ERROR: missing value for -dir-impl option");
+ Environment.Exit(1);
+ }
+ j++;
+ dirImpl = args[j];
+ }
+ else if (filename == null)
+ {
+ filename = arg;
+ }
+ j++;
+ }
+
+ if (filename == null)
+ {
+ Console.WriteLine("Usage: org.apache.lucene.index.CompoundFileExtractor [-extract] [-dir-impl X] <cfsfile>");
+ return;
+ }
+
+ Directory dir = null;
+ CompoundFileDirectory cfr = null;
+ IOContext context = IOContext.READ;
+
+ try
+ {
+ File file = new File(filename);
+ string dirname = file.AbsoluteFile.Parent;
+ filename = file.Name;
+ if (dirImpl == null)
+ {
+ dir = FSDirectory.open(new File(dirname));
+ }
+ else
+ {
+ dir = CommandLineUtil.newFSDirectory(dirImpl, new File(dirname));
+ }
+
+ cfr = new CompoundFileDirectory(dir, filename, IOContext.DEFAULT, false);
+
+ string[] files = cfr.listAll();
+ ArrayUtil.timSort(files); // sort the array of filename so that the output is more readable
+
+ for (int i = 0; i < files.Length; ++i)
+ {
+ long len = cfr.fileLength(files[i]);
+
+ if (extract)
+ {
+ Console.WriteLine("extract " + files[i] + " with " + len + " bytes to local directory...");
+ IndexInput ii = cfr.openInput(files[i], context);
+
+ FileOutputStream f = new FileOutputStream(files[i]);
+
+ // read and write with a small buffer, which is more effective than reading byte by byte
+ sbyte[] buffer = new sbyte[1024];
+ int chunk = buffer.Length;
+ while (len > 0)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int bufLen = (int) Math.min(chunk, len);
+ int bufLen = (int) Math.Min(chunk, len);
+ ii.readBytes(buffer, 0, bufLen);
+ f.write(buffer, 0, bufLen);
+ len -= bufLen;
+ }
+
+ f.close();
+ ii.close();
+ }
+ else
+ {
+ Console.WriteLine(files[i] + ": " + len + " bytes");
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ Console.WriteLine(ioe.ToString());
+ Console.Write(ioe.StackTrace);
+ }
+ finally
+ {
+ try
+ {
+ if (dir != null)
+ {
+ dir.close();
+ }
+ if (cfr != null)
+ {
+ cfr.close();
+ }
+ }
+ catch (IOException ioe)
+ {
+ Console.WriteLine(ioe.ToString());
+ Console.Write(ioe.StackTrace);
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Index/IndexSplitter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Index/IndexSplitter.cs b/src/Lucene.Net.Misc/Index/IndexSplitter.cs
new file mode 100644
index 0000000..a0e9946
--- /dev/null
+++ b/src/Lucene.Net.Misc/Index/IndexSplitter.cs
@@ -0,0 +1,200 @@
+using System;
+using System.Collections.Generic;
+
+/*
+ * 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.
+ */
+namespace org.apache.lucene.index
+{
+
+
+ using FSDirectory = org.apache.lucene.store.FSDirectory;
+
+ /// <summary>
+ /// Command-line tool that enables listing segments in an
+ /// index, copying specific segments to another index, and
+ /// deleting segments from an index.
+ ///
+ /// <para>This tool does file-level copying of segments files.
+ /// This means it's unable to split apart a single segment
+ /// into multiple segments. For example if your index is a
+ /// single segment, this tool won't help. Also, it does basic
+ /// file-level copying (using simple
+ /// File{In,Out}putStream) so it will not work with non
+ /// FSDirectory Directory impls.</para>
+ ///
+ /// @lucene.experimental You can easily
+ /// accidentally remove segments from your index so be
+ /// careful!
+ /// </summary>
+ public class IndexSplitter
+ {
+ public SegmentInfos infos;
+
+ internal FSDirectory fsDir;
+
+ internal File dir;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public static void main(String[] args) throws Exception
+ public static void Main(string[] args)
+ {
+ if (args.Length < 2)
+ {
+ Console.Error.WriteLine("Usage: IndexSplitter <srcDir> -l (list the segments and their sizes)");
+ Console.Error.WriteLine("IndexSplitter <srcDir> <destDir> <segments>+");
+ Console.Error.WriteLine("IndexSplitter <srcDir> -d (delete the following segments)");
+ return;
+ }
+ File srcDir = new File(args[0]);
+ IndexSplitter @is = new IndexSplitter(srcDir);
+ if (!srcDir.exists())
+ {
+ throw new Exception("srcdir:" + srcDir.AbsolutePath + " doesn't exist");
+ }
+ if (args[1].Equals("-l"))
+ {
+ @is.listSegments();
+ }
+ else if (args[1].Equals("-d"))
+ {
+ IList<string> segs = new List<string>();
+ for (int x = 2; x < args.Length; x++)
+ {
+ segs.Add(args[x]);
+ }
+ @is.remove(segs.ToArray());
+ }
+ else
+ {
+ File targetDir = new File(args[1]);
+ IList<string> segs = new List<string>();
+ for (int x = 2; x < args.Length; x++)
+ {
+ segs.Add(args[x]);
+ }
+ @is.Split(targetDir, segs.ToArray());
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public IndexSplitter(java.io.File dir) throws java.io.IOException
+ public IndexSplitter(File dir)
+ {
+ this.dir = dir;
+ fsDir = FSDirectory.open(dir);
+ infos = new SegmentInfos();
+ infos.read(fsDir);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public void listSegments() throws java.io.IOException
+ public virtual void listSegments()
+ {
+ DecimalFormat formatter = new DecimalFormat("###,###.###", DecimalFormatSymbols.getInstance(Locale.ROOT));
+ for (int x = 0; x < infos.size(); x++)
+ {
+ SegmentCommitInfo info = infos.info(x);
+ string sizeStr = formatter.format(info.sizeInBytes());
+ Console.WriteLine(info.info.name + " " + sizeStr);
+ }
+ }
+
+ private int getIdx(string name)
+ {
+ for (int x = 0; x < infos.size(); x++)
+ {
+ if (name.Equals(infos.info(x).info.name))
+ {
+ return x;
+ }
+ }
+ return -1;
+ }
+
+ private SegmentCommitInfo getInfo(string name)
+ {
+ for (int x = 0; x < infos.size(); x++)
+ {
+ if (name.Equals(infos.info(x).info.name))
+ {
+ return infos.info(x);
+ }
+ }
+ return null;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public void remove(String[] segs) throws java.io.IOException
+ public virtual void remove(string[] segs)
+ {
+ foreach (string n in segs)
+ {
+ int idx = getIdx(n);
+ infos.remove(idx);
+ }
+ infos.changed();
+ infos.commit(fsDir);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public void split(java.io.File destDir, String[] segs) throws java.io.IOException
+ public virtual void Split(File destDir, string[] segs)
+ {
+ destDir.mkdirs();
+ FSDirectory destFSDir = FSDirectory.open(destDir);
+ SegmentInfos destInfos = new SegmentInfos();
+ destInfos.counter = infos.counter;
+ foreach (string n in segs)
+ {
+ SegmentCommitInfo infoPerCommit = getInfo(n);
+ SegmentInfo info = infoPerCommit.info;
+ // Same info just changing the dir:
+ SegmentInfo newInfo = new SegmentInfo(destFSDir, info.Version, info.name, info.DocCount, info.UseCompoundFile, info.Codec, info.Diagnostics);
+ destInfos.add(new SegmentCommitInfo(newInfo, infoPerCommit.DelCount, infoPerCommit.DelGen, infoPerCommit.FieldInfosGen));
+ // now copy files over
+ ICollection<string> files = infoPerCommit.files();
+ foreach (String srcName in files)
+ {
+ File srcFile = new File(dir, srcName);
+ File destFile = new File(destDir, srcName);
+ copyFile(srcFile, destFile);
+ }
+ }
+ destInfos.changed();
+ destInfos.commit(destFSDir);
+ // System.out.println("destDir:"+destDir.getAbsolutePath());
+ }
+
+ private static readonly sbyte[] copyBuffer = new sbyte[32 * 1024];
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private static void copyFile(java.io.File src, java.io.File dst) throws java.io.IOException
+ private static void copyFile(File src, File dst)
+ {
+ InputStream @in = new FileInputStream(src);
+ OutputStream @out = new FileOutputStream(dst);
+ int len;
+ while ((len = @in.read(copyBuffer)) > 0)
+ {
+ @out.write(copyBuffer, 0, len);
+ }
+ @in.close();
+ @out.close();
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Index/MultiPassIndexSplitter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Index/MultiPassIndexSplitter.cs b/src/Lucene.Net.Misc/Index/MultiPassIndexSplitter.cs
new file mode 100644
index 0000000..1e03fed
--- /dev/null
+++ b/src/Lucene.Net.Misc/Index/MultiPassIndexSplitter.cs
@@ -0,0 +1,329 @@
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace org.apache.lucene.index
+{
+
+ /*
+ * 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 OpenMode = org.apache.lucene.index.IndexWriterConfig.OpenMode;
+ using Directory = org.apache.lucene.store.Directory;
+ using FSDirectory = org.apache.lucene.store.FSDirectory;
+ using FixedBitSet = org.apache.lucene.util.FixedBitSet;
+ using Bits = org.apache.lucene.util.Bits;
+ using Version = org.apache.lucene.util.Version;
+
+ /// <summary>
+ /// This tool splits input index into multiple equal parts. The method employed
+ /// here uses <seealso cref="IndexWriter#addIndexes(IndexReader[])"/> where the input data
+ /// comes from the input index with artificially applied deletes to the document
+ /// id-s that fall outside the selected partition.
+ /// <para>Note 1: Deletes are only applied to a buffered list of deleted docs and
+ /// don't affect the source index - this tool works also with read-only indexes.
+ /// </para>
+ /// <para>Note 2: the disadvantage of this tool is that source index needs to be
+ /// read as many times as there are parts to be created, hence the name of this
+ /// tool.
+ ///
+ /// </para>
+ /// <para><b>NOTE</b>: this tool is unaware of documents added
+ /// atomically via <seealso cref="IndexWriter#addDocuments"/> or {@link
+ /// IndexWriter#updateDocuments}, which means it can easily
+ /// break up such document groups.
+ /// </para>
+ /// </summary>
+ public class MultiPassIndexSplitter
+ {
+
+ /// <summary>
+ /// Split source index into multiple parts. </summary>
+ /// <param name="in"> source index, can have deletions, can have
+ /// multiple segments (or multiple readers). </param>
+ /// <param name="outputs"> list of directories where the output parts will be stored. </param>
+ /// <param name="seq"> if true, then the source index will be split into equal
+ /// increasing ranges of document id-s. If false, source document id-s will be
+ /// assigned in a deterministic round-robin fashion to one of the output splits. </param>
+ /// <exception cref="IOException"> If there is a low-level I/O error </exception>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public void split(org.apache.lucene.util.Version version, IndexReader in, org.apache.lucene.store.Directory[] outputs, boolean seq) throws java.io.IOException
+ public virtual void Split(Version version, IndexReader @in, Directory[] outputs, bool seq)
+ {
+ if (outputs == null || outputs.Length < 2)
+ {
+ throw new IOException("Invalid number of outputs.");
+ }
+ if (@in == null || @in.numDocs() < 2)
+ {
+ throw new IOException("Not enough documents for splitting");
+ }
+ int numParts = outputs.Length;
+ // wrap a potentially read-only input
+ // this way we don't have to preserve original deletions because neither
+ // deleteDocument(int) or undeleteAll() is applied to the wrapped input index.
+ FakeDeleteIndexReader input = new FakeDeleteIndexReader(@in);
+ int maxDoc = input.maxDoc();
+ int partLen = maxDoc / numParts;
+ for (int i = 0; i < numParts; i++)
+ {
+ input.undeleteAll();
+ if (seq) // sequential range
+ {
+ int lo = partLen * i;
+ int hi = lo + partLen;
+ // below range
+ for (int j = 0; j < lo; j++)
+ {
+ input.deleteDocument(j);
+ }
+ // above range - last part collects all id-s that remained due to
+ // integer rounding errors
+ if (i < numParts - 1)
+ {
+ for (int j = hi; j < maxDoc; j++)
+ {
+ input.deleteDocument(j);
+ }
+ }
+ }
+ else
+ {
+ // round-robin
+ for (int j = 0; j < maxDoc; j++)
+ {
+ if ((j + numParts - i) % numParts != 0)
+ {
+ input.deleteDocument(j);
+ }
+ }
+ }
+ IndexWriter w = new IndexWriter(outputs[i], new IndexWriterConfig(version, null)
+ .setOpenMode(OpenMode.CREATE));
+ Console.Error.WriteLine("Writing part " + (i + 1) + " ...");
+ // pass the subreaders directly, as our wrapper's numDocs/hasDeletetions are not up-to-date
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final java.util.List<? extends FakeDeleteAtomicIndexReader> sr = input.getSequentialSubReaders();
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+ IList<?> sr = input.SequentialSubReaders;
+ w.addIndexes(sr.ToArray()); // TODO: maybe take List<IR> here?
+ w.close();
+ }
+ Console.Error.WriteLine("Done.");
+ }
+
+//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
+//ORIGINAL LINE: @SuppressWarnings("deprecation") public static void main(String[] args) throws Exception
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+ public static void Main(string[] args)
+ {
+ if (args.Length < 5)
+ {
+ Console.Error.WriteLine("Usage: MultiPassIndexSplitter -out <outputDir> -num <numParts> [-seq] <inputIndex1> [<inputIndex2 ...]");
+ Console.Error.WriteLine("\tinputIndex\tpath to input index, multiple values are ok");
+ Console.Error.WriteLine("\t-out ouputDir\tpath to output directory to contain partial indexes");
+ Console.Error.WriteLine("\t-num numParts\tnumber of parts to produce");
+ Console.Error.WriteLine("\t-seq\tsequential docid-range split (default is round-robin)");
+ Environment.Exit(-1);
+ }
+ List<IndexReader> indexes = new List<IndexReader>();
+ string outDir = null;
+ int numParts = -1;
+ bool seq = false;
+ for (int i = 0; i < args.Length; i++)
+ {
+ if (args[i].Equals("-out"))
+ {
+ outDir = args[++i];
+ }
+ else if (args[i].Equals("-num"))
+ {
+ numParts = Convert.ToInt32(args[++i]);
+ }
+ else if (args[i].Equals("-seq"))
+ {
+ seq = true;
+ }
+ else
+ {
+ File file = new File(args[i]);
+ if (!file.exists() || !file.Directory)
+ {
+ Console.Error.WriteLine("Invalid input path - skipping: " + file);
+ continue;
+ }
+ Directory dir = FSDirectory.open(new File(args[i]));
+ try
+ {
+ if (!DirectoryReader.indexExists(dir))
+ {
+ Console.Error.WriteLine("Invalid input index - skipping: " + file);
+ continue;
+ }
+ }
+ catch (Exception)
+ {
+ Console.Error.WriteLine("Invalid input index - skipping: " + file);
+ continue;
+ }
+ indexes.Add(DirectoryReader.open(dir));
+ }
+ }
+ if (outDir == null)
+ {
+ throw new Exception("Required argument missing: -out outputDir");
+ }
+ if (numParts < 2)
+ {
+ throw new Exception("Invalid value of required argument: -num numParts");
+ }
+ if (indexes.Count == 0)
+ {
+ throw new Exception("No input indexes to process");
+ }
+ File @out = new File(outDir);
+ if (!@out.mkdirs())
+ {
+ throw new Exception("Can't create output directory: " + @out);
+ }
+ Directory[] dirs = new Directory[numParts];
+ for (int i = 0; i < numParts; i++)
+ {
+ dirs[i] = FSDirectory.open(new File(@out, "part-" + i));
+ }
+ MultiPassIndexSplitter splitter = new MultiPassIndexSplitter();
+ IndexReader input;
+ if (indexes.Count == 1)
+ {
+ input = indexes[0];
+ }
+ else
+ {
+ input = new MultiReader(indexes.ToArray());
+ }
+ splitter.Split(Version.LUCENE_CURRENT, input, dirs, seq);
+ }
+
+ /// <summary>
+ /// This class emulates deletions on the underlying index.
+ /// </summary>
+ private sealed class FakeDeleteIndexReader : BaseCompositeReader<FakeDeleteAtomicIndexReader>
+ {
+
+ public FakeDeleteIndexReader(IndexReader reader) : base(initSubReaders(reader))
+ {
+ }
+
+ internal static FakeDeleteAtomicIndexReader[] initSubReaders(IndexReader reader)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final java.util.List<AtomicReaderContext> leaves = reader.leaves();
+ IList<AtomicReaderContext> leaves = reader.leaves();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final FakeDeleteAtomicIndexReader[] subs = new FakeDeleteAtomicIndexReader[leaves.size()];
+ FakeDeleteAtomicIndexReader[] subs = new FakeDeleteAtomicIndexReader[leaves.Count];
+ int i = 0;
+ foreach (AtomicReaderContext ctx in leaves)
+ {
+ subs[i++] = new FakeDeleteAtomicIndexReader(ctx.reader());
+ }
+ return subs;
+ }
+
+ public void deleteDocument(int docID)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int i = readerIndex(docID);
+ int i = readerIndex(docID);
+ SequentialSubReaders.get(i).deleteDocument(docID - readerBase(i));
+ }
+
+ public void undeleteAll()
+ {
+ foreach (FakeDeleteAtomicIndexReader r in SequentialSubReaders)
+ {
+ r.undeleteAll();
+ }
+ }
+
+ protected internal override void doClose()
+ {
+ }
+
+ // no need to override numDocs/hasDeletions,
+ // as we pass the subreaders directly to IW.addIndexes().
+ }
+
+ private sealed class FakeDeleteAtomicIndexReader : FilterAtomicReader
+ {
+ internal FixedBitSet liveDocs;
+
+ public FakeDeleteAtomicIndexReader(AtomicReader reader) : base(reader)
+ {
+ undeleteAll(); // initialize main bitset
+ }
+
+ public override int numDocs()
+ {
+ return liveDocs.cardinality();
+ }
+
+ public void undeleteAll()
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int maxDoc = in.maxDoc();
+ int maxDoc = @in.maxDoc();
+ liveDocs = new FixedBitSet(@in.maxDoc());
+ if (@in.hasDeletions())
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.Bits oldLiveDocs = in.getLiveDocs();
+ Bits oldLiveDocs = @in.LiveDocs;
+ Debug.Assert(oldLiveDocs != null);
+ // this loop is a little bit ineffective, as Bits has no nextSetBit():
+ for (int i = 0; i < maxDoc; i++)
+ {
+ if (oldLiveDocs.get(i))
+ {
+ liveDocs.set(i);
+ }
+ }
+ }
+ else
+ {
+ // mark all docs as valid
+ liveDocs.set(0, maxDoc);
+ }
+ }
+
+ public void deleteDocument(int n)
+ {
+ liveDocs.clear(n);
+ }
+
+ public override Bits LiveDocs
+ {
+ get
+ {
+ return liveDocs;
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Index/PKIndexSplitter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Index/PKIndexSplitter.cs b/src/Lucene.Net.Misc/Index/PKIndexSplitter.cs
new file mode 100644
index 0000000..f3e7ed4
--- /dev/null
+++ b/src/Lucene.Net.Misc/Index/PKIndexSplitter.cs
@@ -0,0 +1,220 @@
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace org.apache.lucene.index
+{
+
+ /*
+ * 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 OpenMode = org.apache.lucene.index.IndexWriterConfig.OpenMode;
+ using DocIdSet = org.apache.lucene.search.DocIdSet;
+ using DocIdSetIterator = org.apache.lucene.search.DocIdSetIterator;
+ using Filter = org.apache.lucene.search.Filter;
+ using TermRangeFilter = org.apache.lucene.search.TermRangeFilter;
+ using Directory = org.apache.lucene.store.Directory;
+ using Bits = org.apache.lucene.util.Bits;
+ using FixedBitSet = org.apache.lucene.util.FixedBitSet;
+ using IOUtils = org.apache.lucene.util.IOUtils;
+ using Version = org.apache.lucene.util.Version;
+
+ /// <summary>
+ /// Split an index based on a <seealso cref="Filter"/>.
+ /// </summary>
+
+ public class PKIndexSplitter
+ {
+ private readonly Filter docsInFirstIndex;
+ private readonly Directory input;
+ private readonly Directory dir1;
+ private readonly Directory dir2;
+ private readonly IndexWriterConfig config1;
+ private readonly IndexWriterConfig config2;
+
+ /// <summary>
+ /// Split an index based on a <seealso cref="Filter"/>. All documents that match the filter
+ /// are sent to dir1, remaining ones to dir2.
+ /// </summary>
+ public PKIndexSplitter(Version version, Directory input, Directory dir1, Directory dir2, Filter docsInFirstIndex) : this(input, dir1, dir2, docsInFirstIndex, newDefaultConfig(version), newDefaultConfig(version))
+ {
+ }
+
+ private static IndexWriterConfig newDefaultConfig(Version version)
+ {
+ return (new IndexWriterConfig(version, null)).setOpenMode(OpenMode.CREATE);
+ }
+
+ public PKIndexSplitter(Directory input, Directory dir1, Directory dir2, Filter docsInFirstIndex, IndexWriterConfig config1, IndexWriterConfig config2)
+ {
+ this.input = input;
+ this.dir1 = dir1;
+ this.dir2 = dir2;
+ this.docsInFirstIndex = docsInFirstIndex;
+ this.config1 = config1;
+ this.config2 = config2;
+ }
+
+ /// <summary>
+ /// Split an index based on a given primary key term
+ /// and a 'middle' term. If the middle term is present, it's
+ /// sent to dir2.
+ /// </summary>
+ public PKIndexSplitter(Version version, Directory input, Directory dir1, Directory dir2, Term midTerm) : this(version, input, dir1, dir2, new TermRangeFilter(midTerm.field(), null, midTerm.bytes(), true, false))
+ {
+ }
+
+ public PKIndexSplitter(Directory input, Directory dir1, Directory dir2, Term midTerm, IndexWriterConfig config1, IndexWriterConfig config2) : this(input, dir1, dir2, new TermRangeFilter(midTerm.field(), null, midTerm.bytes(), true, false), config1, config2)
+ {
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public void split() throws java.io.IOException
+ public virtual void Split()
+ {
+ bool success = false;
+ DirectoryReader reader = DirectoryReader.open(input);
+ try
+ {
+ // pass an individual config in here since one config can not be reused!
+ createIndex(config1, dir1, reader, docsInFirstIndex, false);
+ createIndex(config2, dir2, reader, docsInFirstIndex, true);
+ success = true;
+ }
+ finally
+ {
+ if (success)
+ {
+ IOUtils.close(reader);
+ }
+ else
+ {
+ IOUtils.closeWhileHandlingException(reader);
+ }
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private void createIndex(IndexWriterConfig config, org.apache.lucene.store.Directory target, IndexReader reader, org.apache.lucene.search.Filter preserveFilter, boolean negateFilter) throws java.io.IOException
+ private void createIndex(IndexWriterConfig config, Directory target, IndexReader reader, Filter preserveFilter, bool negateFilter)
+ {
+ bool success = false;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final IndexWriter w = new IndexWriter(target, config);
+ IndexWriter w = new IndexWriter(target, config);
+ try
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final java.util.List<AtomicReaderContext> leaves = reader.leaves();
+ IList<AtomicReaderContext> leaves = reader.leaves();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final IndexReader[] subReaders = new IndexReader[leaves.size()];
+ IndexReader[] subReaders = new IndexReader[leaves.Count];
+ int i = 0;
+ foreach (AtomicReaderContext ctx in leaves)
+ {
+ subReaders[i++] = new DocumentFilteredAtomicIndexReader(ctx, preserveFilter, negateFilter);
+ }
+ w.addIndexes(subReaders);
+ success = true;
+ }
+ finally
+ {
+ if (success)
+ {
+ IOUtils.close(w);
+ }
+ else
+ {
+ IOUtils.closeWhileHandlingException(w);
+ }
+ }
+ }
+
+ private class DocumentFilteredAtomicIndexReader : FilterAtomicReader
+ {
+ internal readonly Bits liveDocs;
+ internal readonly int numDocs_Renamed;
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public DocumentFilteredAtomicIndexReader(AtomicReaderContext context, org.apache.lucene.search.Filter preserveFilter, boolean negateFilter) throws java.io.IOException
+ public DocumentFilteredAtomicIndexReader(AtomicReaderContext context, Filter preserveFilter, bool negateFilter) : base(context.reader())
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int maxDoc = in.maxDoc();
+ int maxDoc = @in.maxDoc();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.FixedBitSet bits = new org.apache.lucene.util.FixedBitSet(maxDoc);
+ FixedBitSet bits = new FixedBitSet(maxDoc);
+ // ignore livedocs here, as we filter them later:
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.DocIdSet docs = preserveFilter.getDocIdSet(context, null);
+ DocIdSet docs = preserveFilter.getDocIdSet(context, null);
+ if (docs != null)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.DocIdSetIterator it = docs.iterator();
+ DocIdSetIterator it = docs.GetEnumerator();
+ if (it != null)
+ {
+ bits.or(it);
+ }
+ }
+ if (negateFilter)
+ {
+ bits.flip(0, maxDoc);
+ }
+
+ if (@in.hasDeletions())
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.Bits oldLiveDocs = in.getLiveDocs();
+ Bits oldLiveDocs = @in.LiveDocs;
+ Debug.Assert(oldLiveDocs != null);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.DocIdSetIterator it = bits.iterator();
+ DocIdSetIterator it = bits.GetEnumerator();
+ for (int i = it.nextDoc(); i < maxDoc; i = it.nextDoc())
+ {
+ if (!oldLiveDocs.get(i))
+ {
+ // we can safely modify the current bit, as the iterator already stepped over it:
+ bits.clear(i);
+ }
+ }
+ }
+
+ this.liveDocs = bits;
+ this.numDocs_Renamed = bits.cardinality();
+ }
+
+ public override int numDocs()
+ {
+ return numDocs_Renamed;
+ }
+
+ public override Bits LiveDocs
+ {
+ get
+ {
+ return liveDocs;
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Index/Sorter/BlockJoinComparatorSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Index/Sorter/BlockJoinComparatorSource.cs b/src/Lucene.Net.Misc/Index/Sorter/BlockJoinComparatorSource.cs
new file mode 100644
index 0000000..70ad20a
--- /dev/null
+++ b/src/Lucene.Net.Misc/Index/Sorter/BlockJoinComparatorSource.cs
@@ -0,0 +1,321 @@
+using System;
+
+namespace org.apache.lucene.index.sorter
+{
+
+ /*
+ * 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 DocIdSet = org.apache.lucene.search.DocIdSet;
+ using FieldComparator = org.apache.lucene.search.FieldComparator;
+ using FieldComparatorSource = org.apache.lucene.search.FieldComparatorSource;
+ using Filter = org.apache.lucene.search.Filter;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher; // javadocs
+ using Query = org.apache.lucene.search.Query; // javadocs
+ using ScoreDoc = org.apache.lucene.search.ScoreDoc; // javadocs
+ using Scorer = org.apache.lucene.search.Scorer;
+ using Sort = org.apache.lucene.search.Sort;
+ using SortField = org.apache.lucene.search.SortField;
+ using FixedBitSet = org.apache.lucene.util.FixedBitSet;
+
+ /// <summary>
+ /// Helper class to sort readers that contain blocks of documents.
+ /// <para>
+ /// Note that this class is intended to used with <seealso cref="SortingMergePolicy"/>,
+ /// and for other purposes has some limitations:
+ /// <ul>
+ /// <li>Cannot yet be used with <seealso cref="IndexSearcher#searchAfter(ScoreDoc, Query, int, Sort) IndexSearcher.searchAfter"/>
+ /// <li>Filling sort field values is not yet supported.
+ /// </ul>
+ /// @lucene.experimental
+ /// </para>
+ /// </summary>
+ // TODO: can/should we clean this thing up (e.g. return a proper sort value)
+ // and move to the join/ module?
+ public class BlockJoinComparatorSource : FieldComparatorSource
+ {
+ internal readonly Filter parentsFilter;
+ internal readonly Sort parentSort;
+ internal readonly Sort childSort;
+
+ /// <summary>
+ /// Create a new BlockJoinComparatorSource, sorting only blocks of documents
+ /// with {@code parentSort} and not reordering children with a block.
+ /// </summary>
+ /// <param name="parentsFilter"> Filter identifying parent documents </param>
+ /// <param name="parentSort"> Sort for parent documents </param>
+ public BlockJoinComparatorSource(Filter parentsFilter, Sort parentSort) : this(parentsFilter, parentSort, new Sort(SortField.FIELD_DOC))
+ {
+ }
+
+ /// <summary>
+ /// Create a new BlockJoinComparatorSource, specifying the sort order for both
+ /// blocks of documents and children within a block.
+ /// </summary>
+ /// <param name="parentsFilter"> Filter identifying parent documents </param>
+ /// <param name="parentSort"> Sort for parent documents </param>
+ /// <param name="childSort"> Sort for child documents in the same block </param>
+ public BlockJoinComparatorSource(Filter parentsFilter, Sort parentSort, Sort childSort)
+ {
+ this.parentsFilter = parentsFilter;
+ this.parentSort = parentSort;
+ this.childSort = childSort;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.FieldComparator<Integer> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws java.io.IOException
+ public override FieldComparator<int?> newComparator(string fieldname, int numHits, int sortPos, bool reversed)
+ {
+ // we keep parallel slots: the parent ids and the child ids
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int parentSlots[] = new int[numHits];
+ int[] parentSlots = new int[numHits];
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int childSlots[] = new int[numHits];
+ int[] childSlots = new int[numHits];
+
+ SortField[] parentFields = parentSort.Sort;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int parentReverseMul[] = new int[parentFields.length];
+ int[] parentReverseMul = new int[parentFields.Length];
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldComparator<?> parentComparators[] = new org.apache.lucene.search.FieldComparator[parentFields.length];
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+ FieldComparator<?>[] parentComparators = new FieldComparator[parentFields.Length];
+ for (int i = 0; i < parentFields.Length; i++)
+ {
+ parentReverseMul[i] = parentFields[i].Reverse ? - 1 : 1;
+ parentComparators[i] = parentFields[i].getComparator(1, i);
+ }
+
+ SortField[] childFields = childSort.Sort;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int childReverseMul[] = new int[childFields.length];
+ int[] childReverseMul = new int[childFields.Length];
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldComparator<?> childComparators[] = new org.apache.lucene.search.FieldComparator[childFields.length];
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+ FieldComparator<?>[] childComparators = new FieldComparator[childFields.Length];
+ for (int i = 0; i < childFields.Length; i++)
+ {
+ childReverseMul[i] = childFields[i].Reverse ? - 1 : 1;
+ childComparators[i] = childFields[i].getComparator(1, i);
+ }
+
+ // NOTE: we could return parent ID as value but really our sort "value" is more complex...
+ // So we throw UOE for now. At the moment you really should only use this at indexing time.
+ return new FieldComparatorAnonymousInnerClassHelper(this, parentSlots, childSlots, parentReverseMul, parentComparators, childReverseMul, childComparators);
+ }
+
+ private class FieldComparatorAnonymousInnerClassHelper : FieldComparator<int?>
+ {
+ private readonly BlockJoinComparatorSource outerInstance;
+
+ private int[] parentSlots;
+ private int[] childSlots;
+ private int[] parentReverseMul;
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: private org.apache.lucene.search.FieldComparator<JavaToDotNetGenericWildcard>[] parentComparators;
+ private FieldComparator<?>[] parentComparators;
+ private int[] childReverseMul;
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: private org.apache.lucene.search.FieldComparator<JavaToDotNetGenericWildcard>[] childComparators;
+ private FieldComparator<?>[] childComparators;
+
+ public FieldComparatorAnonymousInnerClassHelper<T1, T2>(BlockJoinComparatorSource outerInstance, int[] parentSlots, int[] childSlots, int[] parentReverseMul, FieldComparator<T1>[] parentComparators, int[] childReverseMul, FieldComparator<T2>[] childComparators)
+ {
+ this.outerInstance = outerInstance;
+ this.parentSlots = parentSlots;
+ this.childSlots = childSlots;
+ this.parentReverseMul = parentReverseMul;
+ this.parentComparators = parentComparators;
+ this.childReverseMul = childReverseMul;
+ this.childComparators = childComparators;
+ }
+
+ internal int bottomParent;
+ internal int bottomChild;
+ internal FixedBitSet parentBits;
+
+ public override int compare(int slot1, int slot2)
+ {
+ try
+ {
+ return compare(childSlots[slot1], parentSlots[slot1], childSlots[slot2], parentSlots[slot2]);
+ }
+ catch (IOException e)
+ {
+ throw new Exception(e);
+ }
+ }
+
+ public override int Bottom
+ {
+ set
+ {
+ bottomParent = parentSlots[value];
+ bottomChild = childSlots[value];
+ }
+ }
+
+ public override int? TopValue
+ {
+ set
+ {
+ // we dont have enough information (the docid is needed)
+ throw new System.NotSupportedException("this comparator cannot be used with deep paging");
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int compareBottom(int doc) throws java.io.IOException
+ public override int compareBottom(int doc)
+ {
+ return compare(bottomChild, bottomParent, doc, parent(doc));
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int compareTop(int doc) throws java.io.IOException
+ public override int compareTop(int doc)
+ {
+ // we dont have enough information (the docid is needed)
+ throw new System.NotSupportedException("this comparator cannot be used with deep paging");
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void copy(int slot, int doc) throws java.io.IOException
+ public override void copy(int slot, int doc)
+ {
+ childSlots[slot] = doc;
+ parentSlots[slot] = parent(doc);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.FieldComparator<Integer> setNextReader(org.apache.lucene.index.AtomicReaderContext context) throws java.io.IOException
+ public override FieldComparator<int?> setNextReader(AtomicReaderContext context)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.DocIdSet parents = parentsFilter.getDocIdSet(context, null);
+ DocIdSet parents = outerInstance.parentsFilter.getDocIdSet(context, null);
+ if (parents == null)
+ {
+ throw new IllegalStateException("AtomicReader " + context.reader() + " contains no parents!");
+ }
+ if (!(parents is FixedBitSet))
+ {
+ throw new IllegalStateException("parentFilter must return FixedBitSet; got " + parents);
+ }
+ parentBits = (FixedBitSet) parents;
+ for (int i = 0; i < parentComparators.Length; i++)
+ {
+ parentComparators[i] = parentComparators[i].setNextReader(context);
+ }
+ for (int i = 0; i < childComparators.Length; i++)
+ {
+ childComparators[i] = childComparators[i].setNextReader(context);
+ }
+ return this;
+ }
+
+ public override int? value(int slot)
+ {
+ // really our sort "value" is more complex...
+ throw new System.NotSupportedException("filling sort field values is not yet supported");
+ }
+
+ public override Scorer Scorer
+ {
+ set
+ {
+ base.Scorer = value;
+ //JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+ //ORIGINAL LINE: for (org.apache.lucene.search.FieldComparator<?> comp : parentComparators)
+ foreach (FieldComparator<?> comp in parentComparators)
+ {
+ comp.Scorer = value;
+ }
+ //JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+ //ORIGINAL LINE: for (org.apache.lucene.search.FieldComparator<?> comp : childComparators)
+ foreach (FieldComparator<?> comp in childComparators)
+ {
+ comp.Scorer = value;
+ }
+ }
+ }
+
+ internal virtual int parent(int doc)
+ {
+ return parentBits.nextSetBit(doc);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: int compare(int docID1, int parent1, int docID2, int parent2) throws java.io.IOException
+ internal virtual int compare(int docID1, int parent1, int docID2, int parent2)
+ {
+ if (parent1 == parent2) // both are in the same block
+ {
+ if (docID1 == parent1 || docID2 == parent2)
+ {
+ // keep parents at the end of blocks
+ return docID1 - docID2;
+ }
+ else
+ {
+ return compare(docID1, docID2, childComparators, childReverseMul);
+ }
+ }
+ else
+ {
+ int cmp = compare(parent1, parent2, parentComparators, parentReverseMul);
+ if (cmp == 0)
+ {
+ return parent1 - parent2;
+ }
+ else
+ {
+ return cmp;
+ }
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: int compare(int docID1, int docID2, org.apache.lucene.search.FieldComparator<?> comparators[] , int reverseMul[]) throws java.io.IOException
+ internal virtual int compare<T1>(int docID1, int docID2, FieldComparator<T1>[] comparators, int[] reverseMul)
+ {
+ for (int i = 0; i < comparators.Length; i++)
+ {
+ // TODO: would be better if copy() didnt cause a term lookup in TermOrdVal & co,
+ // the segments are always the same here...
+ comparators[i].copy(0, docID1);
+ comparators[i].Bottom = 0;
+ int comp = reverseMul[i] * comparators[i].compareBottom(docID2);
+ if (comp != 0)
+ {
+ return comp;
+ }
+ }
+ return 0; // no need to docid tiebreak
+ }
+ }
+
+ public override string ToString()
+ {
+ return "blockJoin(parentSort=" + parentSort + ",childSort=" + childSort + ")";
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Index/Sorter/EarlyTerminatingSortingCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Index/Sorter/EarlyTerminatingSortingCollector.cs b/src/Lucene.Net.Misc/Index/Sorter/EarlyTerminatingSortingCollector.cs
new file mode 100644
index 0000000..654ba85
--- /dev/null
+++ b/src/Lucene.Net.Misc/Index/Sorter/EarlyTerminatingSortingCollector.cs
@@ -0,0 +1,147 @@
+namespace org.apache.lucene.index.sorter
+{
+
+ /*
+ * 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 CollectionTerminatedException = org.apache.lucene.search.CollectionTerminatedException;
+ using Collector = org.apache.lucene.search.Collector;
+ using Scorer = org.apache.lucene.search.Scorer;
+ using Sort = org.apache.lucene.search.Sort;
+ using TopDocsCollector = org.apache.lucene.search.TopDocsCollector;
+ using TotalHitCountCollector = org.apache.lucene.search.TotalHitCountCollector;
+
+ /// <summary>
+ /// A <seealso cref="Collector"/> that early terminates collection of documents on a
+ /// per-segment basis, if the segment was sorted according to the given
+ /// <seealso cref="Sort"/>.
+ ///
+ /// <para>
+ /// <b>NOTE:</b> the {@code Collector} detects sorted segments according to
+ /// <seealso cref="SortingMergePolicy"/>, so it's best used in conjunction with it. Also,
+ /// it collects up to a specified {@code numDocsToCollect} from each segment,
+ /// and therefore is mostly suitable for use in conjunction with collectors such as
+ /// <seealso cref="TopDocsCollector"/>, and not e.g. <seealso cref="TotalHitCountCollector"/>.
+ /// </para>
+ /// <para>
+ /// <b>NOTE</b>: If you wrap a {@code TopDocsCollector} that sorts in the same
+ /// order as the index order, the returned <seealso cref="TopDocsCollector#topDocs() TopDocs"/>
+ /// will be correct. However the total of {@link TopDocsCollector#getTotalHits()
+ /// hit count} will be underestimated since not all matching documents will have
+ /// been collected.
+ /// </para>
+ /// <para>
+ /// <b>NOTE</b>: This {@code Collector} uses <seealso cref="Sort#toString()"/> to detect
+ /// whether a segment was sorted with the same {@code Sort}. This has
+ /// two implications:
+ /// <ul>
+ /// <li>if a custom comparator is not implemented correctly and returns
+ /// different identifiers for equivalent instances, this collector will not
+ /// detect sorted segments,</li>
+ /// <li>if you suddenly change the <seealso cref="IndexWriter"/>'s
+ /// {@code SortingMergePolicy} to sort according to another criterion and if both
+ /// the old and the new {@code Sort}s have the same identifier, this
+ /// {@code Collector} will incorrectly detect sorted segments.</li>
+ /// </ul>
+ ///
+ /// @lucene.experimental
+ /// </para>
+ /// </summary>
+ public class EarlyTerminatingSortingCollector : Collector
+ {
+ /// <summary>
+ /// The wrapped Collector </summary>
+ protected internal readonly Collector @in;
+ /// <summary>
+ /// Sort used to sort the search results </summary>
+ protected internal readonly Sort sort;
+ /// <summary>
+ /// Number of documents to collect in each segment </summary>
+ protected internal readonly int numDocsToCollect;
+ /// <summary>
+ /// Number of documents to collect in the current segment being processed </summary>
+ protected internal int segmentTotalCollect;
+ /// <summary>
+ /// True if the current segment being processed is sorted by <seealso cref="#sort"/> </summary>
+ protected internal bool segmentSorted;
+
+ private int numCollected;
+
+ /// <summary>
+ /// Create a new <seealso cref="EarlyTerminatingSortingCollector"/> instance.
+ /// </summary>
+ /// <param name="in">
+ /// the collector to wrap </param>
+ /// <param name="sort">
+ /// the sort you are sorting the search results on </param>
+ /// <param name="numDocsToCollect">
+ /// the number of documents to collect on each segment. When wrapping
+ /// a <seealso cref="TopDocsCollector"/>, this number should be the number of
+ /// hits. </param>
+ public EarlyTerminatingSortingCollector(Collector @in, Sort sort, int numDocsToCollect)
+ {
+ if (numDocsToCollect <= 0)
+ {
+ throw new IllegalStateException("numDocsToCollect must always be > 0, got " + segmentTotalCollect);
+ }
+ this.@in = @in;
+ this.sort = sort;
+ this.numDocsToCollect = numDocsToCollect;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void setScorer(org.apache.lucene.search.Scorer scorer) throws java.io.IOException
+ public override Scorer Scorer
+ {
+ set
+ {
+ @in.Scorer = value;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void collect(int doc) throws java.io.IOException
+ public override void collect(int doc)
+ {
+ @in.collect(doc);
+ if (++numCollected >= segmentTotalCollect)
+ {
+ throw new CollectionTerminatedException();
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void setNextReader(org.apache.lucene.index.AtomicReaderContext context) throws java.io.IOException
+ public override AtomicReaderContext NextReader
+ {
+ set
+ {
+ @in.NextReader = value;
+ segmentSorted = SortingMergePolicy.isSorted(value.reader(), sort);
+ segmentTotalCollect = segmentSorted ? numDocsToCollect : int.MaxValue;
+ numCollected = 0;
+ }
+ }
+
+ public override bool acceptsDocsOutOfOrder()
+ {
+ return !segmentSorted && @in.acceptsDocsOutOfOrder();
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/674f0cb9/src/Lucene.Net.Misc/Index/Sorter/Sorter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Misc/Index/Sorter/Sorter.cs b/src/Lucene.Net.Misc/Index/Sorter/Sorter.cs
new file mode 100644
index 0000000..f315b9c
--- /dev/null
+++ b/src/Lucene.Net.Misc/Index/Sorter/Sorter.cs
@@ -0,0 +1,404 @@
+using System;
+using System.Diagnostics;
+
+namespace org.apache.lucene.index.sorter
+{
+
+ /*
+ * 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 FieldComparator = org.apache.lucene.search.FieldComparator;
+ using Scorer = org.apache.lucene.search.Scorer;
+ using Sort = org.apache.lucene.search.Sort;
+ using SortField = org.apache.lucene.search.SortField;
+ using TimSorter = org.apache.lucene.util.TimSorter;
+ using MonotonicAppendingLongBuffer = org.apache.lucene.util.packed.MonotonicAppendingLongBuffer;
+
+ /// <summary>
+ /// Sorts documents of a given index by returning a permutation on the document
+ /// IDs.
+ /// @lucene.experimental
+ /// </summary>
+ internal sealed class Sorter
+ {
+ internal readonly Sort sort_Renamed;
+
+ /// <summary>
+ /// Creates a new Sorter to sort the index with {@code sort} </summary>
+ internal Sorter(Sort sort)
+ {
+ if (sort.needsScores())
+ {
+ throw new System.ArgumentException("Cannot sort an index with a Sort that refers to the relevance score");
+ }
+ this.sort_Renamed = sort;
+ }
+
+ /// <summary>
+ /// A permutation of doc IDs. For every document ID between <tt>0</tt> and
+ /// <seealso cref="IndexReader#maxDoc()"/>, <code>oldToNew(newToOld(docID))</code> must
+ /// return <code>docID</code>.
+ /// </summary>
+ internal abstract class DocMap
+ {
+
+ /// <summary>
+ /// Given a doc ID from the original index, return its ordinal in the
+ /// sorted index.
+ /// </summary>
+ internal abstract int oldToNew(int docID);
+
+ /// <summary>
+ /// Given the ordinal of a doc ID, return its doc ID in the original index. </summary>
+ internal abstract int newToOld(int docID);
+
+ /// <summary>
+ /// Return the number of documents in this map. This must be equal to the
+ /// <seealso cref="AtomicReader#maxDoc() number of documents"/> of the
+ /// <seealso cref="AtomicReader"/> which is sorted.
+ /// </summary>
+ internal abstract int size();
+ }
+
+ /// <summary>
+ /// Check consistency of a <seealso cref="DocMap"/>, useful for assertions. </summary>
+ internal static bool isConsistent(DocMap docMap)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int maxDoc = docMap.size();
+ int maxDoc = docMap.size();
+ for (int i = 0; i < maxDoc; ++i)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int newID = docMap.oldToNew(i);
+ int newID = docMap.oldToNew(i);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int oldID = docMap.newToOld(newID);
+ int oldID = docMap.newToOld(newID);
+ Debug.Assert(newID >= 0 && newID < maxDoc, "doc IDs must be in [0-" + maxDoc + "[, got " + newID);
+ Debug.Assert(i == oldID, "mapping is inconsistent: " + i + " --oldToNew--> " + newID + " --newToOld--> " + oldID);
+ if (i != oldID || newID < 0 || newID >= maxDoc)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// A comparator of doc IDs. </summary>
+ internal abstract class DocComparator
+ {
+
+ /// <summary>
+ /// Compare docID1 against docID2. The contract for the return value is the
+ /// same as <seealso cref="Comparator#compare(Object, Object)"/>.
+ /// </summary>
+ public abstract int compare(int docID1, int docID2);
+
+ }
+
+ private sealed class DocValueSorter : TimSorter
+ {
+
+ internal readonly int[] docs;
+ internal readonly Sorter.DocComparator comparator;
+ internal readonly int[] tmp;
+
+ internal DocValueSorter(int[] docs, Sorter.DocComparator comparator) : base(docs.Length / 64)
+ {
+ this.docs = docs;
+ this.comparator = comparator;
+ tmp = new int[docs.Length / 64];
+ }
+
+ protected internal override int compare(int i, int j)
+ {
+ return comparator.compare(docs[i], docs[j]);
+ }
+
+ protected internal override void swap(int i, int j)
+ {
+ int tmpDoc = docs[i];
+ docs[i] = docs[j];
+ docs[j] = tmpDoc;
+ }
+
+ protected internal override void copy(int src, int dest)
+ {
+ docs[dest] = docs[src];
+ }
+
+ protected internal override void save(int i, int len)
+ {
+ Array.Copy(docs, i, tmp, 0, len);
+ }
+
+ protected internal override void restore(int i, int j)
+ {
+ docs[j] = tmp[i];
+ }
+
+ protected internal override int compareSaved(int i, int j)
+ {
+ return comparator.compare(tmp[i], docs[j]);
+ }
+ }
+
+ /// <summary>
+ /// Computes the old-to-new permutation over the given comparator. </summary>
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: private static Sorter.DocMap sort(final int maxDoc, DocComparator comparator)
+ private static Sorter.DocMap sort(int maxDoc, DocComparator comparator)
+ {
+ // check if the index is sorted
+ bool sorted = true;
+ for (int i = 1; i < maxDoc; ++i)
+ {
+ if (comparator.compare(i - 1, i) > 0)
+ {
+ sorted = false;
+ break;
+ }
+ }
+ if (sorted)
+ {
+ return null;
+ }
+
+ // sort doc IDs
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int[] docs = new int[maxDoc];
+ int[] docs = new int[maxDoc];
+ for (int i = 0; i < maxDoc; i++)
+ {
+ docs[i] = i;
+ }
+
+ DocValueSorter sorter = new DocValueSorter(docs, comparator);
+ // It can be common to sort a reader, add docs, sort it again, ... and in
+ // that case timSort can save a lot of time
+ sorter.sort(0, docs.Length); // docs is now the newToOld mapping
+
+ // The reason why we use MonotonicAppendingLongBuffer here is that it
+ // wastes very little memory if the index is in random order but can save
+ // a lot of memory if the index is already "almost" sorted
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.packed.MonotonicAppendingLongBuffer newToOld = new org.apache.lucene.util.packed.MonotonicAppendingLongBuffer();
+ MonotonicAppendingLongBuffer newToOld = new MonotonicAppendingLongBuffer();
+ for (int i = 0; i < maxDoc; ++i)
+ {
+ newToOld.add(docs[i]);
+ }
+ newToOld.freeze();
+
+ for (int i = 0; i < maxDoc; ++i)
+ {
+ docs[(int) newToOld.get(i)] = i;
+ } // docs is now the oldToNew mapping
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.packed.MonotonicAppendingLongBuffer oldToNew = new org.apache.lucene.util.packed.MonotonicAppendingLongBuffer();
+ MonotonicAppendingLongBuffer oldToNew = new MonotonicAppendingLongBuffer();
+ for (int i = 0; i < maxDoc; ++i)
+ {
+ oldToNew.add(docs[i]);
+ }
+ oldToNew.freeze();
+
+ return new DocMapAnonymousInnerClassHelper(maxDoc, newToOld, oldToNew);
+ }
+
+ private class DocMapAnonymousInnerClassHelper : Sorter.DocMap
+ {
+ private int maxDoc;
+ private MonotonicAppendingLongBuffer newToOld;
+ private MonotonicAppendingLongBuffer oldToNew;
+
+ public DocMapAnonymousInnerClassHelper(int maxDoc, MonotonicAppendingLongBuffer newToOld, MonotonicAppendingLongBuffer oldToNew)
+ {
+ this.maxDoc = maxDoc;
+ this.newToOld = newToOld;
+ this.oldToNew = oldToNew;
+ }
+
+
+ public override int oldToNew(int docID)
+ {
+ return (int) oldToNew.get(docID);
+ }
+
+ public override int newToOld(int docID)
+ {
+ return (int) newToOld.get(docID);
+ }
+
+ public override int size()
+ {
+ return maxDoc;
+ }
+ }
+
+ /// <summary>
+ /// Returns a mapping from the old document ID to its new location in the
+ /// sorted index. Implementations can use the auxiliary
+ /// <seealso cref="#sort(int, DocComparator)"/> to compute the old-to-new permutation
+ /// given a list of documents and their corresponding values.
+ /// <para>
+ /// A return value of <tt>null</tt> is allowed and means that
+ /// <code>reader</code> is already sorted.
+ /// </para>
+ /// <para>
+ /// <b>NOTE:</b> deleted documents are expected to appear in the mapping as
+ /// well, they will however be marked as deleted in the sorted view.
+ /// </para>
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: DocMap sort(org.apache.lucene.index.AtomicReader reader) throws java.io.IOException
+ internal DocMap sort(AtomicReader reader)
+ {
+ SortField[] fields = sort_Renamed.Sort;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int reverseMul[] = new int[fields.length];
+ int[] reverseMul = new int[fields.Length];
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldComparator<?> comparators[] = new org.apache.lucene.search.FieldComparator[fields.length];
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+ FieldComparator<?>[] comparators = new FieldComparator[fields.Length];
+
+ for (int i = 0; i < fields.Length; i++)
+ {
+ reverseMul[i] = fields[i].Reverse ? - 1 : 1;
+ comparators[i] = fields[i].getComparator(1, i);
+ comparators[i].NextReader = reader.Context;
+ comparators[i].Scorer = FAKESCORER;
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final DocComparator comparator = new DocComparator()
+ DocComparator comparator = new DocComparatorAnonymousInnerClassHelper(this, reverseMul, comparators);
+ return sort(reader.maxDoc(), comparator);
+ }
+
+ private class DocComparatorAnonymousInnerClassHelper : DocComparator
+ {
+ private readonly Sorter outerInstance;
+
+ private int[] reverseMul;
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: private org.apache.lucene.search.FieldComparator<JavaToDotNetGenericWildcard>[] comparators;
+ private FieldComparator<?>[] comparators;
+
+ public DocComparatorAnonymousInnerClassHelper<T1>(Sorter outerInstance, int[] reverseMul, FieldComparator<T1>[] comparators)
+ {
+ this.outerInstance = outerInstance;
+ this.reverseMul = reverseMul;
+ this.comparators = comparators;
+ }
+
+ public override int compare(int docID1, int docID2)
+ {
+ try
+ {
+ for (int i = 0; i < comparators.Length; i++)
+ {
+ // TODO: would be better if copy() didnt cause a term lookup in TermOrdVal & co,
+ // the segments are always the same here...
+ comparators[i].copy(0, docID1);
+ comparators[i].Bottom = 0;
+ int comp = reverseMul[i] * comparators[i].compareBottom(docID2);
+ if (comp != 0)
+ {
+ return comp;
+ }
+ }
+ return int.compare(docID1, docID2); // docid order tiebreak
+ }
+ catch (IOException e)
+ {
+ throw new Exception(e);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the identifier of this <seealso cref="Sorter"/>.
+ /// <para>This identifier is similar to <seealso cref="Object#hashCode()"/> and should be
+ /// chosen so that two instances of this class that sort documents likewise
+ /// will have the same identifier. On the contrary, this identifier should be
+ /// different on different <seealso cref="Sort sorts"/>.
+ /// </para>
+ /// </summary>
+ public string ID
+ {
+ get
+ {
+ return sort_Renamed.ToString();
+ }
+ }
+
+ public override string ToString()
+ {
+ return ID;
+ }
+
+ internal static readonly Scorer FAKESCORER = new ScorerAnonymousInnerClassHelper();
+
+ private class ScorerAnonymousInnerClassHelper : Scorer
+ {
+ public ScorerAnonymousInnerClassHelper() : base(null)
+ {
+ }
+
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public float score() throws java.io.IOException
+ public override float score()
+ {
+ throw new System.NotSupportedException();
+ }
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int freq() throws java.io.IOException
+ public override int freq()
+ {
+ throw new System.NotSupportedException();
+ }
+ public override int docID()
+ {
+ throw new System.NotSupportedException();
+ }
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int nextDoc() throws java.io.IOException
+ public override int nextDoc()
+ {
+ throw new System.NotSupportedException();
+ }
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public int advance(int target) throws java.io.IOException
+ public override int advance(int target)
+ {
+ throw new System.NotSupportedException();
+ }
+ public override long cost()
+ {
+ throw new System.NotSupportedException();
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
[04/11] Skeleton porting of Lucene.Net.Queries
Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/MultiBoolFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/MultiBoolFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/MultiBoolFunction.cs
new file mode 100644
index 0000000..56810a3
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/MultiBoolFunction.cs
@@ -0,0 +1,148 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using BoolDocValues = org.apache.lucene.queries.function.docvalues.BoolDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+ /// <summary>
+ /// Abstract <seealso cref="ValueSource"/> implementation which wraps multiple ValueSources
+ /// and applies an extendible boolean function to their values.
+ ///
+ /// </summary>
+ public abstract class MultiBoolFunction : BoolFunction
+ {
+ protected internal readonly IList<ValueSource> sources;
+
+ public MultiBoolFunction(IList<ValueSource> sources)
+ {
+ this.sources = sources;
+ }
+
+ protected internal abstract string name();
+
+ protected internal abstract bool func(int doc, FunctionValues[] vals);
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.docvalues.BoolDocValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override BoolDocValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues[] vals = new org.apache.lucene.queries.function.FunctionValues[sources.size()];
+ FunctionValues[] vals = new FunctionValues[sources.Count];
+ int i = 0;
+ foreach (ValueSource source in sources)
+ {
+ vals[i++] = source.getValues(context, readerContext);
+ }
+
+ return new BoolDocValuesAnonymousInnerClassHelper(this, this, vals);
+ }
+
+ private class BoolDocValuesAnonymousInnerClassHelper : BoolDocValues
+ {
+ private readonly MultiBoolFunction outerInstance;
+
+ private FunctionValues[] vals;
+
+ public BoolDocValuesAnonymousInnerClassHelper(MultiBoolFunction outerInstance, org.apache.lucene.queries.function.valuesource.MultiBoolFunction this, FunctionValues[] vals) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.vals = vals;
+ }
+
+ public override bool boolVal(int doc)
+ {
+ return outerInstance.func(doc, vals);
+ }
+
+ public override string ToString(int doc)
+ {
+ StringBuilder sb = new StringBuilder(outerInstance.name());
+ sb.Append('(');
+ bool first = true;
+ foreach (FunctionValues dv in vals)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ sb.Append(',');
+ }
+ sb.Append(dv.ToString(doc));
+ }
+ return sb.ToString();
+ }
+ }
+
+ public override string description()
+ {
+ StringBuilder sb = new StringBuilder(name());
+ sb.Append('(');
+ bool first = true;
+ foreach (ValueSource source in sources)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ sb.Append(',');
+ }
+ sb.Append(source.description());
+ }
+ return sb.ToString();
+ }
+
+ public override int GetHashCode()
+ {
+ return sources.GetHashCode() + name().GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ MultiBoolFunction other = (MultiBoolFunction)o;
+ return this.sources.Equals(other.sources);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ foreach (ValueSource source in sources)
+ {
+ source.createWeight(context, searcher);
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/MultiFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/MultiFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/MultiFloatFunction.cs
new file mode 100644
index 0000000..90b56ff
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/MultiFloatFunction.cs
@@ -0,0 +1,146 @@
+using System.Collections;
+using System.Text;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+
+ /// <summary>
+ /// Abstract <seealso cref="ValueSource"/> implementation which wraps multiple ValueSources
+ /// and applies an extendible float function to their values.
+ ///
+ /// </summary>
+ public abstract class MultiFloatFunction : ValueSource
+ {
+ protected internal readonly ValueSource[] sources;
+
+ public MultiFloatFunction(ValueSource[] sources)
+ {
+ this.sources = sources;
+ }
+
+ protected internal abstract string name();
+ protected internal abstract float func(int doc, FunctionValues[] valsArr);
+
+ public override string description()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(name()).Append('(');
+ bool firstTime = true;
+ foreach (ValueSource source in sources)
+ {
+ if (firstTime)
+ {
+ firstTime = false;
+ }
+ else
+ {
+ sb.Append(',');
+ }
+ sb.Append(source);
+ }
+ sb.Append(')');
+ return sb.ToString();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues[] valsArr = new org.apache.lucene.queries.function.FunctionValues[sources.length];
+ FunctionValues[] valsArr = new FunctionValues[sources.Length];
+ for (int i = 0; i < sources.Length; i++)
+ {
+ valsArr[i] = sources[i].getValues(context, readerContext);
+ }
+
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, valsArr);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly MultiFloatFunction outerInstance;
+
+ private FunctionValues[] valsArr;
+
+ public FloatDocValuesAnonymousInnerClassHelper(MultiFloatFunction outerInstance, org.apache.lucene.queries.function.valuesource.MultiFloatFunction this, FunctionValues[] valsArr) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.valsArr = valsArr;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return outerInstance.func(doc, valsArr);
+ }
+ public override string ToString(int doc)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(outerInstance.name()).Append('(');
+ bool firstTime = true;
+ foreach (FunctionValues vals in valsArr)
+ {
+ if (firstTime)
+ {
+ firstTime = false;
+ }
+ else
+ {
+ sb.Append(',');
+ }
+ sb.Append(vals.ToString(doc));
+ }
+ sb.Append(')');
+ return sb.ToString();
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ foreach (ValueSource source in sources)
+ {
+ source.createWeight(context, searcher);
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return Arrays.GetHashCode(sources) + name().GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ MultiFloatFunction other = (MultiFloatFunction)o;
+ return this.name().Equals(other.name()) && Arrays.Equals(this.sources, other.sources);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/MultiFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/MultiFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/MultiFunction.cs
new file mode 100644
index 0000000..089d21c
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/MultiFunction.cs
@@ -0,0 +1,161 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+ /// <summary>
+ /// Abstract parent class for <seealso cref="ValueSource"/> implementations that wrap multiple
+ /// ValueSources and apply their own logic.
+ /// </summary>
+ public abstract class MultiFunction : ValueSource
+ {
+ protected internal readonly IList<ValueSource> sources;
+
+ public MultiFunction(IList<ValueSource> sources)
+ {
+ this.sources = sources;
+ }
+
+ protected internal abstract string name();
+
+ public override string description()
+ {
+ return description(name(), sources);
+ }
+
+ public static string description(string name, IList<ValueSource> sources)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(name).Append('(');
+ bool firstTime = true;
+ foreach (ValueSource source in sources)
+ {
+ if (firstTime)
+ {
+ firstTime = false;
+ }
+ else
+ {
+ sb.Append(',');
+ }
+ sb.Append(source);
+ }
+ sb.Append(')');
+ return sb.ToString();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public static org.apache.lucene.queries.function.FunctionValues[] valsArr(java.util.List<org.apache.lucene.queries.function.ValueSource> sources, java.util.Map fcontext, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public static FunctionValues[] valsArr(IList<ValueSource> sources, IDictionary fcontext, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues[] valsArr = new org.apache.lucene.queries.function.FunctionValues[sources.size()];
+ FunctionValues[] valsArr = new FunctionValues[sources.Count];
+ int i = 0;
+ foreach (ValueSource source in sources)
+ {
+ valsArr[i++] = source.getValues(fcontext, readerContext);
+ }
+ return valsArr;
+ }
+
+ public class Values : FunctionValues
+ {
+ private readonly MultiFunction outerInstance;
+
+ internal readonly FunctionValues[] valsArr;
+
+ public Values(MultiFunction outerInstance, FunctionValues[] valsArr)
+ {
+ this.outerInstance = outerInstance;
+ this.valsArr = valsArr;
+ }
+
+ public override string ToString(int doc)
+ {
+ return MultiFunction.ToString(outerInstance.name(), valsArr, doc);
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ // TODO: need ValueSource.type() to determine correct type
+ return base.ValueFiller;
+ }
+ }
+ }
+
+
+ public static string ToString(string name, FunctionValues[] valsArr, int doc)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(name).Append('(');
+ bool firstTime = true;
+ foreach (FunctionValues vals in valsArr)
+ {
+ if (firstTime)
+ {
+ firstTime = false;
+ }
+ else
+ {
+ sb.Append(',');
+ }
+ sb.Append(vals.ToString(doc));
+ }
+ sb.Append(')');
+ return sb.ToString();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ foreach (ValueSource source in sources)
+ {
+ source.createWeight(context, searcher);
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return sources.GetHashCode() + name().GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ MultiFunction other = (MultiFunction)o;
+ return this.sources.Equals(other.sources);
+ }
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/MultiValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/MultiValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/MultiValueSource.cs
new file mode 100644
index 0000000..908eae9
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/MultiValueSource.cs
@@ -0,0 +1,32 @@
+namespace org.apache.lucene.queries.function.valuesource
+{
+ /*
+ * 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.
+ */
+
+
+ /// <summary>
+ /// A <seealso cref="ValueSource"/> that abstractly represents <seealso cref="ValueSource"/>s for
+ /// poly fields, and other things.
+ ///
+ /// </summary>
+ public abstract class MultiValueSource : ValueSource
+ {
+
+ public abstract int dimension();
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/NormValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/NormValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/NormValueSource.cs
new file mode 100644
index 0000000..d0de6c1
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/NormValueSource.cs
@@ -0,0 +1,125 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using NumericDocValues = org.apache.lucene.index.NumericDocValues;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using TFIDFSimilarity = org.apache.lucene.search.similarities.TFIDFSimilarity;
+
+
+ /// <summary>
+ /// Function that returns <seealso cref="TFIDFSimilarity#decodeNormValue(long)"/>
+ /// for every document.
+ /// <para>
+ /// Note that the configured Similarity for the field must be
+ /// a subclass of <seealso cref="TFIDFSimilarity"/>
+ /// @lucene.internal
+ /// </para>
+ /// </summary>
+ public class NormValueSource : ValueSource
+ {
+ protected internal readonly string field;
+ public NormValueSource(string field)
+ {
+ this.field = field;
+ }
+
+ public virtual string name()
+ {
+ return "norm";
+ }
+
+ public override string description()
+ {
+ return name() + '(' + field + ')';
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ context["searcher"] = searcher;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ IndexSearcher searcher = (IndexSearcher)context["searcher"];
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.similarities.TFIDFSimilarity similarity = IDFValueSource.asTFIDF(searcher.getSimilarity(), field);
+ TFIDFSimilarity similarity = IDFValueSource.asTFIDF(searcher.Similarity, field);
+ if (similarity == null)
+ {
+ throw new System.NotSupportedException("requires a TFIDFSimilarity (such as DefaultSimilarity)");
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.NumericDocValues norms = readerContext.reader().getNormValues(field);
+ NumericDocValues norms = readerContext.reader().getNormValues(field);
+
+ if (norms == null)
+ {
+ return new ConstDoubleDocValues(0.0, this);
+ }
+
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, similarity, norms);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly NormValueSource outerInstance;
+
+ private TFIDFSimilarity similarity;
+ private NumericDocValues norms;
+
+ public FloatDocValuesAnonymousInnerClassHelper(NormValueSource outerInstance, org.apache.lucene.queries.function.valuesource.NormValueSource this, TFIDFSimilarity similarity, NumericDocValues norms) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.similarity = similarity;
+ this.norms = norms;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return similarity.decodeNormValue(norms.get(doc));
+ }
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ return this.field.Equals(((NormValueSource)o).field);
+ }
+
+ public override int GetHashCode()
+ {
+ return this.GetType().GetHashCode() + field.GetHashCode();
+ }
+ }
+
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/NumDocsValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/NumDocsValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/NumDocsValueSource.cs
new file mode 100644
index 0000000..b5e6669
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/NumDocsValueSource.cs
@@ -0,0 +1,63 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using ReaderUtil = org.apache.lucene.index.ReaderUtil;
+
+
+ /// <summary>
+ /// Returns the value of <seealso cref="IndexReader#numDocs()"/>
+ /// for every document. This is the number of documents
+ /// excluding deletions.
+ /// </summary>
+ public class NumDocsValueSource : ValueSource
+ {
+ public virtual string name()
+ {
+ return "numdocs";
+ }
+
+ public override string description()
+ {
+ return name() + "()";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ // Searcher has no numdocs so we must use the reader instead
+ return new ConstIntDocValues(ReaderUtil.getTopLevelContext(readerContext).reader().numDocs(), this);
+ }
+
+ public override bool Equals(object o)
+ {
+ return this.GetType() == o.GetType();
+ }
+
+ public override int GetHashCode()
+ {
+ return this.GetType().GetHashCode();
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/OrdFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/OrdFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/OrdFieldSource.cs
new file mode 100644
index 0000000..123327f
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/OrdFieldSource.cs
@@ -0,0 +1,175 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ using AtomicReader = org.apache.lucene.index.AtomicReader;
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using CompositeReader = org.apache.lucene.index.CompositeReader;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using ReaderUtil = org.apache.lucene.index.ReaderUtil;
+ using SlowCompositeReaderWrapper = org.apache.lucene.index.SlowCompositeReaderWrapper;
+ using SortedDocValues = org.apache.lucene.index.SortedDocValues;
+ using IntDocValues = org.apache.lucene.queries.function.docvalues.IntDocValues;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueInt = org.apache.lucene.util.mutable.MutableValueInt;
+
+ /// <summary>
+ /// Obtains the ordinal of the field value from the default Lucene <seealso cref="org.apache.lucene.search.FieldCache"/> using getStringIndex().
+ /// <br>
+ /// The native lucene index order is used to assign an ordinal value for each field value.
+ /// <br>Field values (terms) are lexicographically ordered by unicode value, and numbered starting at 1.
+ /// <br>
+ /// Example:<br>
+ /// If there were only three field values: "apple","banana","pear"
+ /// <br>then ord("apple")=1, ord("banana")=2, ord("pear")=3
+ /// <para>
+ /// WARNING: ord() depends on the position in an index and can thus change when other documents are inserted or deleted,
+ /// or if a MultiSearcher is used.
+ /// <br>WARNING: as of Solr 1.4, ord() and rord() can cause excess memory use since they must use a FieldCache entry
+ /// at the top level reader, while sorting and function queries now use entries at the segment level. Hence sorting
+ /// or using a different function query, in addition to ord()/rord() will double memory use.
+ ///
+ /// </para>
+ /// </summary>
+
+ public class OrdFieldSource : ValueSource
+ {
+ protected internal readonly string field;
+
+ public OrdFieldSource(string field)
+ {
+ this.field = field;
+ }
+
+ public override string description()
+ {
+ return "ord(" + field + ')';
+ }
+
+
+ // TODO: this is trappy? perhaps this query instead should make you pass a slow reader yourself?
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int off = readerContext.docBase;
+ int off = readerContext.docBase;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.IndexReader topReader = org.apache.lucene.index.ReaderUtil.getTopLevelContext(readerContext).reader();
+ IndexReader topReader = ReaderUtil.getTopLevelContext(readerContext).reader();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.AtomicReader r = org.apache.lucene.index.SlowCompositeReaderWrapper.wrap(topReader);
+ AtomicReader r = SlowCompositeReaderWrapper.wrap(topReader);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.SortedDocValues sindex = org.apache.lucene.search.FieldCache.DEFAULT.getTermsIndex(r, field);
+ SortedDocValues sindex = FieldCache.DEFAULT.getTermsIndex(r, field);
+ return new IntDocValuesAnonymousInnerClassHelper(this, this, off, sindex);
+ }
+
+ private class IntDocValuesAnonymousInnerClassHelper : IntDocValues
+ {
+ private readonly OrdFieldSource outerInstance;
+
+ private int off;
+ private SortedDocValues sindex;
+
+ public IntDocValuesAnonymousInnerClassHelper(OrdFieldSource outerInstance, org.apache.lucene.queries.function.valuesource.OrdFieldSource this, int off, SortedDocValues sindex) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.off = off;
+ this.sindex = sindex;
+ }
+
+ protected internal virtual string toTerm(string readableValue)
+ {
+ return readableValue;
+ }
+ public override int intVal(int doc)
+ {
+ return sindex.getOrd(doc + off);
+ }
+ public override int ordVal(int doc)
+ {
+ return sindex.getOrd(doc + off);
+ }
+ public override int numOrd()
+ {
+ return sindex.ValueCount;
+ }
+
+ public override bool exists(int doc)
+ {
+ return sindex.getOrd(doc + off) != 0;
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly IntDocValuesAnonymousInnerClassHelper outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(IntDocValuesAnonymousInnerClassHelper outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueInt();
+ }
+
+ private readonly MutableValueInt mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.sindex.getOrd(doc);
+ mval.exists = mval.value != 0;
+ }
+ }
+ }
+
+ public override bool Equals(object o)
+ {
+ return o != null && o.GetType() == typeof(OrdFieldSource) && this.field.Equals(((OrdFieldSource)o).field);
+ }
+
+ private static readonly int hcode = typeof(OrdFieldSource).GetHashCode();
+ public override int GetHashCode()
+ {
+ return hcode + field.GetHashCode();
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/PowFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/PowFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/PowFloatFunction.cs
new file mode 100644
index 0000000..99b4c42
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/PowFloatFunction.cs
@@ -0,0 +1,48 @@
+using System;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ /// <summary>
+ /// Function to raise the base "a" to the power "b"
+ /// </summary>
+ public class PowFloatFunction : DualFloatFunction
+ {
+ /// <param name="a"> the base. </param>
+ /// <param name="b"> the exponent. </param>
+ public PowFloatFunction(ValueSource a, ValueSource b) : base(a,b)
+ {
+ }
+
+ protected internal override string name()
+ {
+ return "pow";
+ }
+
+ protected internal override float func(int doc, FunctionValues aVals, FunctionValues bVals)
+ {
+ return (float)Math.Pow(aVals.floatVal(doc), bVals.floatVal(doc));
+ }
+ }
+
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/ProductFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/ProductFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/ProductFloatFunction.cs
new file mode 100644
index 0000000..92cc4d7
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/ProductFloatFunction.cs
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ /// <summary>
+ /// <code>ProductFloatFunction</code> returns the product of it's components.
+ /// </summary>
+ public class ProductFloatFunction : MultiFloatFunction
+ {
+ public ProductFloatFunction(ValueSource[] sources) : base(sources)
+ {
+ }
+
+ protected internal override string name()
+ {
+ return "product";
+ }
+
+ protected internal override float func(int doc, FunctionValues[] valsArr)
+ {
+ float val = 1.0f;
+ foreach (FunctionValues vals in valsArr)
+ {
+ val *= vals.floatVal(doc);
+ }
+ return val;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/QueryValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/QueryValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/QueryValueSource.cs
new file mode 100644
index 0000000..9abc198
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/QueryValueSource.cs
@@ -0,0 +1,328 @@
+using System;
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using ReaderUtil = org.apache.lucene.index.ReaderUtil;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using org.apache.lucene.search;
+ using Bits = org.apache.lucene.util.Bits;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueFloat = org.apache.lucene.util.mutable.MutableValueFloat;
+
+
+ /// <summary>
+ /// <code>QueryValueSource</code> returns the relevance score of the query
+ /// </summary>
+ public class QueryValueSource : ValueSource
+ {
+ internal readonly Query q;
+ internal readonly float defVal;
+
+ public QueryValueSource(Query q, float defVal)
+ {
+ this.q = q;
+ this.defVal = defVal;
+ }
+
+ public virtual Query Query
+ {
+ get
+ {
+ return q;
+ }
+ }
+ public virtual float DefaultValue
+ {
+ get
+ {
+ return defVal;
+ }
+ }
+
+ public override string description()
+ {
+ return "query(" + q + ",def=" + defVal + ")";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map fcontext, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary fcontext, AtomicReaderContext readerContext)
+ {
+ return new QueryDocValues(this, readerContext, fcontext);
+ }
+
+ public override int GetHashCode()
+ {
+ return q.GetHashCode() * 29;
+ }
+
+ public override bool Equals(object o)
+ {
+ if (typeof(QueryValueSource) != o.GetType())
+ {
+ return false;
+ }
+ QueryValueSource other = (QueryValueSource)o;
+ return this.q.Equals(other.q) && this.defVal == other.defVal;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ Weight w = searcher.createNormalizedWeight(q);
+ context[this] = w;
+ }
+ }
+
+
+ internal class QueryDocValues : FloatDocValues
+ {
+ internal readonly AtomicReaderContext readerContext;
+ internal readonly Bits acceptDocs;
+ internal readonly Weight weight;
+ internal readonly float defVal;
+ internal readonly IDictionary fcontext;
+ internal readonly Query q;
+
+ internal Scorer scorer;
+ internal int scorerDoc; // the document the scorer is on
+ internal bool noMatches = false;
+
+ // the last document requested... start off with high value
+ // to trigger a scorer reset on first access.
+ internal int lastDocRequested = int.MaxValue;
+
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: public QueryDocValues(QueryValueSource vs, org.apache.lucene.index.AtomicReaderContext readerContext, java.util.Map fcontext) throws java.io.IOException
+ public QueryDocValues(QueryValueSource vs, AtomicReaderContext readerContext, IDictionary fcontext) : base(vs)
+ {
+
+ this.readerContext = readerContext;
+ this.acceptDocs = readerContext.reader().LiveDocs;
+ this.defVal = vs.defVal;
+ this.q = vs.q;
+ this.fcontext = fcontext;
+
+ Weight w = fcontext == null ? null : (Weight)fcontext[vs];
+ if (w == null)
+ {
+ IndexSearcher weightSearcher;
+ if (fcontext == null)
+ {
+ weightSearcher = new IndexSearcher(ReaderUtil.getTopLevelContext(readerContext));
+ }
+ else
+ {
+ weightSearcher = (IndexSearcher)fcontext["searcher"];
+ if (weightSearcher == null)
+ {
+ weightSearcher = new IndexSearcher(ReaderUtil.getTopLevelContext(readerContext));
+ }
+ }
+ vs.createWeight(fcontext, weightSearcher);
+ w = (Weight)fcontext[vs];
+ }
+ weight = w;
+ }
+
+ public override float floatVal(int doc)
+ {
+ try
+ {
+ if (doc < lastDocRequested)
+ {
+ if (noMatches)
+ {
+ return defVal;
+ }
+ scorer = weight.scorer(readerContext, acceptDocs);
+ if (scorer == null)
+ {
+ noMatches = true;
+ return defVal;
+ }
+ scorerDoc = -1;
+ }
+ lastDocRequested = doc;
+
+ if (scorerDoc < doc)
+ {
+ scorerDoc = scorer.advance(doc);
+ }
+
+ if (scorerDoc > doc)
+ {
+ // query doesn't match this document... either because we hit the
+ // end, or because the next doc is after this doc.
+ return defVal;
+ }
+
+ // a match!
+ return scorer.score();
+ }
+ catch (IOException e)
+ {
+ throw new Exception("caught exception in QueryDocVals(" + q + ") doc=" + doc, e);
+ }
+ }
+
+ public override bool exists(int doc)
+ {
+ try
+ {
+ if (doc < lastDocRequested)
+ {
+ if (noMatches)
+ {
+ return false;
+ }
+ scorer = weight.scorer(readerContext, acceptDocs);
+ scorerDoc = -1;
+ if (scorer == null)
+ {
+ noMatches = true;
+ return false;
+ }
+ }
+ lastDocRequested = doc;
+
+ if (scorerDoc < doc)
+ {
+ scorerDoc = scorer.advance(doc);
+ }
+
+ if (scorerDoc > doc)
+ {
+ // query doesn't match this document... either because we hit the
+ // end, or because the next doc is after this doc.
+ return false;
+ }
+
+ // a match!
+ return true;
+ }
+ catch (IOException e)
+ {
+ throw new Exception("caught exception in QueryDocVals(" + q + ") doc=" + doc, e);
+ }
+ }
+
+ public override object objectVal(int doc)
+ {
+ try
+ {
+ return exists(doc) ? scorer.score() : null;
+ }
+ catch (IOException e)
+ {
+ throw new Exception("caught exception in QueryDocVals(" + q + ") doc=" + doc, e);
+ }
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ //
+ // TODO: if we want to support more than one value-filler or a value-filler in conjunction with
+ // the FunctionValues, then members like "scorer" should be per ValueFiller instance.
+ // Or we can say that the user should just instantiate multiple FunctionValues.
+ //
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly QueryDocValues outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(QueryDocValues outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueFloat();
+ }
+
+ private readonly MutableValueFloat mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ try
+ {
+ if (outerInstance.noMatches)
+ {
+ mval.value = outerInstance.defVal;
+ mval.exists = false;
+ return;
+ }
+ outerInstance.scorer = outerInstance.weight.scorer(outerInstance.readerContext, outerInstance.acceptDocs);
+ outerInstance.scorerDoc = -1;
+ if (outerInstance.scorer == null)
+ {
+ outerInstance.noMatches = true;
+ mval.value = outerInstance.defVal;
+ mval.exists = false;
+ return;
+ }
+ outerInstance.lastDocRequested = doc;
+
+ if (outerInstance.scorerDoc < doc)
+ {
+ outerInstance.scorerDoc = outerInstance.scorer.advance(doc);
+ }
+
+ if (outerInstance.scorerDoc > doc)
+ {
+ // query doesn't match this document... either because we hit the
+ // end, or because the next doc is after this doc.
+ mval.value = outerInstance.defVal;
+ mval.exists = false;
+ return;
+ }
+
+ // a match!
+ mval.value = outerInstance.scorer.score();
+ mval.exists = true;
+ }
+ catch (IOException e)
+ {
+ throw new Exception("caught exception in QueryDocVals(" + outerInstance.q + ") doc=" + doc, e);
+ }
+ }
+ }
+
+ public override string ToString(int doc)
+ {
+ return "query(" + q + ",def=" + defVal + ")=" + floatVal(doc);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/RangeMapFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/RangeMapFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/RangeMapFloatFunction.cs
new file mode 100644
index 0000000..d6cf6df
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/RangeMapFloatFunction.cs
@@ -0,0 +1,138 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+ /// <summary>
+ /// <code>RangeMapFloatFunction</code> implements a map function over
+ /// another <seealso cref="ValueSource"/> whose values fall within min and max inclusive to target.
+ /// <br>
+ /// Normally Used as an argument to a <seealso cref="org.apache.lucene.queries.function.FunctionQuery"/>
+ ///
+ ///
+ /// </summary>
+ public class RangeMapFloatFunction : ValueSource
+ {
+ protected internal readonly ValueSource source;
+ protected internal readonly float min;
+ protected internal readonly float max;
+ protected internal readonly ValueSource target;
+ protected internal readonly ValueSource defaultVal;
+
+ public RangeMapFloatFunction(ValueSource source, float min, float max, float target, float? def) : this(source, min, max, new ConstValueSource(target), def == null ? null : new ConstValueSource(def.Value))
+ {
+ }
+
+ public RangeMapFloatFunction(ValueSource source, float min, float max, ValueSource target, ValueSource def)
+ {
+ this.source = source;
+ this.min = min;
+ this.max = max;
+ this.target = target;
+ this.defaultVal = def;
+ }
+
+ public override string description()
+ {
+ return "map(" + source.description() + "," + min + "," + max + "," + target.description() + ")";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues vals = source.getValues(context, readerContext);
+ FunctionValues vals = source.getValues(context, readerContext);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues targets = target.getValues(context, readerContext);
+ FunctionValues targets = target.getValues(context, readerContext);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues defaults = (this.defaultVal == null) ? null : defaultVal.getValues(context, readerContext);
+ FunctionValues defaults = (this.defaultVal == null) ? null : defaultVal.getValues(context, readerContext);
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, vals, targets, defaults);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly RangeMapFloatFunction outerInstance;
+
+ private FunctionValues vals;
+ private FunctionValues targets;
+ private FunctionValues defaults;
+
+ public FloatDocValuesAnonymousInnerClassHelper(RangeMapFloatFunction outerInstance, org.apache.lucene.queries.function.valuesource.RangeMapFloatFunction this, FunctionValues vals, FunctionValues targets, FunctionValues defaults) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.vals = vals;
+ this.targets = targets;
+ this.defaults = defaults;
+ }
+
+ public override float floatVal(int doc)
+ {
+ float val = vals.floatVal(doc);
+ return (val >= outerInstance.min && val <= outerInstance.max) ? targets.floatVal(doc) : (outerInstance.defaultVal == null ? val : defaults.floatVal(doc));
+ }
+ public override string ToString(int doc)
+ {
+ return "map(" + vals.ToString(doc) + ",min=" + outerInstance.min + ",max=" + outerInstance.max + ",target=" + targets.ToString(doc) + ")";
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ source.createWeight(context, searcher);
+ }
+
+ public override int GetHashCode()
+ {
+ int h = source.GetHashCode();
+ h ^= (h << 10) | ((int)((uint)h >> 23));
+ h += float.floatToIntBits(min);
+ h ^= (h << 14) | ((int)((uint)h >> 19));
+ h += float.floatToIntBits(max);
+ h += target.GetHashCode();
+ if (defaultVal != null)
+ {
+ h += defaultVal.GetHashCode();
+ }
+ return h;
+ }
+
+ public override bool Equals(object o)
+ {
+ if (typeof(RangeMapFloatFunction) != o.GetType())
+ {
+ return false;
+ }
+ RangeMapFloatFunction other = (RangeMapFloatFunction)o;
+ return this.min == other.min && this.max == other.max && this.target.Equals(other.target) && this.source.Equals(other.source) && (this.defaultVal == other.defaultVal || (this.defaultVal != null && this.defaultVal.Equals(other.defaultVal)));
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/ReciprocalFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/ReciprocalFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/ReciprocalFloatFunction.cs
new file mode 100644
index 0000000..9fcf24c
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/ReciprocalFloatFunction.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+ /// <summary>
+ /// <code>ReciprocalFloatFunction</code> implements a reciprocal function f(x) = a/(mx+b), based on
+ /// the float value of a field or function as exported by <seealso cref="org.apache.lucene.queries.function.ValueSource"/>.
+ /// <br>
+ ///
+ /// When a and b are equal, and x>=0, this function has a maximum value of 1 that drops as x increases.
+ /// Increasing the value of a and b together results in a movement of the entire function to a flatter part of the curve.
+ /// <para>These properties make this an idea function for boosting more recent documents.
+ /// </para>
+ /// <para>Example:<code> recip(ms(NOW,mydatefield),3.16e-11,1,1)</code>
+ /// </para>
+ /// <para>A multiplier of 3.16e-11 changes the units from milliseconds to years (since there are about 3.16e10 milliseconds
+ /// per year). Thus, a very recent date will yield a value close to 1/(0+1) or 1,
+ /// a date a year in the past will get a multiplier of about 1/(1+1) or 1/2,
+ /// and date two years old will yield 1/(2+1) or 1/3.
+ ///
+ /// </para>
+ /// </summary>
+ /// <seealso cref= org.apache.lucene.queries.function.FunctionQuery
+ ///
+ /// </seealso>
+ public class ReciprocalFloatFunction : ValueSource
+ {
+ protected internal readonly ValueSource source;
+ protected internal readonly float m;
+ protected internal readonly float a;
+ protected internal readonly float b;
+
+ /// <summary>
+ /// f(source) = a/(m*float(source)+b)
+ /// </summary>
+ public ReciprocalFloatFunction(ValueSource source, float m, float a, float b)
+ {
+ this.source = source;
+ this.m = m;
+ this.a = a;
+ this.b = b;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues vals = source.getValues(context, readerContext);
+ FunctionValues vals = source.getValues(context, readerContext);
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, vals);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly ReciprocalFloatFunction outerInstance;
+
+ private FunctionValues vals;
+
+ public FloatDocValuesAnonymousInnerClassHelper(ReciprocalFloatFunction outerInstance, org.apache.lucene.queries.function.valuesource.ReciprocalFloatFunction this, FunctionValues vals) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.vals = vals;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return outerInstance.a / (outerInstance.m * vals.floatVal(doc) + outerInstance.b);
+ }
+ public override string ToString(int doc)
+ {
+ return Convert.ToString(outerInstance.a) + "/(" + outerInstance.m + "*float(" + vals.ToString(doc) + ')' + '+' + outerInstance.b + ')';
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ source.createWeight(context, searcher);
+ }
+
+ public override string description()
+ {
+ return Convert.ToString(a) + "/(" + m + "*float(" + source.description() + ")" + "+" + b + ')';
+ }
+
+ public override int GetHashCode()
+ {
+ int h = float.floatToIntBits(a) + float.floatToIntBits(m);
+ h ^= (h << 13) | ((int)((uint)h >> 20));
+ return h + (float.floatToIntBits(b)) + source.GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (typeof(ReciprocalFloatFunction) != o.GetType())
+ {
+ return false;
+ }
+ ReciprocalFloatFunction other = (ReciprocalFloatFunction)o;
+ return this.m == other.m && this.a == other.a && this.b == other.b && this.source.Equals(other.source);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/ReverseOrdFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/ReverseOrdFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/ReverseOrdFieldSource.cs
new file mode 100644
index 0000000..b509dde
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/ReverseOrdFieldSource.cs
@@ -0,0 +1,135 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ using AtomicReader = org.apache.lucene.index.AtomicReader;
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using CompositeReader = org.apache.lucene.index.CompositeReader;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using ReaderUtil = org.apache.lucene.index.ReaderUtil;
+ using SlowCompositeReaderWrapper = org.apache.lucene.index.SlowCompositeReaderWrapper;
+ using SortedDocValues = org.apache.lucene.index.SortedDocValues;
+ using IntDocValues = org.apache.lucene.queries.function.docvalues.IntDocValues;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+
+ /// <summary>
+ /// Obtains the ordinal of the field value from the default Lucene <seealso cref="org.apache.lucene.search.FieldCache"/> using getTermsIndex()
+ /// and reverses the order.
+ /// <br>
+ /// The native lucene index order is used to assign an ordinal value for each field value.
+ /// <br>Field values (terms) are lexicographically ordered by unicode value, and numbered starting at 1.
+ /// <br>
+ /// Example of reverse ordinal (rord):<br>
+ /// If there were only three field values: "apple","banana","pear"
+ /// <br>then rord("apple")=3, rord("banana")=2, ord("pear")=1
+ /// <para>
+ /// WARNING: ord() depends on the position in an index and can thus change when other documents are inserted or deleted,
+ /// or if a MultiSearcher is used.
+ /// <br>
+ /// WARNING: as of Solr 1.4, ord() and rord() can cause excess memory use since they must use a FieldCache entry
+ /// at the top level reader, while sorting and function queries now use entries at the segment level. Hence sorting
+ /// or using a different function query, in addition to ord()/rord() will double memory use.
+ ///
+ ///
+ /// </para>
+ /// </summary>
+
+ public class ReverseOrdFieldSource : ValueSource
+ {
+ public readonly string field;
+
+ public ReverseOrdFieldSource(string field)
+ {
+ this.field = field;
+ }
+
+ public override string description()
+ {
+ return "rord(" + field + ')';
+ }
+
+ // TODO: this is trappy? perhaps this query instead should make you pass a slow reader yourself?
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.IndexReader topReader = org.apache.lucene.index.ReaderUtil.getTopLevelContext(readerContext).reader();
+ IndexReader topReader = ReaderUtil.getTopLevelContext(readerContext).reader();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.AtomicReader r = org.apache.lucene.index.SlowCompositeReaderWrapper.wrap(topReader);
+ AtomicReader r = SlowCompositeReaderWrapper.wrap(topReader);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int off = readerContext.docBase;
+ int off = readerContext.docBase;
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.SortedDocValues sindex = org.apache.lucene.search.FieldCache.DEFAULT.getTermsIndex(r, field);
+ SortedDocValues sindex = FieldCache.DEFAULT.getTermsIndex(r, field);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int end = sindex.getValueCount();
+ int end = sindex.ValueCount;
+
+ return new IntDocValuesAnonymousInnerClassHelper(this, this, off, sindex, end);
+ }
+
+ private class IntDocValuesAnonymousInnerClassHelper : IntDocValues
+ {
+ private readonly ReverseOrdFieldSource outerInstance;
+
+ private int off;
+ private SortedDocValues sindex;
+ private int end;
+
+ public IntDocValuesAnonymousInnerClassHelper(ReverseOrdFieldSource outerInstance, org.apache.lucene.queries.function.valuesource.ReverseOrdFieldSource this, int off, SortedDocValues sindex, int end) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.off = off;
+ this.sindex = sindex;
+ this.end = end;
+ }
+
+ public override int intVal(int doc)
+ {
+ return (end - sindex.getOrd(doc + off) - 1);
+ }
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o == null || (o.GetType() != typeof(ReverseOrdFieldSource)))
+ {
+ return false;
+ }
+ ReverseOrdFieldSource other = (ReverseOrdFieldSource)o;
+ return this.field.Equals(other.field);
+ }
+
+ private static readonly int hcode = typeof(ReverseOrdFieldSource).GetHashCode();
+ public override int GetHashCode()
+ {
+ return hcode + field.GetHashCode();
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/ScaleFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/ScaleFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/ScaleFloatFunction.cs
new file mode 100644
index 0000000..4d27585
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/ScaleFloatFunction.cs
@@ -0,0 +1,200 @@
+using System.Collections;
+using System.Collections.Generic;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using ReaderUtil = org.apache.lucene.index.ReaderUtil;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+ /// <summary>
+ /// Scales values to be between min and max.
+ /// <para>This implementation currently traverses all of the source values to obtain
+ /// their min and max.
+ /// </para>
+ /// <para>This implementation currently cannot distinguish when documents have been
+ /// deleted or documents that have no value, and 0.0 values will be used for
+ /// these cases. This means that if values are normally all greater than 0.0, one can
+ /// still end up with 0.0 as the min value to map from. In these cases, an
+ /// appropriate map() function could be used as a workaround to change 0.0
+ /// to a value in the real range.
+ /// </para>
+ /// </summary>
+ public class ScaleFloatFunction : ValueSource
+ {
+ protected internal readonly ValueSource source;
+ protected internal readonly float min;
+ protected internal readonly float max;
+
+ public ScaleFloatFunction(ValueSource source, float min, float max)
+ {
+ this.source = source;
+ this.min = min;
+ this.max = max;
+ }
+
+ public override string description()
+ {
+ return "scale(" + source.description() + "," + min + "," + max + ")";
+ }
+
+ private class ScaleInfo
+ {
+ internal float minVal;
+ internal float maxVal;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: private ScaleInfo createScaleInfo(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ private ScaleInfo createScaleInfo(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final java.util.List<org.apache.lucene.index.AtomicReaderContext> leaves = org.apache.lucene.index.ReaderUtil.getTopLevelContext(readerContext).leaves();
+ IList<AtomicReaderContext> leaves = ReaderUtil.getTopLevelContext(readerContext).leaves();
+
+ float minVal = float.PositiveInfinity;
+ float maxVal = float.NegativeInfinity;
+
+ foreach (AtomicReaderContext leaf in leaves)
+ {
+ int maxDoc = leaf.reader().maxDoc();
+ FunctionValues vals = source.getValues(context, leaf);
+ for (int i = 0; i < maxDoc; i++)
+ {
+
+ float val = vals.floatVal(i);
+ if ((float.floatToRawIntBits(val) & (0xff << 23)) == 0xff << 23)
+ {
+ // if the exponent in the float is all ones, then this is +Inf, -Inf or NaN
+ // which don't make sense to factor into the scale function
+ continue;
+ }
+ if (val < minVal)
+ {
+ minVal = val;
+ }
+ if (val > maxVal)
+ {
+ maxVal = val;
+ }
+ }
+ }
+
+ if (minVal == float.PositiveInfinity)
+ {
+ // must have been an empty index
+ minVal = maxVal = 0;
+ }
+
+ ScaleInfo scaleInfo = new ScaleInfo();
+ scaleInfo.minVal = minVal;
+ scaleInfo.maxVal = maxVal;
+ context[ScaleFloatFunction.this] = scaleInfo;
+ return scaleInfo;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+
+ ScaleInfo scaleInfo = (ScaleInfo)context[ScaleFloatFunction.this];
+ if (scaleInfo == null)
+ {
+ scaleInfo = createScaleInfo(context, readerContext);
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float scale = (scaleInfo.maxVal-scaleInfo.minVal==0) ? 0 : (max-min)/(scaleInfo.maxVal-scaleInfo.minVal);
+ float scale = (scaleInfo.maxVal - scaleInfo.minVal == 0) ? 0 : (max - min) / (scaleInfo.maxVal - scaleInfo.minVal);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float minSource = scaleInfo.minVal;
+ float minSource = scaleInfo.minVal;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final float maxSource = scaleInfo.maxVal;
+ float maxSource = scaleInfo.maxVal;
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues vals = source.getValues(context, readerContext);
+ FunctionValues vals = source.getValues(context, readerContext);
+
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, scale, minSource, maxSource, vals);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly ScaleFloatFunction outerInstance;
+
+ private float scale;
+ private float minSource;
+ private float maxSource;
+ private FunctionValues vals;
+
+ public FloatDocValuesAnonymousInnerClassHelper(ScaleFloatFunction outerInstance, org.apache.lucene.queries.function.valuesource.ScaleFloatFunction this, float scale, float minSource, float maxSource, FunctionValues vals) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.scale = scale;
+ this.minSource = minSource;
+ this.maxSource = maxSource;
+ this.vals = vals;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return (vals.floatVal(doc) - minSource) * scale + outerInstance.min;
+ }
+ public override string ToString(int doc)
+ {
+ return "scale(" + vals.ToString(doc) + ",toMin=" + outerInstance.min + ",toMax=" + outerInstance.max + ",fromMin=" + minSource + ",fromMax=" + maxSource + ")";
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ source.createWeight(context, searcher);
+ }
+
+ public override int GetHashCode()
+ {
+ int h = float.floatToIntBits(min);
+ h = h * 29;
+ h += float.floatToIntBits(max);
+ h = h * 29;
+ h += source.GetHashCode();
+ return h;
+ }
+
+ public override bool Equals(object o)
+ {
+ if (typeof(ScaleFloatFunction) != o.GetType())
+ {
+ return false;
+ }
+ ScaleFloatFunction other = (ScaleFloatFunction)o;
+ return this.min == other.min && this.max == other.max && this.source.Equals(other.source);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/ShortFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/ShortFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/ShortFieldSource.cs
new file mode 100644
index 0000000..6240253
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/ShortFieldSource.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+
+
+ /// <summary>
+ /// Obtains short field values from the <seealso cref="org.apache.lucene.search.FieldCache"/>
+ /// using <code>getShorts()</code>
+ /// and makes those values available as other numeric types, casting as needed.
+ ///
+ /// </summary>
+ [Obsolete]
+ public class ShortFieldSource : FieldCacheSource
+ {
+
+ internal readonly FieldCache.ShortParser parser;
+
+ public ShortFieldSource(string field) : this(field, null)
+ {
+ }
+
+ public ShortFieldSource(string field, FieldCache.ShortParser parser) : base(field)
+ {
+ this.parser = parser;
+ }
+
+ public override string description()
+ {
+ return "short(" + field + ')';
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldCache.Shorts arr = cache.getShorts(readerContext.reader(), field, parser, false);
+ FieldCache.Shorts arr = cache.getShorts(readerContext.reader(), field, parser, false);
+
+ return new FunctionValuesAnonymousInnerClassHelper(this, arr);
+ }
+
+ private class FunctionValuesAnonymousInnerClassHelper : FunctionValues
+ {
+ private readonly ShortFieldSource outerInstance;
+
+ private FieldCache.Shorts arr;
+
+ public FunctionValuesAnonymousInnerClassHelper(ShortFieldSource outerInstance, FieldCache.Shorts arr)
+ {
+ this.outerInstance = outerInstance;
+ this.arr = arr;
+ }
+
+ public override sbyte byteVal(int doc)
+ {
+ return (sbyte) arr.get(doc);
+ }
+
+ public override short shortVal(int doc)
+ {
+ return arr.get(doc);
+ }
+
+ public override float floatVal(int doc)
+ {
+ return (float) arr.get(doc);
+ }
+
+ public override int intVal(int doc)
+ {
+ return (int) arr.get(doc);
+ }
+
+ public override long longVal(int doc)
+ {
+ return (long) arr.get(doc);
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return (double) arr.get(doc);
+ }
+
+ public override string strVal(int doc)
+ {
+ return Convert.ToString(arr.get(doc));
+ }
+
+ public override string ToString(int doc)
+ {
+ return outerInstance.description() + '=' + shortVal(doc);
+ }
+
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o.GetType() != typeof(ShortFieldSource))
+ {
+ return false;
+ }
+ ShortFieldSource other = (ShortFieldSource) o;
+ return base.Equals(other) && (this.parser == null ? other.parser == null : this.parser.GetType() == other.parser.GetType());
+ }
+
+ public override int GetHashCode()
+ {
+ int h = parser == null ? typeof(short?).GetHashCode() : parser.GetType().GetHashCode();
+ h += base.GetHashCode();
+ return h;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/SimpleBoolFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/SimpleBoolFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/SimpleBoolFunction.cs
new file mode 100644
index 0000000..01349f6
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/SimpleBoolFunction.cs
@@ -0,0 +1,108 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using BoolDocValues = org.apache.lucene.queries.function.docvalues.BoolDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+ /// <summary>
+ /// <seealso cref="BoolFunction"/> implementation which applies an extendible boolean
+ /// function to the values of a single wrapped <seealso cref="ValueSource"/>.
+ ///
+ /// Functions this can be used for include whether a field has a value or not,
+ /// or inverting the boolean value of the wrapped ValueSource.
+ /// </summary>
+ public abstract class SimpleBoolFunction : BoolFunction
+ {
+ protected internal readonly ValueSource source;
+
+ public SimpleBoolFunction(ValueSource source)
+ {
+ this.source = source;
+ }
+
+ protected internal abstract string name();
+
+ protected internal abstract bool func(int doc, FunctionValues vals);
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.docvalues.BoolDocValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override BoolDocValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues vals = source.getValues(context, readerContext);
+ FunctionValues vals = source.getValues(context, readerContext);
+ return new BoolDocValuesAnonymousInnerClassHelper(this, this, vals);
+ }
+
+ private class BoolDocValuesAnonymousInnerClassHelper : BoolDocValues
+ {
+ private readonly SimpleBoolFunction outerInstance;
+
+ private FunctionValues vals;
+
+ public BoolDocValuesAnonymousInnerClassHelper(SimpleBoolFunction outerInstance, org.apache.lucene.queries.function.valuesource.SimpleBoolFunction this, FunctionValues vals) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.vals = vals;
+ }
+
+ public override bool boolVal(int doc)
+ {
+ return outerInstance.func(doc, vals);
+ }
+ public override string ToString(int doc)
+ {
+ return outerInstance.name() + '(' + vals.ToString(doc) + ')';
+ }
+ }
+
+ public override string description()
+ {
+ return name() + '(' + source.description() + ')';
+ }
+
+ public override int GetHashCode()
+ {
+ return source.GetHashCode() + name().GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ SimpleBoolFunction other = (SimpleBoolFunction)o;
+ return this.source.Equals(other.source);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ source.createWeight(context, searcher);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/SimpleFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/SimpleFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/SimpleFloatFunction.cs
new file mode 100644
index 0000000..4cc6f29
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/SimpleFloatFunction.cs
@@ -0,0 +1,71 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+
+
+ /// <summary>
+ /// A simple float function with a single argument
+ /// </summary>
+ public abstract class SimpleFloatFunction : SingleFunction
+ {
+ public SimpleFloatFunction(ValueSource source) : base(source)
+ {
+ }
+
+ protected internal abstract float func(int doc, FunctionValues vals);
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues vals = source.getValues(context, readerContext);
+ FunctionValues vals = source.getValues(context, readerContext);
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, vals);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly SimpleFloatFunction outerInstance;
+
+ private FunctionValues vals;
+
+ public FloatDocValuesAnonymousInnerClassHelper(SimpleFloatFunction outerInstance, org.apache.lucene.queries.function.valuesource.SimpleFloatFunction this, FunctionValues vals) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.vals = vals;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return outerInstance.func(doc, vals);
+ }
+ public override string ToString(int doc)
+ {
+ return outerInstance.name() + '(' + vals.ToString(doc) + ')';
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/SingleFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/SingleFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/SingleFunction.cs
new file mode 100644
index 0000000..15084be
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/SingleFunction.cs
@@ -0,0 +1,67 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+ /// <summary>
+ /// A function with a single argument
+ /// </summary>
+ public abstract class SingleFunction : ValueSource
+ {
+ protected internal readonly ValueSource source;
+
+ public SingleFunction(ValueSource source)
+ {
+ this.source = source;
+ }
+
+ protected internal abstract string name();
+
+ public override string description()
+ {
+ return name() + '(' + source.description() + ')';
+ }
+
+ public override int GetHashCode()
+ {
+ return source.GetHashCode() + name().GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ SingleFunction other = (SingleFunction)o;
+ return this.name().Equals(other.name()) && this.source.Equals(other.source);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ source.createWeight(context, searcher);
+ }
+ }
+}
\ No newline at end of file
[05/11] Skeleton porting of Lucene.Net.Queries
Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/DivFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/DivFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/DivFloatFunction.cs
new file mode 100644
index 0000000..08912e5
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/DivFloatFunction.cs
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ /// <summary>
+ /// Function to divide "a" by "b"
+ /// </summary>
+ public class DivFloatFunction : DualFloatFunction
+ {
+ /// <param name="a"> the numerator. </param>
+ /// <param name="b"> the denominator. </param>
+ public DivFloatFunction(ValueSource a, ValueSource b) : base(a,b)
+ {
+ }
+
+ protected internal override string name()
+ {
+ return "div";
+ }
+
+ protected internal override float func(int doc, FunctionValues aVals, FunctionValues bVals)
+ {
+ return aVals.floatVal(doc) / bVals.floatVal(doc);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/DocFreqValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/DocFreqValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/DocFreqValueSource.cs
new file mode 100644
index 0000000..56ea07d
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/DocFreqValueSource.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using Term = org.apache.lucene.index.Term;
+ using DoubleDocValues = org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+ using IntDocValues = org.apache.lucene.queries.function.docvalues.IntDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+
+ internal class ConstIntDocValues : IntDocValues
+ {
+ internal readonly int ival;
+ internal readonly float fval;
+ internal readonly double dval;
+ internal readonly long lval;
+ internal readonly string sval;
+ internal readonly ValueSource parent;
+
+ internal ConstIntDocValues(int val, ValueSource parent) : base(parent)
+ {
+ ival = val;
+ fval = val;
+ dval = val;
+ lval = val;
+ sval = Convert.ToString(val);
+ this.parent = parent;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return fval;
+ }
+ public override int intVal(int doc)
+ {
+ return ival;
+ }
+ public override long longVal(int doc)
+ {
+ return lval;
+ }
+ public override double doubleVal(int doc)
+ {
+ return dval;
+ }
+ public override string strVal(int doc)
+ {
+ return sval;
+ }
+ public override string ToString(int doc)
+ {
+ return parent.description() + '=' + sval;
+ }
+ }
+
+ internal class ConstDoubleDocValues : DoubleDocValues
+ {
+ internal readonly int ival;
+ internal readonly float fval;
+ internal readonly double dval;
+ internal readonly long lval;
+ internal readonly string sval;
+ internal readonly ValueSource parent;
+
+ internal ConstDoubleDocValues(double val, ValueSource parent) : base(parent)
+ {
+ ival = (int)val;
+ fval = (float)val;
+ dval = val;
+ lval = (long)val;
+ sval = Convert.ToString(val);
+ this.parent = parent;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return fval;
+ }
+ public override int intVal(int doc)
+ {
+ return ival;
+ }
+ public override long longVal(int doc)
+ {
+ return lval;
+ }
+ public override double doubleVal(int doc)
+ {
+ return dval;
+ }
+ public override string strVal(int doc)
+ {
+ return sval;
+ }
+ public override string ToString(int doc)
+ {
+ return parent.description() + '=' + sval;
+ }
+ }
+
+
+ /// <summary>
+ /// <code>DocFreqValueSource</code> returns the number of documents containing the term.
+ /// @lucene.internal
+ /// </summary>
+ public class DocFreqValueSource : ValueSource
+ {
+ protected internal readonly string field;
+ protected internal readonly string indexedField;
+ protected internal readonly string val;
+ protected internal readonly BytesRef indexedBytes;
+
+ public DocFreqValueSource(string field, string val, string indexedField, BytesRef indexedBytes)
+ {
+ this.field = field;
+ this.val = val;
+ this.indexedField = indexedField;
+ this.indexedBytes = indexedBytes;
+ }
+
+ public virtual string name()
+ {
+ return "docfreq";
+ }
+
+ public override string description()
+ {
+ return name() + '(' + field + ',' + val + ')';
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ IndexSearcher searcher = (IndexSearcher)context["searcher"];
+ int docfreq = searcher.IndexReader.docFreq(new Term(indexedField, indexedBytes));
+ return new ConstIntDocValues(docfreq, this);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ context["searcher"] = searcher;
+ }
+
+ public override int GetHashCode()
+ {
+ return this.GetType().GetHashCode() + indexedField.GetHashCode() * 29 + indexedBytes.GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ DocFreqValueSource other = (DocFreqValueSource)o;
+ return this.indexedField.Equals(other.indexedField) && this.indexedBytes.Equals(other.indexedBytes);
+ }
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/DoubleConstValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/DoubleConstValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/DoubleConstValueSource.cs
new file mode 100644
index 0000000..e21be0c
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/DoubleConstValueSource.cs
@@ -0,0 +1,166 @@
+using System;
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using DoubleDocValues = org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+
+
+ /// <summary>
+ /// Function that returns a constant double value for every document.
+ /// </summary>
+ public class DoubleConstValueSource : ConstNumberSource
+ {
+ internal readonly double constant;
+ private readonly float fv;
+ private readonly long lv;
+
+ public DoubleConstValueSource(double constant)
+ {
+ this.constant = constant;
+ this.fv = (float)constant;
+ this.lv = (long)constant;
+ }
+
+ public override string description()
+ {
+ return "const(" + constant + ")";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ return new DoubleDocValuesAnonymousInnerClassHelper(this, this);
+ }
+
+ private class DoubleDocValuesAnonymousInnerClassHelper : DoubleDocValues
+ {
+ private readonly DoubleConstValueSource outerInstance;
+
+ public DoubleDocValuesAnonymousInnerClassHelper(DoubleConstValueSource outerInstance, org.apache.lucene.queries.function.valuesource.DoubleConstValueSource this) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return outerInstance.fv;
+ }
+
+ public override int intVal(int doc)
+ {
+ return (int) outerInstance.lv;
+ }
+
+ public override long longVal(int doc)
+ {
+ return outerInstance.lv;
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return outerInstance.constant;
+ }
+
+ public override string strVal(int doc)
+ {
+ return Convert.ToString(outerInstance.constant);
+ }
+
+ public override object objectVal(int doc)
+ {
+ return outerInstance.constant;
+ }
+
+ public override string ToString(int doc)
+ {
+ return outerInstance.description();
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ long bits = double.doubleToRawLongBits(constant);
+ return (int)(bits ^ ((long)((ulong)bits >> 32)));
+ }
+
+ public override bool Equals(object o)
+ {
+ if (!(o is DoubleConstValueSource))
+ {
+ return false;
+ }
+ DoubleConstValueSource other = (DoubleConstValueSource) o;
+ return this.constant == other.constant;
+ }
+
+ public override int Int
+ {
+ get
+ {
+ return (int)lv;
+ }
+ }
+
+ public override long Long
+ {
+ get
+ {
+ return lv;
+ }
+ }
+
+ public override float Float
+ {
+ get
+ {
+ return fv;
+ }
+ }
+
+ public override double Double
+ {
+ get
+ {
+ return constant;
+ }
+ }
+
+ public override Number Number
+ {
+ get
+ {
+ return constant;
+ }
+ }
+
+ public override bool Bool
+ {
+ get
+ {
+ return constant != 0;
+ }
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/DoubleFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/DoubleFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/DoubleFieldSource.cs
new file mode 100644
index 0000000..188974f
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/DoubleFieldSource.cs
@@ -0,0 +1,149 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using DoubleDocValues = org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+ using Bits = org.apache.lucene.util.Bits;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueDouble = org.apache.lucene.util.mutable.MutableValueDouble;
+
+ /// <summary>
+ /// Obtains double field values from <seealso cref="FieldCache#getDoubles"/> and makes
+ /// those values available as other numeric types, casting as needed.
+ /// </summary>
+ public class DoubleFieldSource : FieldCacheSource
+ {
+
+ protected internal readonly FieldCache.DoubleParser parser;
+
+ public DoubleFieldSource(string field) : this(field, null)
+ {
+ }
+
+ public DoubleFieldSource(string field, FieldCache.DoubleParser parser) : base(field)
+ {
+ this.parser = parser;
+ }
+
+ public override string description()
+ {
+ return "double(" + field + ')';
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldCache.Doubles arr = cache.getDoubles(readerContext.reader(), field, parser, true);
+ FieldCache.Doubles arr = cache.getDoubles(readerContext.reader(), field, parser, true);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+ Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+ return new DoubleDocValuesAnonymousInnerClassHelper(this, this, arr, valid);
+
+ }
+
+ private class DoubleDocValuesAnonymousInnerClassHelper : DoubleDocValues
+ {
+ private readonly DoubleFieldSource outerInstance;
+
+ private FieldCache.Doubles arr;
+ private Bits valid;
+
+ public DoubleDocValuesAnonymousInnerClassHelper(DoubleFieldSource outerInstance, org.apache.lucene.queries.function.valuesource.DoubleFieldSource this, FieldCache.Doubles arr, Bits valid) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.arr = arr;
+ this.valid = valid;
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return arr.get(doc);
+ }
+
+ public override bool exists(int doc)
+ {
+ return arr.get(doc) != 0 || valid.get(doc);
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly DoubleDocValuesAnonymousInnerClassHelper outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(DoubleDocValuesAnonymousInnerClassHelper outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueDouble();
+ }
+
+ private readonly MutableValueDouble mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.arr.get(doc);
+ mval.exists = mval.value != 0 || outerInstance.valid.get(doc);
+ }
+ }
+
+
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o.GetType() != typeof(DoubleFieldSource))
+ {
+ return false;
+ }
+ DoubleFieldSource other = (DoubleFieldSource) o;
+ return base.Equals(other) && (this.parser == null ? other.parser == null : this.parser.GetType() == other.parser.GetType());
+ }
+
+ public override int GetHashCode()
+ {
+ int h = parser == null ? typeof(double?).GetHashCode() : parser.GetType().GetHashCode();
+ h += base.GetHashCode();
+ return h;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/DualFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/DualFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/DualFloatFunction.cs
new file mode 100644
index 0000000..9a9c069
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/DualFloatFunction.cs
@@ -0,0 +1,121 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+ /// <summary>
+ /// Abstract <seealso cref="ValueSource"/> implementation which wraps two ValueSources
+ /// and applies an extendible float function to their values.
+ ///
+ /// </summary>
+ public abstract class DualFloatFunction : ValueSource
+ {
+ protected internal readonly ValueSource a;
+ protected internal readonly ValueSource b;
+
+ /// <param name="a"> the base. </param>
+ /// <param name="b"> the exponent. </param>
+ public DualFloatFunction(ValueSource a, ValueSource b)
+ {
+ this.a = a;
+ this.b = b;
+ }
+
+ protected internal abstract string name();
+ protected internal abstract float func(int doc, FunctionValues aVals, FunctionValues bVals);
+
+ public override string description()
+ {
+ return name() + "(" + a.description() + "," + b.description() + ")";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues aVals = a.getValues(context, readerContext);
+ FunctionValues aVals = a.getValues(context, readerContext);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues bVals = b.getValues(context, readerContext);
+ FunctionValues bVals = b.getValues(context, readerContext);
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, aVals, bVals);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly DualFloatFunction outerInstance;
+
+ private FunctionValues aVals;
+ private FunctionValues bVals;
+
+ public FloatDocValuesAnonymousInnerClassHelper(DualFloatFunction outerInstance, org.apache.lucene.queries.function.valuesource.DualFloatFunction this, FunctionValues aVals, FunctionValues bVals) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.aVals = aVals;
+ this.bVals = bVals;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return outerInstance.func(doc, aVals, bVals);
+ }
+
+ public override string ToString(int doc)
+ {
+ return outerInstance.name() + '(' + aVals.ToString(doc) + ',' + bVals.ToString(doc) + ')';
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ a.createWeight(context,searcher);
+ b.createWeight(context,searcher);
+ }
+
+ public override int GetHashCode()
+ {
+ int h = a.GetHashCode();
+ h ^= (h << 13) | ((int)((uint)h >> 20));
+ h += b.GetHashCode();
+ h ^= (h << 23) | ((int)((uint)h >> 10));
+ h += name().GetHashCode();
+ return h;
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ DualFloatFunction other = (DualFloatFunction)o;
+ return this.a.Equals(other.a) && this.b.Equals(other.b);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/EnumFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/EnumFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/EnumFieldSource.cs
new file mode 100644
index 0000000..cbdf2cb
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/EnumFieldSource.cs
@@ -0,0 +1,343 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using IntDocValues = org.apache.lucene.queries.function.docvalues.IntDocValues;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+ using Bits = org.apache.lucene.util.Bits;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueInt = org.apache.lucene.util.mutable.MutableValueInt;
+
+ /// <summary>
+ /// Obtains int field values from <seealso cref="FieldCache#getInts"/> and makes
+ /// those values available as other numeric types, casting as needed.
+ /// strVal of the value is not the int value, but its string (displayed) value
+ /// </summary>
+ public class EnumFieldSource : FieldCacheSource
+ {
+ internal const int? DEFAULT_VALUE = -1;
+
+ internal readonly FieldCache.IntParser parser;
+ internal readonly IDictionary<int?, string> enumIntToStringMap;
+ internal readonly IDictionary<string, int?> enumStringToIntMap;
+
+ public EnumFieldSource(string field, FieldCache.IntParser parser, IDictionary<int?, string> enumIntToStringMap, IDictionary<string, int?> enumStringToIntMap) : base(field)
+ {
+ this.parser = parser;
+ this.enumIntToStringMap = enumIntToStringMap;
+ this.enumStringToIntMap = enumStringToIntMap;
+ }
+
+ private static int? tryParseInt(string valueStr)
+ {
+ int? intValue = null;
+ try
+ {
+ intValue = Convert.ToInt32(valueStr);
+ }
+ catch (NumberFormatException)
+ {
+ }
+ return intValue;
+ }
+
+ private string intValueToStringValue(int? intVal)
+ {
+ if (intVal == null)
+ {
+ return null;
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final String enumString = enumIntToStringMap.get(intVal);
+ string enumString = enumIntToStringMap[intVal];
+ if (enumString != null)
+ {
+ return enumString;
+ }
+ // can't find matching enum name - return DEFAULT_VALUE.toString()
+ return DEFAULT_VALUE.ToString();
+ }
+
+ private int? stringValueToIntValue(string stringVal)
+ {
+ if (stringVal == null)
+ {
+ return null;
+ }
+
+ int? intValue;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Integer enumInt = enumStringToIntMap.get(stringVal);
+ int? enumInt = enumStringToIntMap[stringVal];
+ if (enumInt != null) //enum int found for string
+ {
+ return enumInt;
+ }
+
+ //enum int not found for string
+ intValue = tryParseInt(stringVal);
+ if (intValue == null) //not Integer
+ {
+ intValue = DEFAULT_VALUE;
+ }
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final String enumString = enumIntToStringMap.get(intValue);
+ string enumString = enumIntToStringMap[intValue];
+ if (enumString != null) //has matching string
+ {
+ return intValue;
+ }
+
+ return DEFAULT_VALUE;
+ }
+
+ public override string description()
+ {
+ return "enum(" + field + ')';
+ }
+
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldCache.Ints arr = cache.getInts(readerContext.reader(), field, parser, true);
+ FieldCache.Ints arr = cache.getInts(readerContext.reader(), field, parser, true);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+ Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+
+ return new IntDocValuesAnonymousInnerClassHelper(this, this, arr, valid);
+ }
+
+ private class IntDocValuesAnonymousInnerClassHelper : IntDocValues
+ {
+ private readonly EnumFieldSource outerInstance;
+
+ private FieldCache.Ints arr;
+ private Bits valid;
+
+ public IntDocValuesAnonymousInnerClassHelper(EnumFieldSource outerInstance, org.apache.lucene.queries.function.valuesource.EnumFieldSource this, FieldCache.Ints arr, Bits valid) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.arr = arr;
+ this.valid = valid;
+ val = new MutableValueInt();
+ }
+
+ internal readonly MutableValueInt val;
+
+ public override float floatVal(int doc)
+ {
+ return (float) arr.get(doc);
+ }
+
+ public override int intVal(int doc)
+ {
+ return arr.get(doc);
+ }
+
+ public override long longVal(int doc)
+ {
+ return (long) arr.get(doc);
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return (double) arr.get(doc);
+ }
+
+ public override string strVal(int doc)
+ {
+ int? intValue = arr.get(doc);
+ return outerInstance.intValueToStringValue(intValue);
+ }
+
+ public override object objectVal(int doc)
+ {
+ return valid.get(doc) ? arr.get(doc) : null;
+ }
+
+ public override bool exists(int doc)
+ {
+ return valid.get(doc);
+ }
+
+ public override string ToString(int doc)
+ {
+ return outerInstance.description() + '=' + strVal(doc);
+ }
+
+
+ public override ValueSourceScorer getRangeScorer(IndexReader reader, string lowerVal, string upperVal, bool includeLower, bool includeUpper)
+ {
+ int? lower = outerInstance.stringValueToIntValue(lowerVal);
+ int? upper = outerInstance.stringValueToIntValue(upperVal);
+
+ // instead of using separate comparison functions, adjust the endpoints.
+
+ if (lower == null)
+ {
+ lower = int.MinValue;
+ }
+ else
+ {
+ if (!includeLower && lower < int.MaxValue)
+ {
+ lower++;
+ }
+ }
+
+ if (upper == null)
+ {
+ upper = int.MaxValue;
+ }
+ else
+ {
+ if (!includeUpper && upper > int.MinValue)
+ {
+ upper--;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int ll = lower;
+ int ll = lower.Value;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int uu = upper;
+ int uu = upper.Value;
+
+ return new ValueSourceScorerAnonymousInnerClassHelper(this, reader, this, ll, uu);
+ }
+
+ private class ValueSourceScorerAnonymousInnerClassHelper : ValueSourceScorer
+ {
+ private readonly IntDocValuesAnonymousInnerClassHelper outerInstance;
+
+ private int ll;
+ private int uu;
+
+ public ValueSourceScorerAnonymousInnerClassHelper(IntDocValuesAnonymousInnerClassHelper outerInstance, IndexReader reader, org.apache.lucene.queries.function.valuesource.EnumFieldSource this, int ll, int uu) : base(reader, this)
+ {
+ this.outerInstance = outerInstance;
+ this.ll = ll;
+ this.uu = uu;
+ }
+
+ public override bool matchesValue(int doc)
+ {
+ int val = outerInstance.arr.get(doc);
+ // only check for deleted if it's the default value
+ // if (val==0 && reader.isDeleted(doc)) return false;
+ return val >= ll && val <= uu;
+ }
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly IntDocValuesAnonymousInnerClassHelper outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(IntDocValuesAnonymousInnerClassHelper outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueInt();
+ }
+
+ private readonly MutableValueInt mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.arr.get(doc);
+ mval.exists = outerInstance.valid.get(doc);
+ }
+ }
+
+
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || this.GetType() != o.GetType())
+ {
+ return false;
+ }
+ if (!base.Equals(o))
+ {
+ return false;
+ }
+
+ EnumFieldSource that = (EnumFieldSource) o;
+
+ if (!enumIntToStringMap.Equals(that.enumIntToStringMap))
+ {
+ return false;
+ }
+ if (!enumStringToIntMap.Equals(that.enumStringToIntMap))
+ {
+ return false;
+ }
+ if (!parser.Equals(that.parser))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ int result = base.GetHashCode();
+ result = 31 * result + parser.GetHashCode();
+ result = 31 * result + enumIntToStringMap.GetHashCode();
+ result = 31 * result + enumStringToIntMap.GetHashCode();
+ return result;
+ }
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/FieldCacheSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/FieldCacheSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/FieldCacheSource.cs
new file mode 100644
index 0000000..92c2cb4
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/FieldCacheSource.cs
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using FieldCache = org.apache.lucene.search.FieldCache;
+
+ /// <summary>
+ /// A base class for ValueSource implementations that retrieve values for
+ /// a single field from the <seealso cref="org.apache.lucene.search.FieldCache"/>.
+ ///
+ ///
+ /// </summary>
+ public abstract class FieldCacheSource : ValueSource
+ {
+ protected internal readonly string field;
+ protected internal readonly FieldCache cache = FieldCache.DEFAULT;
+
+ public FieldCacheSource(string field)
+ {
+ this.field = field;
+ }
+
+ public virtual FieldCache FieldCache
+ {
+ get
+ {
+ return cache;
+ }
+ }
+
+ public virtual string Field
+ {
+ get
+ {
+ return field;
+ }
+ }
+
+ public override string description()
+ {
+ return field;
+ }
+
+ public override bool Equals(object o)
+ {
+ if (!(o is FieldCacheSource))
+ {
+ return false;
+ }
+ FieldCacheSource other = (FieldCacheSource)o;
+ return this.field.Equals(other.field) && this.cache == other.cache;
+ }
+
+ public override int GetHashCode()
+ {
+ return cache.GetHashCode() + field.GetHashCode();
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/FloatFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/FloatFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/FloatFieldSource.cs
new file mode 100644
index 0000000..c60d99f
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/FloatFieldSource.cs
@@ -0,0 +1,152 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+ using Bits = org.apache.lucene.util.Bits;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueFloat = org.apache.lucene.util.mutable.MutableValueFloat;
+
+ /// <summary>
+ /// Obtains float field values from <seealso cref="FieldCache#getFloats"/> and makes those
+ /// values available as other numeric types, casting as needed.
+ /// </summary>
+ public class FloatFieldSource : FieldCacheSource
+ {
+
+ protected internal readonly FieldCache.FloatParser parser;
+
+ public FloatFieldSource(string field) : this(field, null)
+ {
+ }
+
+ public FloatFieldSource(string field, FieldCache.FloatParser parser) : base(field)
+ {
+ this.parser = parser;
+ }
+
+ public override string description()
+ {
+ return "float(" + field + ')';
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldCache.Floats arr = cache.getFloats(readerContext.reader(), field, parser, true);
+ FieldCache.Floats arr = cache.getFloats(readerContext.reader(), field, parser, true);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+ Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, arr, valid);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly FloatFieldSource outerInstance;
+
+ private FieldCache.Floats arr;
+ private Bits valid;
+
+ public FloatDocValuesAnonymousInnerClassHelper(FloatFieldSource outerInstance, org.apache.lucene.queries.function.valuesource.FloatFieldSource this, FieldCache.Floats arr, Bits valid) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.arr = arr;
+ this.valid = valid;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return arr.get(doc);
+ }
+
+ public override object objectVal(int doc)
+ {
+ return valid.get(doc) ? arr.get(doc) : null;
+ }
+
+ public override bool exists(int doc)
+ {
+ return arr.get(doc) != 0 || valid.get(doc);
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly FloatDocValuesAnonymousInnerClassHelper outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(FloatDocValuesAnonymousInnerClassHelper outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueFloat();
+ }
+
+ private readonly MutableValueFloat mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.arr.get(doc);
+ mval.exists = mval.value != 0 || outerInstance.valid.get(doc);
+ }
+ }
+
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o.GetType() != typeof(FloatFieldSource))
+ {
+ return false;
+ }
+ FloatFieldSource other = (FloatFieldSource)o;
+ return base.Equals(other) && (this.parser == null ? other.parser == null : this.parser.GetType() == other.parser.GetType());
+ }
+
+ public override int GetHashCode()
+ {
+ int h = parser == null ? typeof(float?).GetHashCode() : parser.GetType().GetHashCode();
+ h += base.GetHashCode();
+ return h;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/IDFValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/IDFValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/IDFValueSource.cs
new file mode 100644
index 0000000..13456ff
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/IDFValueSource.cs
@@ -0,0 +1,85 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using org.apache.lucene.index;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using PerFieldSimilarityWrapper = org.apache.lucene.search.similarities.PerFieldSimilarityWrapper;
+ using Similarity = org.apache.lucene.search.similarities.Similarity;
+ using TFIDFSimilarity = org.apache.lucene.search.similarities.TFIDFSimilarity;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+ /// <summary>
+ /// Function that returns <seealso cref="TFIDFSimilarity #idf(long, long)"/>
+ /// for every document.
+ /// <para>
+ /// Note that the configured Similarity for the field must be
+ /// a subclass of <seealso cref="TFIDFSimilarity"/>
+ /// @lucene.internal
+ /// </para>
+ /// </summary>
+ public class IDFValueSource : DocFreqValueSource
+ {
+ public IDFValueSource(string field, string val, string indexedField, BytesRef indexedBytes) : base(field, val, indexedField, indexedBytes)
+ {
+ }
+
+ public override string name()
+ {
+ return "idf";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ IndexSearcher searcher = (IndexSearcher)context["searcher"];
+ TFIDFSimilarity sim = asTFIDF(searcher.Similarity, field);
+ if (sim == null)
+ {
+ throw new System.NotSupportedException("requires a TFIDFSimilarity (such as DefaultSimilarity)");
+ }
+ int docfreq = searcher.IndexReader.docFreq(new Term(indexedField, indexedBytes));
+ float idf = sim.idf(docfreq, searcher.IndexReader.maxDoc());
+ return new ConstDoubleDocValues(idf, this);
+ }
+
+ // tries extra hard to cast the sim to TFIDFSimilarity
+ internal static TFIDFSimilarity asTFIDF(Similarity sim, string field)
+ {
+ while (sim is PerFieldSimilarityWrapper)
+ {
+ sim = ((PerFieldSimilarityWrapper)sim).get(field);
+ }
+ if (sim is TFIDFSimilarity)
+ {
+ return (TFIDFSimilarity)sim;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/IfFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/IfFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/IfFunction.cs
new file mode 100644
index 0000000..a62c801
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/IfFunction.cs
@@ -0,0 +1,186 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using Explanation = org.apache.lucene.search.Explanation;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+
+ /// <summary>
+ /// Depending on the boolean value of the <code>ifSource</code> function,
+ /// returns the value of the <code>trueSource</code> or <code>falseSource</code> function.
+ /// </summary>
+ public class IfFunction : BoolFunction
+ {
+ private readonly ValueSource ifSource;
+ private readonly ValueSource trueSource;
+ private readonly ValueSource falseSource;
+
+
+ public IfFunction(ValueSource ifSource, ValueSource trueSource, ValueSource falseSource)
+ {
+ this.ifSource = ifSource;
+ this.trueSource = trueSource;
+ this.falseSource = falseSource;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues ifVals = ifSource.getValues(context, readerContext);
+ FunctionValues ifVals = ifSource.getValues(context, readerContext);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues trueVals = trueSource.getValues(context, readerContext);
+ FunctionValues trueVals = trueSource.getValues(context, readerContext);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues falseVals = falseSource.getValues(context, readerContext);
+ FunctionValues falseVals = falseSource.getValues(context, readerContext);
+
+ return new FunctionValuesAnonymousInnerClassHelper(this, ifVals, trueVals, falseVals);
+
+ }
+
+ private class FunctionValuesAnonymousInnerClassHelper : FunctionValues
+ {
+ private readonly IfFunction outerInstance;
+
+ private FunctionValues ifVals;
+ private FunctionValues trueVals;
+ private FunctionValues falseVals;
+
+ public FunctionValuesAnonymousInnerClassHelper(IfFunction outerInstance, FunctionValues ifVals, FunctionValues trueVals, FunctionValues falseVals)
+ {
+ this.outerInstance = outerInstance;
+ this.ifVals = ifVals;
+ this.trueVals = trueVals;
+ this.falseVals = falseVals;
+ }
+
+ public override sbyte byteVal(int doc)
+ {
+ return ifVals.boolVal(doc) ? trueVals.byteVal(doc) : falseVals.byteVal(doc);
+ }
+
+ public override short shortVal(int doc)
+ {
+ return ifVals.boolVal(doc) ? trueVals.shortVal(doc) : falseVals.shortVal(doc);
+ }
+
+ public override float floatVal(int doc)
+ {
+ return ifVals.boolVal(doc) ? trueVals.floatVal(doc) : falseVals.floatVal(doc);
+ }
+
+ public override int intVal(int doc)
+ {
+ return ifVals.boolVal(doc) ? trueVals.intVal(doc) : falseVals.intVal(doc);
+ }
+
+ public override long longVal(int doc)
+ {
+ return ifVals.boolVal(doc) ? trueVals.longVal(doc) : falseVals.longVal(doc);
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return ifVals.boolVal(doc) ? trueVals.doubleVal(doc) : falseVals.doubleVal(doc);
+ }
+
+ public override string strVal(int doc)
+ {
+ return ifVals.boolVal(doc) ? trueVals.strVal(doc) : falseVals.strVal(doc);
+ }
+
+ public override bool boolVal(int doc)
+ {
+ return ifVals.boolVal(doc) ? trueVals.boolVal(doc) : falseVals.boolVal(doc);
+ }
+
+ public override bool bytesVal(int doc, BytesRef target)
+ {
+ return ifVals.boolVal(doc) ? trueVals.bytesVal(doc, target) : falseVals.bytesVal(doc, target);
+ }
+
+ public override object objectVal(int doc)
+ {
+ return ifVals.boolVal(doc) ? trueVals.objectVal(doc) : falseVals.objectVal(doc);
+ }
+
+ public override bool exists(int doc)
+ {
+ return true; // TODO: flow through to any sub-sources?
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ // TODO: we need types of trueSource / falseSource to handle this
+ // for now, use float.
+ return base.ValueFiller;
+ }
+ }
+
+ public override string ToString(int doc)
+ {
+ return "if(" + ifVals.ToString(doc) + ',' + trueVals.ToString(doc) + ',' + falseVals.ToString(doc) + ')';
+ }
+ }
+
+ public override string description()
+ {
+ return "if(" + ifSource.description() + ',' + trueSource.description() + ',' + falseSource + ')';
+ }
+
+ public override int GetHashCode()
+ {
+ int h = ifSource.GetHashCode();
+ h = h * 31 + trueSource.GetHashCode();
+ h = h * 31 + falseSource.GetHashCode();
+ return h;
+ }
+
+ public override bool Equals(object o)
+ {
+ if (!(o is IfFunction))
+ {
+ return false;
+ }
+ IfFunction other = (IfFunction)o;
+ return ifSource.Equals(other.ifSource) && trueSource.Equals(other.trueSource) && falseSource.Equals(other.falseSource);
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ ifSource.createWeight(context, searcher);
+ trueSource.createWeight(context, searcher);
+ falseSource.createWeight(context, searcher);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/IntFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/IntFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/IntFieldSource.cs
new file mode 100644
index 0000000..bb6cf35
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/IntFieldSource.cs
@@ -0,0 +1,183 @@
+using System;
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using IntDocValues = org.apache.lucene.queries.function.docvalues.IntDocValues;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+ using Bits = org.apache.lucene.util.Bits;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueInt = org.apache.lucene.util.mutable.MutableValueInt;
+
+ /// <summary>
+ /// Obtains int field values from <seealso cref="FieldCache#getInts"/> and makes those
+ /// values available as other numeric types, casting as needed.
+ /// </summary>
+ public class IntFieldSource : FieldCacheSource
+ {
+ internal readonly FieldCache.IntParser parser;
+
+ public IntFieldSource(string field) : this(field, null)
+ {
+ }
+
+ public IntFieldSource(string field, FieldCache.IntParser parser) : base(field)
+ {
+ this.parser = parser;
+ }
+
+ public override string description()
+ {
+ return "int(" + field + ')';
+ }
+
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldCache.Ints arr = cache.getInts(readerContext.reader(), field, parser, true);
+ FieldCache.Ints arr = cache.getInts(readerContext.reader(), field, parser, true);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+ Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+
+ return new IntDocValuesAnonymousInnerClassHelper(this, this, arr, valid);
+ }
+
+ private class IntDocValuesAnonymousInnerClassHelper : IntDocValues
+ {
+ private readonly IntFieldSource outerInstance;
+
+ private FieldCache.Ints arr;
+ private Bits valid;
+
+ public IntDocValuesAnonymousInnerClassHelper(IntFieldSource outerInstance, org.apache.lucene.queries.function.valuesource.IntFieldSource this, FieldCache.Ints arr, Bits valid) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.arr = arr;
+ this.valid = valid;
+ val = new MutableValueInt();
+ }
+
+ internal readonly MutableValueInt val;
+
+ public override float floatVal(int doc)
+ {
+ return (float)arr.get(doc);
+ }
+
+ public override int intVal(int doc)
+ {
+ return arr.get(doc);
+ }
+
+ public override long longVal(int doc)
+ {
+ return (long)arr.get(doc);
+ }
+
+ public override double doubleVal(int doc)
+ {
+ return (double)arr.get(doc);
+ }
+
+ public override string strVal(int doc)
+ {
+ return Convert.ToString(arr.get(doc));
+ }
+
+ public override object objectVal(int doc)
+ {
+ return valid.get(doc) ? arr.get(doc) : null;
+ }
+
+ public override bool exists(int doc)
+ {
+ return arr.get(doc) != 0 || valid.get(doc);
+ }
+
+ public override string ToString(int doc)
+ {
+ return outerInstance.description() + '=' + intVal(doc);
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly IntDocValuesAnonymousInnerClassHelper outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(IntDocValuesAnonymousInnerClassHelper outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = new MutableValueInt();
+ }
+
+ private readonly MutableValueInt mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.arr.get(doc);
+ mval.exists = mval.value != 0 || outerInstance.valid.get(doc);
+ }
+ }
+
+
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o.GetType() != typeof(IntFieldSource))
+ {
+ return false;
+ }
+ IntFieldSource other = (IntFieldSource)o;
+ return base.Equals(other) && (this.parser == null ? other.parser == null : this.parser.GetType() == other.parser.GetType());
+ }
+
+ public override int GetHashCode()
+ {
+ int h = parser == null ? typeof(int?).GetHashCode() : parser.GetType().GetHashCode();
+ h += base.GetHashCode();
+ return h;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/JoinDocFreqValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/JoinDocFreqValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/JoinDocFreqValueSource.cs
new file mode 100644
index 0000000..46cc5c7
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/JoinDocFreqValueSource.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using BinaryDocValues = org.apache.lucene.index.BinaryDocValues;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using MultiFields = org.apache.lucene.index.MultiFields;
+ using ReaderUtil = org.apache.lucene.index.ReaderUtil;
+ using Terms = org.apache.lucene.index.Terms;
+ using TermsEnum = org.apache.lucene.index.TermsEnum;
+ using IntDocValues = org.apache.lucene.queries.function.docvalues.IntDocValues;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+ using PackedInts = org.apache.lucene.util.packed.PackedInts;
+
+ /// <summary>
+ /// Use a field value and find the Document Frequency within another field.
+ ///
+ /// @since solr 4.0
+ /// </summary>
+ public class JoinDocFreqValueSource : FieldCacheSource
+ {
+
+ public const string NAME = "joindf";
+
+ protected internal readonly string qfield;
+
+ public JoinDocFreqValueSource(string field, string qfield) : base(field)
+ {
+ this.qfield = qfield;
+ }
+
+ public override string description()
+ {
+ return NAME + "(" + field + ":(" + qfield + "))";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.BinaryDocValues terms = cache.getTerms(readerContext.reader(), field, false, org.apache.lucene.util.packed.PackedInts.FAST);
+ BinaryDocValues terms = cache.getTerms(readerContext.reader(), field, false, PackedInts.FAST);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.IndexReader top = org.apache.lucene.index.ReaderUtil.getTopLevelContext(readerContext).reader();
+ IndexReader top = ReaderUtil.getTopLevelContext(readerContext).reader();
+ Terms t = MultiFields.getTerms(top, qfield);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.TermsEnum termsEnum = t == null ? org.apache.lucene.index.TermsEnum.EMPTY : t.iterator(null);
+ TermsEnum termsEnum = t == null ? TermsEnum.EMPTY : t.iterator(null);
+
+ return new IntDocValuesAnonymousInnerClassHelper(this, this, terms, termsEnum);
+ }
+
+ private class IntDocValuesAnonymousInnerClassHelper : IntDocValues
+ {
+ private readonly JoinDocFreqValueSource outerInstance;
+
+ private BinaryDocValues terms;
+ private TermsEnum termsEnum;
+
+ public IntDocValuesAnonymousInnerClassHelper(JoinDocFreqValueSource outerInstance, org.apache.lucene.queries.function.valuesource.JoinDocFreqValueSource this, BinaryDocValues terms, TermsEnum termsEnum) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.terms = terms;
+ this.termsEnum = termsEnum;
+ @ref = new BytesRef();
+ }
+
+ internal readonly BytesRef @ref;
+
+ public override int intVal(int doc)
+ {
+ try
+ {
+ terms.get(doc, @ref);
+ if (termsEnum.seekExact(@ref))
+ {
+ return termsEnum.docFreq();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ catch (IOException e)
+ {
+ throw new Exception("caught exception in function " + outerInstance.description() + " : doc=" + doc, e);
+ }
+ }
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o.GetType() != typeof(JoinDocFreqValueSource))
+ {
+ return false;
+ }
+ JoinDocFreqValueSource other = (JoinDocFreqValueSource)o;
+ if (!qfield.Equals(other.qfield))
+ {
+ return false;
+ }
+ return base.Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return qfield.GetHashCode() + base.GetHashCode();
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/LinearFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/LinearFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/LinearFloatFunction.cs
new file mode 100644
index 0000000..a03268c
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/LinearFloatFunction.cs
@@ -0,0 +1,113 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using FloatDocValues = org.apache.lucene.queries.function.docvalues.FloatDocValues;
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+ /// <summary>
+ /// <code>LinearFloatFunction</code> implements a linear function over
+ /// another <seealso cref="ValueSource"/>.
+ /// <br>
+ /// Normally Used as an argument to a <seealso cref="org.apache.lucene.queries.function.FunctionQuery"/>
+ ///
+ ///
+ /// </summary>
+ public class LinearFloatFunction : ValueSource
+ {
+ protected internal readonly ValueSource source;
+ protected internal readonly float slope;
+ protected internal readonly float intercept;
+
+ public LinearFloatFunction(ValueSource source, float slope, float intercept)
+ {
+ this.source = source;
+ this.slope = slope;
+ this.intercept = intercept;
+ }
+
+ public override string description()
+ {
+ return slope + "*float(" + source.description() + ")+" + intercept;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.queries.function.FunctionValues vals = source.getValues(context, readerContext);
+ FunctionValues vals = source.getValues(context, readerContext);
+ return new FloatDocValuesAnonymousInnerClassHelper(this, this, vals);
+ }
+
+ private class FloatDocValuesAnonymousInnerClassHelper : FloatDocValues
+ {
+ private readonly LinearFloatFunction outerInstance;
+
+ private FunctionValues vals;
+
+ public FloatDocValuesAnonymousInnerClassHelper(LinearFloatFunction outerInstance, org.apache.lucene.queries.function.valuesource.LinearFloatFunction this, FunctionValues vals) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.vals = vals;
+ }
+
+ public override float floatVal(int doc)
+ {
+ return vals.floatVal(doc) * outerInstance.slope + outerInstance.intercept;
+ }
+ public override string ToString(int doc)
+ {
+ return outerInstance.slope + "*float(" + vals.ToString(doc) + ")+" + outerInstance.intercept;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ source.createWeight(context, searcher);
+ }
+
+ public override int GetHashCode()
+ {
+ int h = float.floatToIntBits(slope);
+ h = ((int)((uint)h >> 2)) | (h << 30);
+ h += float.floatToIntBits(intercept);
+ h ^= (h << 14) | ((int)((uint)h >> 19));
+ return h + source.GetHashCode();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (typeof(LinearFloatFunction) != o.GetType())
+ {
+ return false;
+ }
+ LinearFloatFunction other = (LinearFloatFunction)o;
+ return this.slope == other.slope && this.intercept == other.intercept && this.source.Equals(other.source);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/LiteralValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/LiteralValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/LiteralValueSource.cs
new file mode 100644
index 0000000..6107a28
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/LiteralValueSource.cs
@@ -0,0 +1,117 @@
+using System.Collections;
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using StrDocValues = org.apache.lucene.queries.function.docvalues.StrDocValues;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+
+
+
+ /// <summary>
+ /// Pass a the field value through as a String, no matter the type // Q: doesn't this mean it's a "string"?
+ ///
+ ///
+ /// </summary>
+ public class LiteralValueSource : ValueSource
+ {
+ protected internal readonly string @string;
+ protected internal readonly BytesRef bytesRef;
+
+ public LiteralValueSource(string @string)
+ {
+ this.@string = @string;
+ this.bytesRef = new BytesRef(@string);
+ }
+
+ /// <summary>
+ /// returns the literal value </summary>
+ public virtual string Value
+ {
+ get
+ {
+ return @string;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+
+ return new StrDocValuesAnonymousInnerClassHelper(this, this);
+ }
+
+ private class StrDocValuesAnonymousInnerClassHelper : StrDocValues
+ {
+ private readonly LiteralValueSource outerInstance;
+
+ public StrDocValuesAnonymousInnerClassHelper(LiteralValueSource outerInstance, org.apache.lucene.queries.function.valuesource.LiteralValueSource this) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ }
+
+ public override string strVal(int doc)
+ {
+ return outerInstance.@string;
+ }
+
+ public override bool bytesVal(int doc, BytesRef target)
+ {
+ target.copyBytes(outerInstance.bytesRef);
+ return true;
+ }
+
+ public override string ToString(int doc)
+ {
+ return outerInstance.@string;
+ }
+ }
+
+ public override string description()
+ {
+ return "literal(" + @string + ")";
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (!(o is LiteralValueSource))
+ {
+ return false;
+ }
+
+ LiteralValueSource that = (LiteralValueSource) o;
+
+ return @string.Equals(that.@string);
+
+ }
+
+ public static readonly int hash = typeof(LiteralValueSource).GetHashCode();
+ public override int GetHashCode()
+ {
+ return hash + @string.GetHashCode();
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/LongFieldSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/LongFieldSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/LongFieldSource.cs
new file mode 100644
index 0000000..d831ebd
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/LongFieldSource.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Collections;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader;
+ using LongDocValues = org.apache.lucene.queries.function.docvalues.LongDocValues;
+ using FieldCache = org.apache.lucene.search.FieldCache;
+ using Bits = org.apache.lucene.util.Bits;
+ using MutableValue = org.apache.lucene.util.mutable.MutableValue;
+ using MutableValueLong = org.apache.lucene.util.mutable.MutableValueLong;
+
+ /// <summary>
+ /// Obtains long field values from <seealso cref="FieldCache#getLongs"/> and makes those
+ /// values available as other numeric types, casting as needed.
+ /// </summary>
+ public class LongFieldSource : FieldCacheSource
+ {
+
+ protected internal readonly FieldCache.LongParser parser;
+
+ public LongFieldSource(string field) : this(field, null)
+ {
+ }
+
+ public LongFieldSource(string field, FieldCache.LongParser parser) : base(field)
+ {
+ this.parser = parser;
+ }
+
+ public override string description()
+ {
+ return "long(" + field + ')';
+ }
+
+ public virtual long externalToLong(string extVal)
+ {
+ return Convert.ToInt64(extVal);
+ }
+
+ public virtual object longToObject(long val)
+ {
+ return val;
+ }
+
+ public virtual string longToString(long val)
+ {
+ return longToObject(val).ToString();
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.search.FieldCache.Longs arr = cache.getLongs(readerContext.reader(), field, parser, true);
+ FieldCache.Longs arr = cache.getLongs(readerContext.reader(), field, parser, true);
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+ Bits valid = cache.getDocsWithField(readerContext.reader(), field);
+
+ return new LongDocValuesAnonymousInnerClassHelper(this, this, arr, valid);
+ }
+
+ private class LongDocValuesAnonymousInnerClassHelper : LongDocValues
+ {
+ private readonly LongFieldSource outerInstance;
+
+ private FieldCache.Longs arr;
+ private Bits valid;
+
+ public LongDocValuesAnonymousInnerClassHelper(LongFieldSource outerInstance, org.apache.lucene.queries.function.valuesource.LongFieldSource this, FieldCache.Longs arr, Bits valid) : base(this)
+ {
+ this.outerInstance = outerInstance;
+ this.arr = arr;
+ this.valid = valid;
+ }
+
+ public override long longVal(int doc)
+ {
+ return arr.get(doc);
+ }
+
+ public override bool exists(int doc)
+ {
+ return arr.get(doc) != 0 || valid.get(doc);
+ }
+
+ public override object objectVal(int doc)
+ {
+ return valid.get(doc) ? outerInstance.longToObject(arr.get(doc)) : null;
+ }
+
+ public override string strVal(int doc)
+ {
+ return valid.get(doc) ? outerInstance.longToString(arr.get(doc)) : null;
+ }
+
+ protected internal override long externalToLong(string extVal)
+ {
+ return outerInstance.externalToLong(extVal);
+ }
+
+ public override ValueFiller ValueFiller
+ {
+ get
+ {
+ return new ValueFillerAnonymousInnerClassHelper(this);
+ }
+ }
+
+ private class ValueFillerAnonymousInnerClassHelper : ValueFiller
+ {
+ private readonly LongDocValuesAnonymousInnerClassHelper outerInstance;
+
+ public ValueFillerAnonymousInnerClassHelper(LongDocValuesAnonymousInnerClassHelper outerInstance)
+ {
+ this.outerInstance = outerInstance;
+ mval = outerInstance.outerInstance.newMutableValueLong();
+ }
+
+ private readonly MutableValueLong mval;
+
+ public override MutableValue Value
+ {
+ get
+ {
+ return mval;
+ }
+ }
+
+ public override void fillValue(int doc)
+ {
+ mval.value = outerInstance.arr.get(doc);
+ mval.exists = mval.value != 0 || outerInstance.valid.get(doc);
+ }
+ }
+
+ }
+
+ protected internal virtual MutableValueLong newMutableValueLong()
+ {
+ return new MutableValueLong();
+ }
+
+ public override bool Equals(object o)
+ {
+ if (o.GetType() != this.GetType())
+ {
+ return false;
+ }
+ LongFieldSource other = (LongFieldSource) o;
+ return base.Equals(other) && (this.parser == null ? other.parser == null : this.parser.GetType() == other.parser.GetType());
+ }
+
+ public override int GetHashCode()
+ {
+ int h = parser == null ? this.GetType().GetHashCode() : parser.GetType().GetHashCode();
+ h += base.GetHashCode();
+ return h;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/MaxDocValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/MaxDocValueSource.cs b/src/Lucene.Net.Queries/Function/ValueSource/MaxDocValueSource.cs
new file mode 100644
index 0000000..0e00953
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/MaxDocValueSource.cs
@@ -0,0 +1,70 @@
+using System.Collections;
+
+/*
+ * 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.
+ */
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+ using AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using IndexReader = org.apache.lucene.index.IndexReader; // javadocs
+ using IndexSearcher = org.apache.lucene.search.IndexSearcher;
+
+
+ /// <summary>
+ /// Returns the value of <seealso cref="IndexReader#maxDoc()"/>
+ /// for every document. This is the number of documents
+ /// including deletions.
+ /// </summary>
+ public class MaxDocValueSource : ValueSource
+ {
+ public virtual string name()
+ {
+ return "maxdoc";
+ }
+
+ public override string description()
+ {
+ return name() + "()";
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public void createWeight(java.util.Map context, org.apache.lucene.search.IndexSearcher searcher) throws java.io.IOException
+ public override void createWeight(IDictionary context, IndexSearcher searcher)
+ {
+ context["searcher"] = searcher;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.queries.function.FunctionValues getValues(java.util.Map context, org.apache.lucene.index.AtomicReaderContext readerContext) throws java.io.IOException
+ public override FunctionValues getValues(IDictionary context, AtomicReaderContext readerContext)
+ {
+ IndexSearcher searcher = (IndexSearcher)context["searcher"];
+ return new ConstIntDocValues(searcher.IndexReader.maxDoc(), this);
+ }
+
+ public override bool Equals(object o)
+ {
+ return this.GetType() == o.GetType();
+ }
+
+ public override int GetHashCode()
+ {
+ return this.GetType().GetHashCode();
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/MaxFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/MaxFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/MaxFloatFunction.cs
new file mode 100644
index 0000000..24034c3
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/MaxFloatFunction.cs
@@ -0,0 +1,53 @@
+using System;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ /// <summary>
+ /// <code>MaxFloatFunction</code> returns the max of it's components.
+ /// </summary>
+ public class MaxFloatFunction : MultiFloatFunction
+ {
+ public MaxFloatFunction(ValueSource[] sources) : base(sources)
+ {
+ }
+
+ protected internal override string name()
+ {
+ return "max";
+ }
+
+ protected internal override float func(int doc, FunctionValues[] valsArr)
+ {
+ if (valsArr.Length == 0)
+ {
+ return 0.0f;
+ }
+ float val = float.NegativeInfinity;
+ foreach (FunctionValues vals in valsArr)
+ {
+ val = Math.Max(vals.floatVal(doc), val);
+ }
+ return val;
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/Function/ValueSource/MinFloatFunction.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/Function/ValueSource/MinFloatFunction.cs b/src/Lucene.Net.Queries/Function/ValueSource/MinFloatFunction.cs
new file mode 100644
index 0000000..f4abce7
--- /dev/null
+++ b/src/Lucene.Net.Queries/Function/ValueSource/MinFloatFunction.cs
@@ -0,0 +1,53 @@
+using System;
+
+/*
+ * 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.
+ */
+
+namespace org.apache.lucene.queries.function.valuesource
+{
+
+
+ /// <summary>
+ /// <code>MinFloatFunction</code> returns the min of it's components.
+ /// </summary>
+ public class MinFloatFunction : MultiFloatFunction
+ {
+ public MinFloatFunction(ValueSource[] sources) : base(sources)
+ {
+ }
+
+ protected internal override string name()
+ {
+ return "min";
+ }
+
+ protected internal override float func(int doc, FunctionValues[] valsArr)
+ {
+ if (valsArr.Length == 0)
+ {
+ return 0.0f;
+ }
+ float val = float.PositiveInfinity;
+ foreach (FunctionValues vals in valsArr)
+ {
+ val = Math.Min(vals.floatVal(doc), val);
+ }
+ return val;
+ }
+ }
+
+}
\ No newline at end of file
[02/11] Skeleton porting of Lucene.Net.Queries
Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/TermFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/TermFilter.cs b/src/Lucene.Net.Queries/TermFilter.cs
new file mode 100644
index 0000000..1e4ffd0
--- /dev/null
+++ b/src/Lucene.Net.Queries/TermFilter.cs
@@ -0,0 +1,139 @@
+namespace org.apache.lucene.queries
+{
+
+ /*
+ * 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 AtomicReaderContext = org.apache.lucene.index.AtomicReaderContext;
+ using DocsEnum = org.apache.lucene.index.DocsEnum;
+ using Term = org.apache.lucene.index.Term;
+ using Terms = org.apache.lucene.index.Terms;
+ using TermsEnum = org.apache.lucene.index.TermsEnum;
+ using DocIdSet = org.apache.lucene.search.DocIdSet;
+ using DocIdSetIterator = org.apache.lucene.search.DocIdSetIterator;
+ using Filter = org.apache.lucene.search.Filter;
+ using Bits = org.apache.lucene.util.Bits;
+
+ /// <summary>
+ /// A filter that includes documents that match with a specific term.
+ /// </summary>
+ public sealed class TermFilter : Filter
+ {
+
+ private readonly Term term;
+
+ /// <param name="term"> The term documents need to have in order to be a match for this filter. </param>
+ public TermFilter(Term term)
+ {
+ if (term == null)
+ {
+ throw new System.ArgumentException("Term must not be null");
+ }
+ else if (term.field() == null)
+ {
+ throw new System.ArgumentException("Field must not be null");
+ }
+ this.term = term;
+ }
+
+ /// <returns> The term this filter includes documents with. </returns>
+ public Term Term
+ {
+ get
+ {
+ return term;
+ }
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.DocIdSet getDocIdSet(org.apache.lucene.index.AtomicReaderContext context, final org.apache.lucene.util.Bits acceptDocs) throws java.io.IOException
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+ public override DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs)
+ {
+ Terms terms = context.reader().terms(term.field());
+ if (terms == null)
+ {
+ return null;
+ }
+
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.index.TermsEnum termsEnum = terms.iterator(null);
+ TermsEnum termsEnum = terms.iterator(null);
+ if (!termsEnum.seekExact(term.bytes()))
+ {
+ return null;
+ }
+ return new DocIdSetAnonymousInnerClassHelper(this, acceptDocs, termsEnum);
+ }
+
+ private class DocIdSetAnonymousInnerClassHelper : DocIdSet
+ {
+ private readonly TermFilter outerInstance;
+
+ private Bits acceptDocs;
+ private TermsEnum termsEnum;
+
+ public DocIdSetAnonymousInnerClassHelper(TermFilter outerInstance, Bits acceptDocs, TermsEnum termsEnum)
+ {
+ this.outerInstance = outerInstance;
+ this.acceptDocs = acceptDocs;
+ this.termsEnum = termsEnum;
+ }
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.DocIdSetIterator iterator() throws java.io.IOException
+ public override DocIdSetIterator iterator()
+ {
+ return termsEnum.docs(acceptDocs, null, DocsEnum.FLAG_NONE);
+ }
+
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || this.GetType() != o.GetType())
+ {
+ return false;
+ }
+
+ TermFilter that = (TermFilter) o;
+
+ if (term != null ?!term.Equals(that.term) : that.term != null)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ return term != null ? term.GetHashCode() : 0;
+ }
+
+ public override string ToString()
+ {
+ return term.field() + ":" + term.text();
+ }
+
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/882f487d/src/Lucene.Net.Queries/TermsFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Queries/TermsFilter.cs b/src/Lucene.Net.Queries/TermsFilter.cs
new file mode 100644
index 0000000..be418fb
--- /dev/null
+++ b/src/Lucene.Net.Queries/TermsFilter.cs
@@ -0,0 +1,439 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace org.apache.lucene.queries
+{
+
+ /*
+ * 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 org.apache.lucene.index;
+ using DocIdSet = org.apache.lucene.search.DocIdSet;
+ using DocIdSetIterator = org.apache.lucene.search.DocIdSetIterator;
+ using Filter = org.apache.lucene.search.Filter;
+ using ArrayUtil = org.apache.lucene.util.ArrayUtil;
+ using Bits = org.apache.lucene.util.Bits;
+ using BytesRef = org.apache.lucene.util.BytesRef;
+ using FixedBitSet = org.apache.lucene.util.FixedBitSet;
+
+
+ /// <summary>
+ /// Constructs a filter for docs matching any of the terms added to this class.
+ /// Unlike a RangeFilter this can be used for filtering on multiple terms that are not necessarily in
+ /// a sequence. An example might be a collection of primary keys from a database query result or perhaps
+ /// a choice of "category" labels picked by the end user. As a filter, this is much faster than the
+ /// equivalent query (a BooleanQuery with many "should" TermQueries)
+ /// </summary>
+ public sealed class TermsFilter : Filter
+ {
+
+ /*
+ * this class is often used for large number of terms in a single field.
+ * to optimize for this case and to be filter-cache friendly we
+ * serialize all terms into a single byte array and store offsets
+ * in a parallel array to keep the # of object constant and speed up
+ * equals / hashcode.
+ *
+ * This adds quite a bit of complexity but allows large term filters to
+ * be efficient for GC and cache-lookups
+ */
+ private readonly int[] offsets;
+ private readonly sbyte[] termsBytes;
+ private readonly TermsAndField[] termsAndFields;
+ private readonly int hashCode_Renamed; // cached hashcode for fast cache lookups
+ private const int PRIME = 31;
+
+ /// <summary>
+ /// Creates a new <seealso cref="TermsFilter"/> from the given list. The list
+ /// can contain duplicate terms and multiple fields.
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public TermsFilter(final java.util.List<Term> terms)
+ public TermsFilter(IList<Term> terms) : this(new FieldAndTermEnumAnonymousInnerClassHelper(this, terms), terms.Count)
+ {
+ }
+
+ private class FieldAndTermEnumAnonymousInnerClassHelper : FieldAndTermEnum
+ {
+ private readonly TermsFilter outerInstance;
+
+ private IList<Term> terms;
+
+ public FieldAndTermEnumAnonymousInnerClassHelper(TermsFilter outerInstance, IList<Term> terms)
+ {
+ this.outerInstance = outerInstance;
+ this.terms = terms;
+ iter = sort(terms).GetEnumerator();
+ }
+
+ // we need to sort for deduplication and to have a common cache key
+ internal readonly IEnumerator<Term> iter;
+ public override BytesRef next()
+ {
+ if (iter.hasNext())
+ {
+ Term next = iter.next();
+ field = next.field();
+ return next.bytes();
+ }
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Creates a new <seealso cref="TermsFilter"/> from the given <seealso cref="BytesRef"/> list for
+ /// a single field.
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public TermsFilter(final String field, final java.util.List<org.apache.lucene.util.BytesRef> terms)
+ public TermsFilter(string field, IList<BytesRef> terms) : this(new FieldAndTermEnumAnonymousInnerClassHelper2(this, field, terms), terms.Count)
+ {
+ }
+
+ private class FieldAndTermEnumAnonymousInnerClassHelper2 : FieldAndTermEnum
+ {
+ private readonly TermsFilter outerInstance;
+
+ private IList<BytesRef> terms;
+
+ public FieldAndTermEnumAnonymousInnerClassHelper2(TermsFilter outerInstance, string field, IList<BytesRef> terms) : base(field)
+ {
+ this.outerInstance = outerInstance;
+ this.terms = terms;
+ iter = sort(terms).GetEnumerator();
+ }
+
+ // we need to sort for deduplication and to have a common cache key
+ internal readonly IEnumerator<BytesRef> iter;
+ public override BytesRef next()
+ {
+ if (iter.hasNext())
+ {
+ return iter.next();
+ }
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Creates a new <seealso cref="TermsFilter"/> from the given <seealso cref="BytesRef"/> array for
+ /// a single field.
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public TermsFilter(final String field, final org.apache.lucene.util.BytesRef...terms)
+ public TermsFilter(string field, params BytesRef[] terms) : this(field, Arrays.asList(terms))
+ {
+ // this ctor prevents unnecessary Term creations
+ }
+
+ /// <summary>
+ /// Creates a new <seealso cref="TermsFilter"/> from the given array. The array can
+ /// contain duplicate terms and multiple fields.
+ /// </summary>
+//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
+//ORIGINAL LINE: public TermsFilter(final Term... terms)
+ public TermsFilter(params Term[] terms) : this(Arrays.asList(terms))
+ {
+ }
+
+
+ private TermsFilter(FieldAndTermEnum iter, int length)
+ {
+ // TODO: maybe use oal.index.PrefixCodedTerms instead?
+ // If number of terms is more than a few hundred it
+ // should be a win
+
+ // TODO: we also pack terms in FieldCache/DocValues
+ // ... maybe we can refactor to share that code
+
+ // TODO: yet another option is to build the union of the terms in
+ // an automaton an call intersect on the termsenum if the density is high
+
+ int hash = 9;
+ sbyte[] serializedTerms = new sbyte[0];
+ this.offsets = new int[length + 1];
+ int lastEndOffset = 0;
+ int index = 0;
+ List<TermsAndField> termsAndFields = new List<TermsAndField>();
+ TermsAndField lastTermsAndField = null;
+ BytesRef previousTerm = null;
+ string previousField = null;
+ BytesRef currentTerm;
+ string currentField;
+ while ((currentTerm = iter.next()) != null)
+ {
+ currentField = iter.field();
+ if (currentField == null)
+ {
+ throw new System.ArgumentException("Field must not be null");
+ }
+ if (previousField != null)
+ {
+ // deduplicate
+ if (previousField.Equals(currentField))
+ {
+ if (previousTerm.bytesEquals(currentTerm))
+ {
+ continue;
+ }
+ }
+ else
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int start = lastTermsAndField == null ? 0 : lastTermsAndField.end;
+ int start = lastTermsAndField == null ? 0 : lastTermsAndField.end;
+ lastTermsAndField = new TermsAndField(start, index, previousField);
+ termsAndFields.Add(lastTermsAndField);
+ }
+ }
+ hash = PRIME * hash + currentField.GetHashCode();
+ hash = PRIME * hash + currentTerm.GetHashCode();
+ if (serializedTerms.Length < lastEndOffset + currentTerm.length)
+ {
+ serializedTerms = ArrayUtil.grow(serializedTerms, lastEndOffset + currentTerm.length);
+ }
+ Array.Copy(currentTerm.bytes, currentTerm.offset, serializedTerms, lastEndOffset, currentTerm.length);
+ offsets[index] = lastEndOffset;
+ lastEndOffset += currentTerm.length;
+ index++;
+ previousTerm = currentTerm;
+ previousField = currentField;
+ }
+ offsets[index] = lastEndOffset;
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final int start = lastTermsAndField == null ? 0 : lastTermsAndField.end;
+ int start = lastTermsAndField == null ? 0 : lastTermsAndField.end;
+ lastTermsAndField = new TermsAndField(start, index, previousField);
+ termsAndFields.Add(lastTermsAndField);
+ this.termsBytes = ArrayUtil.shrink(serializedTerms, lastEndOffset);
+ this.termsAndFields = termsAndFields.ToArray();
+ this.hashCode_Renamed = hash;
+
+ }
+
+
+//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
+//ORIGINAL LINE: @Override public org.apache.lucene.search.DocIdSet getDocIdSet(AtomicReaderContext context, org.apache.lucene.util.Bits acceptDocs) throws java.io.IOException
+ public override DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs)
+ {
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final AtomicReader reader = context.reader();
+ AtomicReader reader = context.reader();
+ FixedBitSet result = null; // lazy init if needed - no need to create a big bitset ahead of time
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final Fields fields = reader.fields();
+ Fields fields = reader.fields();
+//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
+//ORIGINAL LINE: final org.apache.lucene.util.BytesRef spare = new org.apache.lucene.util.BytesRef(this.termsBytes);
+ BytesRef spare = new BytesRef(this.termsBytes);
+ if (fields == null)
+ {
+ return result;
+ }
+ Terms terms = null;
+ TermsEnum termsEnum = null;
+ DocsEnum docs = null;
+ foreach (TermsAndField termsAndField in this.termsAndFields)
+ {
+ if ((terms = fields.terms(termsAndField.field)) != null)
+ {
+ termsEnum = terms.iterator(termsEnum); // this won't return null
+ for (int i = termsAndField.start; i < termsAndField.end; i++)
+ {
+ spare.offset = offsets[i];
+ spare.length = offsets[i + 1] - offsets[i];
+ if (termsEnum.seekExact(spare))
+ {
+ docs = termsEnum.docs(acceptDocs, docs, DocsEnum.FLAG_NONE); // no freq since we don't need them
+ if (result == null)
+ {
+ if (docs.nextDoc() != DocIdSetIterator.NO_MORE_DOCS)
+ {
+ result = new FixedBitSet(reader.maxDoc());
+ // lazy init but don't do it in the hot loop since we could read many docs
+ result.set(docs.docID());
+ }
+ }
+ while (docs.nextDoc() != DocIdSetIterator.NO_MORE_DOCS)
+ {
+ result.set(docs.docID());
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if ((obj == null) || (obj.GetType() != this.GetType()))
+ {
+ return false;
+ }
+
+ TermsFilter test = (TermsFilter) obj;
+ // first check the fields before even comparing the bytes
+ if (test.hashCode_Renamed == hashCode_Renamed && Arrays.Equals(termsAndFields, test.termsAndFields))
+ {
+ int lastOffset = termsAndFields[termsAndFields.Length - 1].end;
+ // compare offsets since we sort they must be identical
+ if (ArrayUtil.Equals(offsets, 0, test.offsets, 0, lastOffset + 1))
+ {
+ // straight byte comparison since we sort they must be identical
+ return ArrayUtil.Equals(termsBytes, 0, test.termsBytes, 0, offsets[lastOffset]);
+ }
+ }
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return hashCode_Renamed;
+ }
+
+ public override string ToString()
+ {
+ StringBuilder builder = new StringBuilder();
+ BytesRef spare = new BytesRef(termsBytes);
+ bool first = true;
+ for (int i = 0; i < termsAndFields.Length; i++)
+ {
+ TermsAndField current = termsAndFields[i];
+ for (int j = current.start; j < current.end; j++)
+ {
+ spare.offset = offsets[j];
+ spare.length = offsets[j + 1] - offsets[j];
+ if (!first)
+ {
+ builder.Append(' ');
+ }
+ first = false;
+ builder.Append(current.field).Append(':');
+ builder.Append(spare.utf8ToString());
+ }
+ }
+
+ return builder.ToString();
+ }
+
+ private sealed class TermsAndField
+ {
+ internal readonly int start;
+ internal readonly int end;
+ internal readonly string field;
+
+
+ internal TermsAndField(int start, int end, string field) : base()
+ {
+ this.start = start;
+ this.end = end;
+ this.field = field;
+ }
+
+ public override int GetHashCode()
+ {
+ const int prime = 31;
+ int result = 1;
+ result = prime * result + ((field == null) ? 0 : field.GetHashCode());
+ result = prime * result + end;
+ result = prime * result + start;
+ return result;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (this.GetType() != obj.GetType())
+ {
+ return false;
+ }
+ TermsAndField other = (TermsAndField) obj;
+ if (field == null)
+ {
+ if (other.field != null)
+ {
+ return false;
+ }
+ }
+ else if (!field.Equals(other.field))
+ {
+ return false;
+ }
+ if (end != other.end)
+ {
+ return false;
+ }
+ if (start != other.start)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+ private abstract class FieldAndTermEnum
+ {
+ protected internal string field_Renamed;
+
+ public abstract BytesRef next();
+
+ public FieldAndTermEnum()
+ {
+ }
+
+ public FieldAndTermEnum(string field)
+ {
+ this.field_Renamed = field;
+ }
+
+ public virtual string field()
+ {
+ return field_Renamed;
+ }
+ }
+
+ /*
+ * simple utility that returns the in-place sorted list
+ */
+//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
+//ORIGINAL LINE: private static <T extends Comparable<? base T>> java.util.List<T> sort(java.util.List<T> toSort)
+ private static IList<T> sort<T>(IList<T> toSort) where T : Comparable<? base T>
+ {
+ if (toSort.Count == 0)
+ {
+ throw new System.ArgumentException("no terms provided");
+ }
+ toSort.Sort();
+ return toSort;
+ }
+ }
+
+}
\ No newline at end of file