lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aro...@apache.org
Subject svn commit: r411501 [18/30] - in /incubator/lucene.net/trunk/C#/src: ./ Demo/DeleteFiles/ Demo/DemoLib/ Demo/DemoLib/HTML/ Demo/IndexFiles/ Demo/IndexHtml/ Demo/SearchFiles/ Lucene.Net/ Lucene.Net/Analysis/ Lucene.Net/Analysis/Standard/ Lucene.Net/Docu...
Date Sun, 04 Jun 2006 02:41:25 GMT
Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/DisjunctionSumScorer.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/DisjunctionSumScorer.cs?rev=411501&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/DisjunctionSumScorer.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/DisjunctionSumScorer.cs Sat Jun  3 19:41:13 2006
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ */
+
+using System;
+using PriorityQueue = Lucene.Net.Util.PriorityQueue;
+
+namespace Lucene.Net.Search
+{
+	
+	/// <summary>A Scorer for OR like queries, counterpart of Lucene's <code>ConjunctionScorer</code>.
+	/// This Scorer implements {@link Scorer#SkipTo(int)} and uses skipTo() on the given Scorers. 
+	/// </summary>
+	public class DisjunctionSumScorer : Scorer
+	{
+		/// <summary>The number of subscorers. </summary>
+		private int nrScorers;
+		
+		/// <summary>The subscorers. </summary>
+		protected internal System.Collections.IList subScorers;
+		
+		/// <summary>The minimum number of scorers that should match. </summary>
+		private int minimumNrMatchers;
+		
+		/// <summary>The scorerQueue contains all subscorers ordered by their current doc(),
+		/// with the minimum at the top.
+		/// <br>The scorerQueue is initialized the first time next() or skipTo() is called.
+		/// <br>An exhausted scorer is immediately removed from the scorerQueue.
+		/// <br>If less than the minimumNrMatchers scorers
+		/// remain in the scorerQueue next() and skipTo() return false.
+		/// <p>
+		/// After each to call to next() or skipTo()
+		/// <code>currentSumScore</code> is the total score of the current matching doc,
+		/// <code>nrMatchers</code> is the number of matching scorers,
+		/// and all scorers are after the matching doc, or are exhausted.
+		/// </summary>
+		private ScorerQueue scorerQueue = null;
+		
+		/// <summary>The document number of the current match. </summary>
+		private int currentDoc = - 1;
+		
+		/// <summary>The number of subscorers that provide the current match. </summary>
+		protected internal int nrMatchers = - 1;
+		
+		private float currentScore = System.Single.NaN;
+		
+		/// <summary>Construct a <code>DisjunctionScorer</code>.</summary>
+		/// <param name="subScorers">A collection of at least two subscorers.
+		/// </param>
+		/// <param name="minimumNrMatchers">The positive minimum number of subscorers that should
+		/// match to match this query.
+		/// <br>When <code>minimumNrMatchers</code> is bigger than
+		/// the number of <code>subScorers</code>,
+		/// no matches will be produced.
+		/// <br>When minimumNrMatchers equals the number of subScorers,
+		/// it more efficient to use <code>ConjunctionScorer</code>.
+		/// </param>
+		public DisjunctionSumScorer(System.Collections.IList subScorers, int minimumNrMatchers) : base(null)
+		{
+			
+			nrScorers = subScorers.Count;
+			
+			if (minimumNrMatchers <= 0)
+			{
+				throw new System.ArgumentException("Minimum nr of matchers must be positive");
+			}
+			if (nrScorers <= 1)
+			{
+				throw new System.ArgumentException("There must be at least 2 subScorers");
+			}
+			
+			this.minimumNrMatchers = minimumNrMatchers;
+			this.subScorers = subScorers;
+		}
+		
+		/// <summary>Construct a <code>DisjunctionScorer</code>, using one as the minimum number
+		/// of matching subscorers.
+		/// </summary>
+		public DisjunctionSumScorer(System.Collections.IList subScorers) : this(subScorers, 1)
+		{
+		}
+		
+		/// <summary>Called the first time next() or skipTo() is called to
+		/// initialize <code>scorerQueue</code>.
+		/// </summary>
+		private void  InitScorerQueue()
+		{
+			System.Collections.IEnumerator si = subScorers.GetEnumerator();
+			scorerQueue = new ScorerQueue(this, nrScorers);
+			while (si.MoveNext())
+			{
+				Scorer se = (Scorer) si.Current;
+				if (se.Next())
+				{
+					// doc() method will be used in scorerQueue.
+					scorerQueue.Insert(se);
+				}
+			}
+		}
+		
+		/// <summary>A <code>PriorityQueue</code> that orders by {@link Scorer#Doc()}. </summary>
+		private class ScorerQueue : PriorityQueue
+		{
+			private void  InitBlock(DisjunctionSumScorer enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private DisjunctionSumScorer enclosingInstance;
+			public DisjunctionSumScorer Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			internal ScorerQueue(DisjunctionSumScorer enclosingInstance, int size)
+			{
+				InitBlock(enclosingInstance);
+				Initialize(size);
+			}
+			
+			public override bool LessThan(System.Object o1, System.Object o2)
+			{
+				return ((Scorer) o1).Doc() < ((Scorer) o2).Doc();
+			}
+		}
+		
+		public override bool Next()
+		{
+			if (scorerQueue == null)
+			{
+				InitScorerQueue();
+			}
+			if (scorerQueue.Size() < minimumNrMatchers)
+			{
+				return false;
+			}
+			else
+			{
+				return AdvanceAfterCurrent();
+			}
+		}
+		
+		
+		/// <summary>Advance all subscorers after the current document determined by the
+		/// top of the <code>scorerQueue</code>.
+		/// Repeat until at least the minimum number of subscorers match on the same
+		/// document and all subscorers are after that document or are exhausted.
+		/// <br>On entry the <code>scorerQueue</code> has at least <code>minimumNrMatchers</code>
+		/// available. At least the scorer with the minimum document number will be advanced.
+		/// </summary>
+		/// <returns> true iff there is a match.
+		/// <br>In case there is a match, </code>currentDoc</code>, </code>currentSumScore</code>,
+		/// and </code>nrMatchers</code> describe the match.
+		/// 
+		/// </returns>
+		/// <todo>  Investigate whether it is possible to use skipTo() when </todo>
+		/// <summary> the minimum number of matchers is bigger than one, ie. try and use the
+		/// character of ConjunctionScorer for the minimum number of matchers.
+		/// </summary>
+		protected internal virtual bool AdvanceAfterCurrent()
+		{
+			do 
+			{
+				// repeat until minimum nr of matchers
+				Scorer top = (Scorer) scorerQueue.Top();
+				currentDoc = top.Doc();
+				currentScore = top.Score();
+				nrMatchers = 1;
+				do 
+				{
+					// Until all subscorers are after currentDoc
+					if (top.Next())
+					{
+						scorerQueue.AdjustTop();
+					}
+					else
+					{
+						scorerQueue.Pop();
+						if (scorerQueue.Size() < (minimumNrMatchers - nrMatchers))
+						{
+							// Not enough subscorers left for a match on this document,
+							// and also no more chance of any further match.
+							return false;
+						}
+						if (scorerQueue.Size() == 0)
+						{
+							break; // nothing more to advance, check for last match.
+						}
+					}
+					top = (Scorer) scorerQueue.Top();
+					if (top.Doc() != currentDoc)
+					{
+						break; // All remaining subscorers are after currentDoc.
+					}
+					else
+					{
+						currentScore += top.Score();
+						nrMatchers++;
+					}
+				}
+				while (true);
+				
+				if (nrMatchers >= minimumNrMatchers)
+				{
+					return true;
+				}
+				else if (scorerQueue.Size() < minimumNrMatchers)
+				{
+					return false;
+				}
+			}
+			while (true);
+		}
+		
+		/// <summary>Returns the score of the current document matching the query.
+		/// Initially invalid, until {@link #Next()} is called the first time.
+		/// </summary>
+		public override float Score()
+		{
+			return currentScore;
+		}
+		
+		public override int Doc()
+		{
+			return currentDoc;
+		}
+		
+		/// <summary>Returns the number of subscorers matching the current document.
+		/// Initially invalid, until {@link #Next()} is called the first time.
+		/// </summary>
+		public virtual int NrMatchers()
+		{
+			return nrMatchers;
+		}
+		
+		/// <summary>Skips to the first match beyond the current whose document number is
+		/// greater than or equal to a given target.
+		/// <br>When this method is used the {@link #Explain(int)} method should not be used.
+		/// <br>The implementation uses the skipTo() method on the subscorers.
+		/// </summary>
+		/// <param name="target">The target document number.
+		/// </param>
+		/// <returns> true iff there is such a match.
+		/// </returns>
+		public override bool SkipTo(int target)
+		{
+			if (scorerQueue == null)
+			{
+				InitScorerQueue();
+			}
+			if (scorerQueue.Size() < minimumNrMatchers)
+			{
+				return false;
+			}
+			if (target <= currentDoc)
+			{
+				target = currentDoc + 1;
+			}
+			do 
+			{
+				Scorer top = (Scorer) scorerQueue.Top();
+				if (top.Doc() >= target)
+				{
+					return AdvanceAfterCurrent();
+				}
+				else if (top.SkipTo(target))
+				{
+					scorerQueue.AdjustTop();
+				}
+				else
+				{
+					scorerQueue.Pop();
+					if (scorerQueue.Size() < minimumNrMatchers)
+					{
+						return false;
+					}
+				}
+			}
+			while (true);
+		}
+		
+		/// <summary>Gives and explanation for the score of a given document.</summary>
+		/// <todo>  Show the resulting score. See BooleanScorer.explain() on how to do this. </todo>
+		public override Explanation Explain(int doc)
+		{
+			Explanation res = new Explanation();
+			res.SetDescription("At least " + minimumNrMatchers + " of");
+			System.Collections.IEnumerator ssi = subScorers.GetEnumerator();
+			while (ssi.MoveNext())
+			{
+				res.AddDetail(((Scorer) ssi.Current).Explain(doc));
+			}
+			return res;
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/ExactPhraseScorer.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/ExactPhraseScorer.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/ExactPhraseScorer.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/ExactPhraseScorer.cs Sat Jun  3 19:41:13 2006
@@ -13,16 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using Lucene.Net.Index;
+
 namespace Lucene.Net.Search
 {
 	
-	sealed class ExactPhraseScorer:PhraseScorer
+	sealed class ExactPhraseScorer : PhraseScorer
 	{
 		
-		internal ExactPhraseScorer(Weight weight, TermPositions[] tps, int[] positions, Similarity similarity, byte[] norms) : 
-            base(weight, tps, positions, similarity, norms)
+		internal ExactPhraseScorer(Weight weight, TermPositions[] tps, int[] positions, Similarity similarity, byte[] norms) : base(weight, tps, positions, similarity, norms)
 		{
 		}
 		

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Explanation.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Explanation.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Explanation.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Explanation.cs Sat Jun  3 19:41:13 2006
@@ -13,7 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
+
 namespace Lucene.Net.Search
 {
 	
@@ -62,7 +64,7 @@
 		{
 			if (details == null)
 				return null;
-            return (Explanation[]) details.ToArray(typeof(Explanation));
+			return (Explanation[]) details.ToArray(typeof(Explanation));
 		}
 		
 		/// <summary>Adds a sub-node to this explanation node. </summary>

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCache.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FieldCache.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCache.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCache.cs Sat Jun  3 19:41:13 2006
@@ -13,8 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using IndexReader = Lucene.Net.Index.IndexReader;
+
 namespace Lucene.Net.Search
 {
 	
@@ -27,7 +29,7 @@
 	/// </author>
 	/// <since>   lucene 1.4
 	/// </since>
-	/// <version>  $Id: FieldCache.java,v 1.1 2004/05/19 23:05:27 tjones Exp $
+	/// <version>  $Id: FieldCache.java 179605 2005-06-02 16:48:40Z cutting $
 	/// </version>
 	/// <summary>Expert: Stores term text values and document ordering data. </summary>
 	public class StringIndex
@@ -47,7 +49,7 @@
 		}
 	}
 	public struct FieldCache_Fields
-    {
+	{
 		/// <summary>Indicator for StringIndex values in the cache. </summary>
 		// NOTE: the value assigned to this constant must not be
 		// the same as any of those in SortField!!
@@ -64,55 +66,87 @@
 		
 		
 		/// <summary>Checks the internal cache for an appropriate entry, and if none is
-		/// found, reads the terms in <code>Field</code> as integers and returns an array
+		/// found, reads the terms in <code>field</code> as integers and returns an array
 		/// of size <code>reader.maxDoc()</code> of the value each document
-		/// has in the given Field.
+		/// has in the given field.
 		/// </summary>
-		/// <param name="reader"> Used to get Field values.
+		/// <param name="reader"> Used to get field values.
 		/// </param>
-		/// <param name="Field">  Which Field contains the integers.
+		/// <param name="field">  Which field contains the integers.
 		/// </param>
-		/// <returns> The values in the given Field for each document.
+		/// <returns> The values in the given field for each document.
 		/// </returns>
 		/// <throws>  IOException  If any error occurs. </throws>
 		int[] GetInts(IndexReader reader, System.String field);
 		
+		/// <summary>Checks the internal cache for an appropriate entry, and if none is found,
+		/// reads the terms in <code>field</code> as integers and returns an array of
+		/// size <code>reader.maxDoc()</code> of the value each document has in the
+		/// given field.
+		/// </summary>
+		/// <param name="reader"> Used to get field values.
+		/// </param>
+		/// <param name="field">  Which field contains the integers.
+		/// </param>
+		/// <param name="parser"> Computes integer for string values.
+		/// </param>
+		/// <returns> The values in the given field for each document.
+		/// </returns>
+		/// <throws>  IOException  If any error occurs. </throws>
+		int[] GetInts(IndexReader reader, System.String field, IntParser parser);
+		
 		/// <summary>Checks the internal cache for an appropriate entry, and if
-		/// none is found, reads the terms in <code>Field</code> as floats and returns an array
+		/// none is found, reads the terms in <code>field</code> as floats and returns an array
 		/// of size <code>reader.maxDoc()</code> of the value each document
-		/// has in the given Field.
+		/// has in the given field.
 		/// </summary>
-		/// <param name="reader"> Used to get Field values.
+		/// <param name="reader"> Used to get field values.
 		/// </param>
-		/// <param name="Field">  Which Field contains the floats.
+		/// <param name="field">  Which field contains the floats.
 		/// </param>
-		/// <returns> The values in the given Field for each document.
+		/// <returns> The values in the given field for each document.
 		/// </returns>
 		/// <throws>  IOException  If any error occurs. </throws>
 		float[] GetFloats(IndexReader reader, System.String field);
 		
+		/// <summary>Checks the internal cache for an appropriate entry, and if
+		/// none is found, reads the terms in <code>field</code> as floats and returns an array
+		/// of size <code>reader.maxDoc()</code> of the value each document
+		/// has in the given field.
+		/// </summary>
+		/// <param name="reader"> Used to get field values.
+		/// </param>
+		/// <param name="field">  Which field contains the floats.
+		/// </param>
+		/// <param name="parser"> Computes float for string values.
+		/// </param>
+		/// <returns> The values in the given field for each document.
+		/// </returns>
+		/// <throws>  IOException  If any error occurs. </throws>
+		float[] GetFloats(IndexReader reader, System.String field, FloatParser parser);
+		
 		/// <summary>Checks the internal cache for an appropriate entry, and if none
-		/// is found, reads the term values in <code>Field</code> and returns an array
+		/// is found, reads the term values in <code>field</code> and returns an array
 		/// of size <code>reader.maxDoc()</code> containing the value each document
-		/// has in the given Field.
+		/// has in the given field.
 		/// </summary>
-		/// <param name="reader"> Used to get Field values.
+		/// <param name="reader"> Used to get field values.
 		/// </param>
-		/// <param name="Field">  Which Field contains the strings.
+		/// <param name="field">  Which field contains the strings.
 		/// </param>
-		/// <returns> The values in the given Field for each document.
+		/// <returns> The values in the given field for each document.
 		/// </returns>
 		/// <throws>  IOException  If any error occurs. </throws>
 		System.String[] GetStrings(IndexReader reader, System.String field);
 		
 		/// <summary>Checks the internal cache for an appropriate entry, and if none
-		/// is found reads the term values in <code>Field</code> and returns
+		/// is found reads the term values in <code>field</code> and returns
 		/// an array of them in natural order, along with an array telling
 		/// which element in the term array each document uses.
 		/// </summary>
-		/// <param name="reader"> Used to get Field values.
+		/// <param name="reader"> Used to get field values.
 		/// </param>
-		/// <param name="Field">  Which Field contains the strings.
+		/// <param name="field">  Which field contains the strings.
 		/// </param>
 		/// <returns> Array of terms and index into the array for each document.
 		/// </returns>
@@ -120,15 +154,15 @@
 		StringIndex GetStringIndex(IndexReader reader, System.String field);
 		
 		/// <summary>Checks the internal cache for an appropriate entry, and if
-		/// none is found reads <code>Field</code> to see if it contains integers, floats
+		/// none is found reads <code>field</code> to see if it contains integers, floats
 		/// or strings, and then calls one of the other methods in this class to get the
 		/// values.  For string values, a StringIndex is returned.  After
 		/// calling this method, there is an entry in the cache for both
 		/// type <code>AUTO</code> and the actual found type.
 		/// </summary>
-		/// <param name="reader"> Used to get Field values.
+		/// <param name="reader"> Used to get field values.
 		/// </param>
-		/// <param name="Field">  Which Field contains the values.
+		/// <param name="field">  Which field contains the values.
 		/// </param>
 		/// <returns> int[], float[] or StringIndex.
 		/// </returns>
@@ -136,14 +170,14 @@
 		System.Object GetAuto(IndexReader reader, System.String field);
 		
 		/// <summary>Checks the internal cache for an appropriate entry, and if none
-		/// is found reads the terms out of <code>Field</code> and calls the given SortComparator
+		/// is found reads the terms out of <code>field</code> and calls the given SortComparator
 		/// to get the sort values.  A hit in the cache will happen if <code>reader</code>,
-		/// <code>Field</code>, and <code>comparator</code> are the same (using <code>equals()</code>)
+		/// <code>field</code>, and <code>comparator</code> are the same (using <code>equals()</code>)
 		/// as a previous call to this method.
 		/// </summary>
-		/// <param name="reader"> Used to get Field values.
+		/// <param name="reader"> Used to get field values.
 		/// </param>
-		/// <param name="Field">  Which Field contains the values.
+		/// <param name="field">  Which field contains the values.
 		/// </param>
 		/// <param name="comparator">Used to convert terms into something to sort by.
 		/// </param>
@@ -151,5 +185,23 @@
 		/// </returns>
 		/// <throws>  IOException  If any error occurs. </throws>
 		System.IComparable[] GetCustom(IndexReader reader, System.String field, SortComparator comparator);
+	}
+
+    /// <summary>Interface to parse ints from document fields.</summary>
+	/// <seealso cref="GetInts(IndexReader, String, IntParser)">
+	/// </seealso>
+	public interface IntParser
+	{
+		/// <summary>Return an integer representation of this field's value. </summary>
+		int ParseInt(System.String string_Renamed);
+	}
+
+    /// <summary>Interface to parse floats from document fields.</summary>
+	/// <seealso cref="GetFloats(IndexReader, String, FloatParser)">
+	/// </seealso>
+	public interface FloatParser
+	{
+		/// <summary>Return an float representation of this field's value. </summary>
+		float ParseFloat(System.String string_Renamed);
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCacheImpl.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FieldCacheImpl.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCacheImpl.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCacheImpl.cs Sat Jun  3 19:41:13 2006
@@ -13,11 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using IndexReader = Lucene.Net.Index.IndexReader;
 using Term = Lucene.Net.Index.Term;
 using TermDocs = Lucene.Net.Index.TermDocs;
 using TermEnum = Lucene.Net.Index.TermEnum;
+using StringIndex = Lucene.Net.Search.StringIndex;
+
 namespace Lucene.Net.Search
 {
 	
@@ -31,10 +34,24 @@
 	/// </author>
 	/// <since>   lucene 1.4
 	/// </since>
-    /// <version>  $Id: FieldCacheImpl.java,v 1.3.2.1 2004/09/30 19:10:26 dnaber Exp $
-    /// </version>
+	/// <version>  $Id: FieldCacheImpl.java 331964 2005-11-09 06:44:10Z otis $
+	/// </version>
 	class FieldCacheImpl : FieldCache
 	{
+		public class AnonymousClassIntParser : IntParser
+		{
+			public virtual int ParseInt(System.String value_Renamed)
+			{
+				return System.Int32.Parse(value_Renamed);
+			}
+		}
+		public class AnonymousClassFloatParser : FloatParser
+		{
+			public virtual float ParseFloat(System.String value_Renamed)
+			{
+				return System.Single.Parse(value_Renamed);
+			}
+		}
 		
 		/// <summary>Expert: Every key in the internal cache is of this type. </summary>
 		internal class Entry
@@ -46,18 +63,18 @@
 			/// <summary>Creates one of these objects. </summary>
 			internal Entry(System.String field, int type)
 			{
-                this.field = String.Intern(field);
-                this.type = type;
-                this.custom = null;
-            }
+				this.field = String.Intern(field);
+				this.type = type;
+				this.custom = null;
+			}
 			
 			/// <summary>Creates one of these objects for a custom comparator. </summary>
 			internal Entry(System.String field, System.Object custom)
 			{
-                this.field = String.Intern(field);
-                this.type = SortField.CUSTOM;
-                this.custom = custom;
-            }
+				this.field = String.Intern(field);
+				this.type = SortField.CUSTOM;
+				this.custom = custom;
+			}
 			
 			/// <summary>Two of these are equal iff they reference the same field and type. </summary>
 			public  override bool Equals(System.Object o)
@@ -84,10 +101,13 @@
 			/// <summary>Composes a hashcode based on the field and type. </summary>
 			public override int GetHashCode()
 			{
-				return field.GetHashCode() ^ type ^ (custom == null ? 0 : custom.GetHashCode());
+				return field.GetHashCode() ^ type ^ (custom == null?0:custom.GetHashCode());
 			}
 		}
 		
+		private static readonly IntParser INT_PARSER;
+		
+		private static readonly FloatParser FLOAT_PARSER;
 		
 		/// <summary>The internal cache. Maps Entry to array of interpreted term values. *</summary>
 		internal System.Collections.IDictionary cache = new System.Collections.Hashtable();
@@ -98,11 +118,11 @@
 			Entry entry = new Entry(field, type);
 			lock (this)
 			{
-                System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
-                if (readerCache == null)
-                    return null;
-                return readerCache[entry];
-            }
+				System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
+				if (readerCache == null)
+					return null;
+				return readerCache[entry];
+			}
 		}
 		
 		/// <summary>See if a custom object is in the cache. </summary>
@@ -111,11 +131,11 @@
 			Entry entry = new Entry(field, comparer);
 			lock (this)
 			{
-                System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
-                if (readerCache == null)
-                    return null;
-                return readerCache[entry];
-            }
+				System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
+				if (readerCache == null)
+					return null;
+				return readerCache[entry];
+			}
 		}
 		
 		/// <summary>Put an object into the cache. </summary>
@@ -124,17 +144,17 @@
 			Entry entry = new Entry(field, type);
 			lock (this)
 			{
-                System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
-                if (readerCache == null)
-                {
-                    readerCache = new System.Collections.Hashtable();
-                    cache[reader] = readerCache;
-                }
-                System.Object tempObject;
-                tempObject = readerCache[entry];
-                readerCache[entry] = value_Renamed;
-                return tempObject;
-            }
+				System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
+				if (readerCache == null)
+				{
+					readerCache = new System.Collections.Hashtable();
+					cache[reader] = readerCache;
+				}
+				System.Object tempObject;
+				tempObject = readerCache[entry];
+				readerCache[entry] = value_Renamed;
+				return tempObject;
+			}
 		}
 		
 		/// <summary>Put a custom object into the cache. </summary>
@@ -143,24 +163,30 @@
 			Entry entry = new Entry(field, comparer);
 			lock (this)
 			{
-                System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
-                if (readerCache == null)
-                {
-                    readerCache = new System.Collections.Hashtable();
-                    cache[reader] = readerCache;
-                }
-                System.Object tempObject;
-                tempObject = readerCache[entry];
-                readerCache[entry] = value_Renamed;
-                return tempObject;
-            }
+				System.Collections.Hashtable readerCache = (System.Collections.Hashtable) cache[reader];
+				if (readerCache == null)
+				{
+					readerCache = new System.Collections.Hashtable();
+					cache[reader] = readerCache;
+				}
+				System.Object tempObject;
+				tempObject = readerCache[entry];
+				readerCache[entry] = value_Renamed;
+				return tempObject;
+			}
 		}
 		
 		// inherit javadocs
 		public virtual int[] GetInts(IndexReader reader, System.String field)
 		{
+			return GetInts(reader, field, INT_PARSER);
+		}
+		
+		// inherit javadocs
+		public virtual int[] GetInts(IndexReader reader, System.String field, IntParser parser)
+		{
 			field = String.Intern(field);
-			System.Object ret = Lookup(reader, field, SortField.INT);
+			System.Object ret = Lookup(reader, field, parser);
 			if (ret == null)
 			{
 				int[] retArray = new int[reader.MaxDoc()];
@@ -172,14 +198,14 @@
 					{
 						if (termEnum.Term() == null)
 						{
-							throw new System.SystemException("no terms in Field " + field);
+							throw new System.SystemException("no terms in field " + field);
 						}
 						do 
 						{
 							Term term = termEnum.Term();
 							if (term.Field() != field)
 								break;
-							int termval = System.Int32.Parse(term.Text());
+							int termval = parser.ParseInt(term.Text());
 							termDocs.Seek(termEnum);
 							while (termDocs.Next())
 							{
@@ -194,7 +220,7 @@
 						termEnum.Close();
 					}
 				}
-				Store(reader, field, SortField.INT, retArray);
+				Store(reader, field, parser, retArray);
 				return retArray;
 			}
 			return (int[]) ret;
@@ -203,8 +229,14 @@
 		// inherit javadocs
 		public virtual float[] GetFloats(IndexReader reader, System.String field)
 		{
+			return GetFloats(reader, field, FLOAT_PARSER);
+		}
+		
+		// inherit javadocs
+		public virtual float[] GetFloats(IndexReader reader, System.String field, FloatParser parser)
+		{
 			field = String.Intern(field);
-			System.Object ret = Lookup(reader, field, SortField.FLOAT);
+			System.Object ret = Lookup(reader, field, parser);
 			if (ret == null)
 			{
 				float[] retArray = new float[reader.MaxDoc()];
@@ -212,41 +244,33 @@
 				{
 					TermDocs termDocs = reader.TermDocs();
 					TermEnum termEnum = reader.Terms(new Term(field, ""));
-                    try
-                    {
-                        if (termEnum.Term() == null)
-                        {
-                            throw new System.SystemException("no terms in Field " + field);
-                        }
-                        do 
-                        {
-                            Term term = termEnum.Term();
-                            if (term.Field() != field)
-                                break;
-                            float termval;
-                            try
-                            {
-                                termval = SupportClass.Single.Parse(term.Text());
-                            }
-                            catch (Exception e)
-                            {
-                                termval = 0;
-                            }
-                            termDocs.Seek(termEnum);
-                            while (termDocs.Next())
-                            {
-                                retArray[termDocs.Doc()] = termval;
-                            }
-                        }
-                        while (termEnum.Next());
-                    }
-                    finally
-                    {
-                        termDocs.Close();
-                        termEnum.Close();
-                    }
+					try
+					{
+						if (termEnum.Term() == null)
+						{
+							throw new System.SystemException("no terms in field " + field);
+						}
+						do 
+						{
+							Term term = termEnum.Term();
+							if (term.Field() != field)
+								break;
+							float termval = parser.ParseFloat(term.Text());
+							termDocs.Seek(termEnum);
+							while (termDocs.Next())
+							{
+								retArray[termDocs.Doc()] = termval;
+							}
+						}
+						while (termEnum.Next());
+					}
+					finally
+					{
+						termDocs.Close();
+						termEnum.Close();
+					}
 				}
-				Store(reader, field, SortField.FLOAT, retArray);
+				Store(reader, field, parser, retArray);
 				return retArray;
 			}
 			return (float[]) ret;
@@ -268,7 +292,7 @@
 					{
 						if (termEnum.Term() == null)
 						{
-							throw new System.SystemException("no terms in Field " + field);
+							throw new System.SystemException("no terms in field " + field);
 						}
 						do 
 						{
@@ -311,7 +335,7 @@
 					TermEnum termEnum = reader.Terms(new Term(field, ""));
 					int t = 0; // current term number
 					
-					// an entry for documents that have no terms in this Field
+					// an entry for documents that have no terms in this field
 					// should a document with no terms be at top or bottom?
 					// this puts them at the top - if it is changed, FieldDocSortedHitQueue
 					// needs to change as well.
@@ -321,7 +345,7 @@
 					{
 						if (termEnum.Term() == null)
 						{
-							throw new System.SystemException("no terms in Field " + field);
+							throw new System.SystemException("no terms in field " + field);
 						}
 						do 
 						{
@@ -332,7 +356,7 @@
 							// store term text
 							// we expect that there is at most one term per document
 							if (t >= mterms.Length)
-								throw new System.SystemException("there are more terms than documents in Field \"" + field + "\"");
+								throw new System.SystemException("there are more terms than " + "documents in field \"" + field + "\", but it's impossible to sort on " + "tokenized fields");
 							mterms[t] = term.Text();
 							
 							termDocs.Seek(termEnum);
@@ -373,13 +397,13 @@
 			return (StringIndex) ret;
 		}
 		
-		/// <summary>The pattern used to detect integer values in a Field </summary>
+		/// <summary>The pattern used to detect integer values in a field </summary>
 		/// <summary>removed for java 1.3 compatibility
 		/// protected static final Pattern pIntegers = Pattern.compile ("[0-9\\-]+");
 		/// 
 		/// </summary>
 		
-		/// <summary>The pattern used to detect float values in a Field </summary>
+		/// <summary>The pattern used to detect float values in a field </summary>
 		/// <summary> removed for java 1.3 compatibility
 		/// protected static final Object pFloats = Pattern.compile ("[0-9+\\-\\.eEfFdD]+");
 		/// </summary>
@@ -397,18 +421,21 @@
 					Term term = enumerator.Term();
 					if (term == null)
 					{
-						throw new System.SystemException("no terms in Field " + field + " - cannot determine sort type");
+						throw new System.SystemException("no terms in field " + field + " - cannot determine sort type");
 					}
 					if (term.Field() == field)
 					{
 						System.String termtext = term.Text().Trim();
 						
-						/// <summary> Java 1.4 level code:
-						/// if (pIntegers.matcher(termtext).matches())
-						/// return IntegerSortedHitQueue.comparator (reader, enumerator, Field);
-						/// else if (pFloats.matcher(termtext).matches())
-						/// return FloatSortedHitQueue.comparator (reader, enumerator, Field);
-						/// </summary>
+						/**
+						* Java 1.4 level code:
+						
+						if (pIntegers.matcher(termtext).matches())
+						return IntegerSortedHitQueue.comparator (reader, enumerator, field);
+						
+						else if (pFloats.matcher(termtext).matches())
+						return FloatSortedHitQueue.comparator (reader, enumerator, field);
+						*/
 						
 						// Java 1.3 level code:
 						try
@@ -435,7 +462,7 @@
 					}
 					else
 					{
-						throw new System.SystemException("Field \"" + field + "\" does not appear to be indexed");
+						throw new System.SystemException("field \"" + field + "\" does not appear to be indexed");
 					}
 				}
 				finally
@@ -462,7 +489,7 @@
 					{
 						if (termEnum.Term() == null)
 						{
-							throw new System.SystemException("no terms in Field " + field);
+							throw new System.SystemException("no terms in field " + field);
 						}
 						do 
 						{
@@ -484,10 +511,15 @@
 						termEnum.Close();
 					}
 				}
-				Store(reader, field, SortField.CUSTOM, retArray);
+				Store(reader, field, comparator, retArray);
 				return retArray;
 			}
 			return (System.IComparable[]) ret;
+		}
+		static FieldCacheImpl()
+		{
+			INT_PARSER = new AnonymousClassIntParser();
+			FLOAT_PARSER = new AnonymousClassFloatParser();
 		}
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldDoc.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FieldDoc.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldDoc.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldDoc.cs Sat Jun  3 19:41:13 2006
@@ -13,20 +13,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
+
 namespace Lucene.Net.Search
 {
+	
+	
 	/// <summary> Expert: A ScoreDoc which also contains information about
 	/// how to sort the referenced document.  In addition to the
 	/// document number and score, this object contains an array
-	/// of values for the document from the Field(s) used to sort.
+	/// of values for the document from the field(s) used to sort.
 	/// For example, if the sort criteria was to sort by fields
 	/// "a", "b" then "c", the <code>fields</code> object array
 	/// will have three elements, corresponding respectively to
 	/// the term values for the document in fields "a", "b" and "c".
 	/// The class of each element in the array will be either
 	/// Integer, Float or String depending on the type of values
-	/// in the terms of each Field.
+	/// in the terms of each field.
 	/// 
 	/// <p>Created: Feb 11, 2004 1:23:38 PM
 	/// 
@@ -35,7 +39,7 @@
 	/// </author>
 	/// <since>   lucene 1.4
 	/// </since>
-	/// <version>  $Id: FieldDoc.java,v 1.4 2004/04/22 22:23:14 tjones Exp $
+	/// <version>  $Id: FieldDoc.java 164865 2005-04-26 19:30:20Z cutting $
 	/// </version>
 	/// <seealso cref="ScoreDoc">
 	/// </seealso>
@@ -48,11 +52,11 @@
 		/// <summary>Expert: The values which are used to sort the referenced document.
 		/// The order of these will match the original sort criteria given by a
 		/// Sort object.  Each Object will be either an Integer, Float or String,
-		/// depending on the type of values in the terms of the original Field.
+		/// depending on the type of values in the terms of the original field.
 		/// </summary>
 		/// <seealso cref="Sort">
 		/// </seealso>
-		/// <seealso cref="Searchable#Search(Query,Filter,int,Sort)">
+		/// <seealso cref="Searcher.Search(Query,Filter,int,Sort)">
 		/// </seealso>
 		public System.IComparable[] fields;
 		

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldDocSortedHitQueue.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FieldDocSortedHitQueue.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldDocSortedHitQueue.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldDocSortedHitQueue.cs Sat Jun  3 19:41:13 2006
@@ -13,8 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using PriorityQueue = Lucene.Net.Util.PriorityQueue;
+
 namespace Lucene.Net.Search
 {
 	
@@ -28,7 +30,7 @@
 	/// </author>
 	/// <since>   lucene 1.4
 	/// </since>
-	/// <version>  $Id: FieldDocSortedHitQueue.java,v 1.5 2004/05/24 22:51:42 tjones Exp $
+	/// <version>  $Id: FieldDocSortedHitQueue.java 332431 2005-11-11 03:13:10Z yonik $
 	/// </version>
 	class FieldDocSortedHitQueue : PriorityQueue
 	{
@@ -47,7 +49,6 @@
 		/// </param>
 		/// <param name="size"> The number of hits to retain.  Must be greater than zero.
 		/// </param>
-		/// <throws>  IOException </throws>
 		internal FieldDocSortedHitQueue(SortField[] fields, int size)
 		{
 			this.fields = fields;
@@ -62,7 +63,7 @@
 		/// type until the values come back.  The fields can only be set once.
 		/// This method is thread safe.
 		/// </summary>
-		/// <param name="">fields
+		/// <param name="fields">
 		/// </param>
 		internal virtual void  SetFields(SortField[] fields)
 		{
@@ -122,146 +123,86 @@
 			for (int i = 0; i < n && c == 0; ++i)
 			{
 				int type = fields[i].GetType();
-				if (fields[i].GetReverse())
+				switch (type)
 				{
-					switch (type)
-					{
-						
-						case SortField.SCORE: 
-							float r1 = (float) ((System.Single) docA.fields[i]);
-							float r2 = (float) ((System.Single) docB.fields[i]);
-							if (r1 < r2)
-								c = - 1;
-							if (r1 > r2)
-								c = 1;
-							break;
-						
-						case SortField.DOC: 
-						case SortField.INT: 
-							int i1 = ((System.Int32) docA.fields[i]);
-							int i2 = ((System.Int32) docB.fields[i]);
-							if (i1 > i2)
-								c = - 1;
-							if (i1 < i2)
-								c = 1;
-							break;
-						
-						case SortField.STRING: 
-							System.String s1 = (System.String) docA.fields[i];
-							System.String s2 = (System.String) docB.fields[i];
-							if (s2 == null)
-								c = - 1;
-							// could be null if there are
-							else if (s1 == null)
-								c = 1;
-							// no terms in the given Field
-							else if (fields[i].GetLocale() == null)
-							{
-								c = String.CompareOrdinal(s2, s1);
-							}
-							else
-							{
-								c = collators[i].Compare(s2.ToString(), s1.ToString());
-							}
-							break;
-						
-						case SortField.FLOAT: 
-							float f1 = (float) ((System.Single) docA.fields[i]);
-							float f2 = (float) ((System.Single) docB.fields[i]);
-							if (f1 > f2)
-								c = - 1;
-							if (f1 < f2)
-								c = 1;
-							break;
-						
-						case SortField.CUSTOM: 
-							c = docB.fields[i].CompareTo(docA.fields[i]);
-							break;
-						
-						case SortField.AUTO: 
-							// we cannot handle this - even if we determine the type of object (Float or
-							// Integer), we don't necessarily know how to compare them (both SCORE and
-							// FLOAT both contain floats, but are sorted opposite of each other). Before
-							// we get here, each AUTO should have been replaced with its actual value.
-							throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");
-						
-						default: 
-							throw new System.SystemException("invalid SortField type: " + type);
-						
-					}
+					
+					case SortField.SCORE: 
+						float r1 = (float) ((System.Single) docA.fields[i]);
+						float r2 = (float) ((System.Single) docB.fields[i]);
+						if (r1 > r2)
+							c = - 1;
+						if (r1 < r2)
+							c = 1;
+						break;
+					
+					case SortField.DOC: 
+					case SortField.INT: 
+						int i1 = ((System.Int32) docA.fields[i]);
+						int i2 = ((System.Int32) docB.fields[i]);
+						if (i1 < i2)
+							c = - 1;
+						if (i1 > i2)
+							c = 1;
+						break;
+					
+					case SortField.STRING: 
+						System.String s1 = (System.String) docA.fields[i];
+						System.String s2 = (System.String) docB.fields[i];
+						// null values need to be sorted first, because of how FieldCache.getStringIndex()
+						// works - in that routine, any documents without a value in the given field are
+						// put first.  If both are null, the next SortField is used
+						if (s1 == null)
+							c = (s2 == null)?0:- 1;
+						else if (s2 == null)
+							c = 1;
+						// 
+						else if (fields[i].GetLocale() == null)
+						{
+							c = String.CompareOrdinal(s1, s2);
+						}
+						else
+						{
+							//UPGRADE_TODO: The equivalent in .NET for method 'java.text.Collator.compare' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
+							c = collators[i].Compare(s1.ToString(), s2.ToString());
+						}
+						break;
+					
+					case SortField.FLOAT: 
+						//UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
+						float f1 = (float) ((System.Single) docA.fields[i]);
+						//UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
+						float f2 = (float) ((System.Single) docB.fields[i]);
+						if (f1 < f2)
+							c = - 1;
+						if (f1 > f2)
+							c = 1;
+						break;
+					
+					case SortField.CUSTOM: 
+						c = docA.fields[i].CompareTo(docB.fields[i]);
+						break;
+					
+					case SortField.AUTO: 
+						// we cannot handle this - even if we determine the type of object (Float or
+						// Integer), we don't necessarily know how to compare them (both SCORE and
+						// FLOAT contain floats, but are sorted opposite of each other). Before
+						// we get here, each AUTO should have been replaced with its actual value.
+						throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");
+					
+					default: 
+						throw new System.SystemException("invalid SortField type: " + type);
+					
 				}
-				else
+				if (fields[i].GetReverse())
 				{
-					switch (type)
-					{
-						
-						case SortField.SCORE: 
-							float r1 = (float) ((System.Single) docA.fields[i]);
-							float r2 = (float) ((System.Single) docB.fields[i]);
-							if (r1 > r2)
-								c = - 1;
-							if (r1 < r2)
-								c = 1;
-							break;
-						
-						case SortField.DOC: 
-						case SortField.INT: 
-							int i1 = ((System.Int32) docA.fields[i]);
-							int i2 = ((System.Int32) docB.fields[i]);
-							if (i1 < i2)
-								c = - 1;
-							if (i1 > i2)
-								c = 1;
-							break;
-						
-						case SortField.STRING: 
-							System.String s1 = (System.String) docA.fields[i];
-							System.String s2 = (System.String) docB.fields[i];
-							// null values need to be sorted first, because of how FieldCache.getStringIndex()
-							// works - in that routine, any documents without a value in the given Field are
-							// put first.
-							if (s1 == null)
-								c = - 1;
-							// could be null if there are
-							else if (s2 == null)
-								c = 1;
-							// no terms in the given Field
-							else if (fields[i].GetLocale() == null)
-							{
-								c = String.CompareOrdinal(s1, s2);
-							}
-							else
-							{
-								c = collators[i].Compare(s1.ToString(), s2.ToString());
-							}
-							break;
-						
-						case SortField.FLOAT: 
-							float f1 = (float) ((System.Single) docA.fields[i]);
-							float f2 = (float) ((System.Single) docB.fields[i]);
-							if (f1 < f2)
-								c = - 1;
-							if (f1 > f2)
-								c = 1;
-							break;
-						
-						case SortField.CUSTOM: 
-							c = docA.fields[i].CompareTo(docB.fields[i]);
-							break;
-						
-						case SortField.AUTO: 
-							// we cannot handle this - even if we determine the type of object (Float or
-							// Integer), we don't necessarily know how to compare them (both SCORE and
-							// FLOAT both contain floats, but are sorted opposite of each other). Before
-							// we get here, each AUTO should have been replaced with its actual value.
-							throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");
-						
-						default: 
-							throw new System.SystemException("invalid SortField type: " + type);
-						
-					}
+					c = - c;
 				}
 			}
+			
+			// avoid random sort order that could lead to duplicates (bug #31241):
+			if (c == 0)
+				return docA.doc > docB.doc;
+			
 			return c > 0;
 		}
 	}

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldSortedHitQueue.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FieldSortedHitQueue.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldSortedHitQueue.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldSortedHitQueue.cs Sat Jun  3 19:41:13 2006
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using IndexReader = Lucene.Net.Index.IndexReader;
 using PriorityQueue = Lucene.Net.Util.PriorityQueue;
+
 namespace Lucene.Net.Search
 {
 	
-	/// <summary> Expert: A hit queue for sorting by hits by terms in more than one Field.
+	/// <summary> Expert: A hit queue for sorting by hits by terms in more than one field.
 	/// Uses <code>FieldCache.DEFAULT</code> for maintaining internal term lookup tables.
 	/// 
 	/// <p>Created: Dec 8, 2003 12:56:03 PM
@@ -29,9 +31,9 @@
 	/// </author>
 	/// <since>   lucene 1.4
 	/// </since>
-	/// <version>  $Id: FieldSortedHitQueue.java,v 1.11.2.2 2004/09/30 18:46:27 dnaber Exp $
+	/// <version>  $Id: FieldSortedHitQueue.java 354819 2005-12-07 17:48:37Z yonik $
 	/// </version>
-	/// <seealso cref="Searchable#Search(Query,Filter,int,Sort)">
+	/// <seealso cref="Searcher.Search(Query,Filter,int,Sort)">
 	/// </seealso>
 	/// <seealso cref="FieldCache">
 	/// </seealso>
@@ -47,8 +49,8 @@
 			{
 				this.fieldOrder = fieldOrder;
 			}
-			
-			private int[] fieldOrder;
+
+            private int[] fieldOrder;
 			
 			public int Compare(ScoreDoc i, ScoreDoc j)
 			{
@@ -145,9 +147,9 @@
 			}
 			private void  InitBlock(System.Globalization.CompareInfo collator, System.String[] index)
 			{
-                this.collator = collator;
-                this.index = index;
-            }
+				this.collator = collator;
+				this.index = index;
+			}
 			private System.Globalization.CompareInfo collator;
 			private System.String[] index;
 			
@@ -190,18 +192,37 @@
 		}
 		
 		
-		/// <summary>Stores a comparator corresponding to each Field being sorted by </summary>
+		/// <summary>Stores a comparator corresponding to each field being sorted by </summary>
 		protected internal ScoreDocComparator[] comparators;
 		
 		/// <summary>Stores the sort criteria being used. </summary>
 		protected internal SortField[] fields;
 		
-		/// <summary>Stores the maximum score value encountered, for normalizing.
-		/// we only care about scores greater than 1.0 - if all the scores
-		/// are less than 1.0, we don't have to normalize. 
-		/// </summary>
-		protected internal float maxscore = 1.0f;
+		/// <summary>Stores the maximum score value encountered, needed for normalizing. </summary>
+		protected internal float maxscore = System.Single.NegativeInfinity;
 		
+		/// <summary>returns the maximum score encountered by elements inserted via insert()</summary>
+		public virtual float GetMaxScore()
+		{
+			return maxscore;
+		}
+		
+		// The signature of this method takes a FieldDoc in order to avoid
+		// the unneeded cast to retrieve the score.
+		// inherit javadoc
+		public virtual bool Insert(FieldDoc fdoc)
+		{
+			maxscore = System.Math.Max(maxscore, fdoc.score);
+			return base.Insert(fdoc);
+		}
+		
+		// This overrides PriorityQueue.insert() so that insert(FieldDoc) that
+		// keeps track of the score isn't accidentally bypassed.  
+		// inherit javadoc
+		public override bool Insert(System.Object fdoc)
+		{
+			return Insert((FieldDoc) fdoc);
+		}
 		
 		/// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
 		/// <param name="a">ScoreDoc
@@ -215,24 +236,18 @@
 			ScoreDoc docA = (ScoreDoc) a;
 			ScoreDoc docB = (ScoreDoc) b;
 			
-			// keep track of maximum score
-			if (docA.score > maxscore)
-				maxscore = docA.score;
-			if (docB.score > maxscore)
-				maxscore = docB.score;
-			
 			// run comparators
 			int n = comparators.Length;
 			int c = 0;
 			for (int i = 0; i < n && c == 0; ++i)
 			{
-				c = (fields[i].reverse) ? comparators[i].Compare(docB, docA) : comparators[i].Compare(docA, docB);
+				c = (fields[i].reverse)?comparators[i].Compare(docB, docA):comparators[i].Compare(docA, docB);
 			}
-            // avoid random sort order that could lead to duplicates (bug #31241):
-            if (c == 0)
-                return docA.doc > docB.doc;
-            return c > 0;
-        }
+			// avoid random sort order that could lead to duplicates (bug #31241):
+			if (c == 0)
+				return docA.doc > docB.doc;
+			return c > 0;
+		}
 		
 		
 		/// <summary> Given a FieldDoc object, stores the values used
@@ -245,7 +260,7 @@
 		/// </param>
 		/// <returns>  The same FieldDoc passed in.
 		/// </returns>
-		/// <seealso cref="Searchable#Search(Query,Filter,int,Sort)">
+		/// <seealso cref="Searchable.Search(Weight,Filter,int,Sort)">
 		/// </seealso>
 		internal virtual FieldDoc FillFields(FieldDoc doc)
 		{
@@ -254,8 +269,7 @@
 			for (int i = 0; i < n; ++i)
 				fields[i] = comparators[i].SortValue(doc);
 			doc.fields = fields;
-			if (maxscore > 1.0f)
-				doc.score /= maxscore; // normalize scores
+			//if (maxscore > 1.0f) doc.score /= maxscore;   // normalize scores
 			return doc;
 		}
 		
@@ -277,10 +291,10 @@
 			FieldCacheImpl.Entry entry = (factory != null) ? new FieldCacheImpl.Entry(field, factory) : new FieldCacheImpl.Entry(field, type);
 			lock (Comparators.SyncRoot)
 			{
-                System.Collections.Hashtable readerCache = (System.Collections.Hashtable) Comparators[reader];
-                if (readerCache == null)
-                    return null;
-                return (ScoreDocComparator) readerCache[entry];
+				System.Collections.Hashtable readerCache = (System.Collections.Hashtable) Comparators[reader];
+				if (readerCache == null)
+					return null;
+				return (ScoreDocComparator) readerCache[entry];
 			}
 		}
 		
@@ -290,17 +304,17 @@
 			FieldCacheImpl.Entry entry = (factory != null) ? new FieldCacheImpl.Entry(field, factory) : new FieldCacheImpl.Entry(field, type);
 			lock (Comparators.SyncRoot)
 			{
-                System.Collections.Hashtable readerCache = (System.Collections.Hashtable) Comparators[reader];
-                if (readerCache == null)
-                {
-                    readerCache = new System.Collections.Hashtable();
-                    Comparators[reader] = readerCache;
-                }
-                System.Object tempObject;
-                tempObject = readerCache[entry];
-                readerCache[entry] = value_Renamed;
-                return tempObject;
-            }
+				System.Collections.Hashtable readerCache = (System.Collections.Hashtable) Comparators[reader];
+				if (readerCache == null)
+				{
+					readerCache = new System.Collections.Hashtable();
+					Comparators[reader] = readerCache;
+				}
+				System.Object tempObject;
+				tempObject = readerCache[entry];
+				readerCache[entry] = value_Renamed;
+				return tempObject;
+			}
 		}
 		
 		internal static ScoreDocComparator GetCachedComparator(IndexReader reader, System.String fieldname, int type, System.Globalization.CultureInfo locale, SortComparatorSource factory)
@@ -339,7 +353,7 @@
 						break;
 					
 					default: 
-						throw new System.SystemException("unknown Field type: " + type);
+						throw new System.SystemException("unknown field type: " + type);
 					
 				}
 				Store(reader, fieldname, type, factory, comparator);
@@ -347,7 +361,7 @@
 			return comparator;
 		}
 		
-		/// <summary> Returns a comparator for sorting hits according to a Field containing integers.</summary>
+		/// <summary> Returns a comparator for sorting hits according to a field containing integers.</summary>
 		/// <param name="reader"> Index to use.
 		/// </param>
 		/// <param name="fieldname"> Field containg integer values.
@@ -358,11 +372,11 @@
 		internal static ScoreDocComparator ComparatorInt(IndexReader reader, System.String fieldname)
 		{
 			System.String field = String.Intern(fieldname);
-            int[] fieldOrder = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetInts(reader, field);
-            return new AnonymousClassScoreDocComparator(fieldOrder);
-        }
+			int[] fieldOrder = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetInts(reader, field);
+			return new AnonymousClassScoreDocComparator(fieldOrder);
+		}
 		
-		/// <summary> Returns a comparator for sorting hits according to a Field containing floats.</summary>
+		/// <summary> Returns a comparator for sorting hits according to a field containing floats.</summary>
 		/// <param name="reader"> Index to use.
 		/// </param>
 		/// <param name="fieldname"> Field containg float values.
@@ -373,11 +387,11 @@
 		internal static ScoreDocComparator ComparatorFloat(IndexReader reader, System.String fieldname)
 		{
 			System.String field = String.Intern(fieldname);
-            float[] fieldOrder = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetFloats(reader, field);
-            return new AnonymousClassScoreDocComparator1(fieldOrder);
-        }
+			float[] fieldOrder = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetFloats(reader, field);
+			return new AnonymousClassScoreDocComparator1(fieldOrder);
+		}
 		
-		/// <summary> Returns a comparator for sorting hits according to a Field containing strings.</summary>
+		/// <summary> Returns a comparator for sorting hits according to a field containing strings.</summary>
 		/// <param name="reader"> Index to use.
 		/// </param>
 		/// <param name="fieldname"> Field containg string values.
@@ -388,11 +402,11 @@
 		internal static ScoreDocComparator ComparatorString(IndexReader reader, System.String fieldname)
 		{
 			System.String field = String.Intern(fieldname);
-            Lucene.Net.Search.StringIndex index = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetStringIndex(reader, field);
-            return new AnonymousClassScoreDocComparator2(index);
-        }
+			Lucene.Net.Search.StringIndex index = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetStringIndex(reader, field);
+			return new AnonymousClassScoreDocComparator2(index);
+		}
 		
-		/// <summary> Returns a comparator for sorting hits according to a Field containing strings.</summary>
+		/// <summary> Returns a comparator for sorting hits according to a field containing strings.</summary>
 		/// <param name="reader"> Index to use.
 		/// </param>
 		/// <param name="fieldname"> Field containg string values.
@@ -404,12 +418,12 @@
 		{
 			System.Globalization.CompareInfo collator = locale.CompareInfo;
 			System.String field = String.Intern(fieldname);
-            System.String[] index = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetStrings(reader, field);
-            return new AnonymousClassScoreDocComparator3(collator, index);
-        }
+			System.String[] index = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetStrings(reader, field);
+			return new AnonymousClassScoreDocComparator3(collator, index);
+		}
 		
-		/// <summary> Returns a comparator for sorting hits according to values in the given Field.
-		/// The terms in the Field are looked at to determine whether they contain integers,
+		/// <summary> Returns a comparator for sorting hits according to values in the given field.
+		/// The terms in the field are looked at to determine whether they contain integers,
 		/// floats or strings.  Once the type is determined, one of the other static methods
 		/// in this class is called to get the comparator.
 		/// </summary>
@@ -442,7 +456,7 @@
 			}
 			else
 			{
-				throw new System.SystemException("unknown data type in Field '" + field + "'");
+				throw new System.SystemException("unknown data type in field '" + field + "'");
 			}
 		}
 	}

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Filter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Filter.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Filter.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Filter.cs Sat Jun  3 19:41:13 2006
@@ -13,8 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using IndexReader = Lucene.Net.Index.IndexReader;
+
 namespace Lucene.Net.Search
 {
 	

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FilteredQuery.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FilteredQuery.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FilteredQuery.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FilteredQuery.cs Sat Jun  3 19:41:13 2006
@@ -13,8 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using IndexReader = Lucene.Net.Index.IndexReader;
+using ToStringUtils = Lucene.Net.Util.ToStringUtils;
+
 namespace Lucene.Net.Search
 {
 	
@@ -32,19 +35,19 @@
 	/// </author>
 	/// <since>   1.4
 	/// </since>
-	/// <version>  $Id: FilteredQuery.java,v 1.5 2004/06/18 09:52:25 ehatcher Exp $
+	/// <version>  $Id: FilteredQuery.java 331113 2005-11-06 15:55:45Z yonik $
 	/// </version>
 	/// <seealso cref="CachingWrapperFilter">
 	/// </seealso>
 	[Serializable]
-	public class FilteredQuery : Query
+	public class FilteredQuery:Query
 	{
 		[Serializable]
 		private class AnonymousClassWeight : Weight
 		{
-			public AnonymousClassWeight(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Searcher searcher, FilteredQuery enclosingInstance)
+			public AnonymousClassWeight(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance)
 			{
-				InitBlock(weight, searcher, enclosingInstance);
+				InitBlock(weight, similarity, enclosingInstance);
 			}
 			private class AnonymousClassScorer : Scorer
 			{
@@ -101,36 +104,16 @@
 					return exp;
 				}
 			}
-			private void  InitBlock(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Searcher searcher, FilteredQuery enclosingInstance)
+			private void  InitBlock(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance)
 			{
 				this.weight = weight;
-				this.searcher = searcher;
+				this.similarity = similarity;
 				this.enclosingInstance = enclosingInstance;
 			}
 			private Lucene.Net.Search.Weight weight;
-			private Lucene.Net.Search.Searcher searcher;
+			private Lucene.Net.Search.Similarity similarity;
 			private FilteredQuery enclosingInstance;
-            virtual public float Value
-            {
-                // pass these methods through to enclosed query's weight
-				
-                get
-                {
-                    return weight.Value;
-                }
-				
-            }
-            virtual public Query Query
-            {
-                // return this query
-				
-                get
-                {
-                    return Enclosing_Instance;
-                }
-				
-            }
-            public FilteredQuery Enclosing_Instance
+			public FilteredQuery Enclosing_Instance
 			{
 				get
 				{
@@ -138,6 +121,12 @@
 				}
 				
 			}
+			
+			// pass these methods through to enclosed query's weight
+			public virtual float GetValue()
+			{
+				return weight.GetValue();
+			}
 			public virtual float SumOfSquaredWeights()
 			{
 				return weight.SumOfSquaredWeights();
@@ -151,13 +140,19 @@
 				return weight.Explain(ir, i);
 			}
 			
+			// return this query
+			public virtual Query GetQuery()
+			{
+				return Enclosing_Instance;
+			}
+			
 			// return a scorer that overrides the enclosed query's score if
 			// the given hit has been filtered out.
 			public virtual Scorer Scorer(IndexReader indexReader)
 			{
 				Scorer scorer = weight.Scorer(indexReader);
 				System.Collections.BitArray bitset = Enclosing_Instance.filter.Bits(indexReader);
-				return new AnonymousClassScorer(scorer, bitset, this, Enclosing_Instance.query.GetSimilarity(searcher));
+				return new AnonymousClassScorer(scorer, bitset, this, similarity);
 			}
 		}
 		
@@ -177,13 +172,16 @@
 			this.filter = filter;
 		}
 		
+		
+		
 		/// <summary> Returns a Weight that applies the filter to the enclosed query's Weight.
 		/// This is accomplished by overriding the Scorer returned by the Weight.
 		/// </summary>
 		protected internal override Weight CreateWeight(Searcher searcher)
 		{
 			Weight weight = query.CreateWeight(searcher);
-			return new AnonymousClassWeight(weight, searcher, this);
+			Similarity similarity = query.GetSimilarity(searcher);
+			return new AnonymousClassWeight(weight, similarity, this);
 		}
 		
 		/// <summary>Rewrites the wrapped query. </summary>
@@ -207,10 +205,27 @@
 			return query;
 		}
 		
+		public virtual Filter GetFilter()
+		{
+			return filter;
+		}
+		
+		// inherit javadoc
+		public override void  ExtractTerms(System.Collections.Hashtable terms)
+		{
+			GetQuery().ExtractTerms(terms);
+		}
+		
 		/// <summary>Prints a user-readable version of this query. </summary>
 		public override System.String ToString(System.String s)
 		{
-			return "filtered(" + query.ToString(s) + ")->" + filter;
+			System.Text.StringBuilder buffer = new System.Text.StringBuilder();
+			buffer.Append("filtered(");
+			buffer.Append(query.ToString(s));
+			buffer.Append(")->");
+			buffer.Append(filter);
+			buffer.Append(ToStringUtils.Boost(GetBoost()));
+			return buffer.ToString();
 		}
 		
 		/// <summary>Returns true iff <code>o</code> is equal to this. </summary>

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FilteredTermEnum.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FilteredTermEnum.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FilteredTermEnum.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FilteredTermEnum.cs Sat Jun  3 19:41:13 2006
@@ -13,10 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
-using IndexReader = Lucene.Net.Index.IndexReader;
 using Term = Lucene.Net.Index.Term;
 using TermEnum = Lucene.Net.Index.TermEnum;
+
 namespace Lucene.Net.Search
 {
 	
@@ -54,7 +55,7 @@
 		}
 		
 		/// <summary> Returns the docFreq of the current Term in the enumeration.
-		/// Initially invalid, valid after next() called for the first time. 
+		/// Returns -1 if no Term matches or all terms have been enumerated.
 		/// </summary>
 		public override int DocFreq()
 		{
@@ -90,7 +91,7 @@
 		}
 		
 		/// <summary>Returns the current Term in the enumeration.
-		/// Initially invalid, valid after next() called for the first time. 
+		/// Returns null if no Term matches or all terms have been enumerated. 
 		/// </summary>
 		public override Term Term()
 		{

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FuzzyQuery.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FuzzyQuery.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FuzzyQuery.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FuzzyQuery.cs Sat Jun  3 19:41:13 2006
@@ -13,93 +13,214 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using IndexReader = Lucene.Net.Index.IndexReader;
 using Term = Lucene.Net.Index.Term;
+using PriorityQueue = Lucene.Net.Util.PriorityQueue;
+using ToStringUtils = Lucene.Net.Util.ToStringUtils;
+
 namespace Lucene.Net.Search
 {
 	
-    /// <summary>Implements the fuzzy search query. The similiarity measurement
-    /// is based on the Levenshtein (edit distance) algorithm.
-    /// </summary>
-    [Serializable]
-    public sealed class FuzzyQuery:MultiTermQuery
-    {
-		
-        public const float defaultMinSimilarity = 0.5f;
-        private float minimumSimilarity;
-        private int prefixLength;
-		
-        /// <summary> Create a new FuzzyQuery that will match terms with a similarity 
-        /// of at least <code>minimumSimilarity</code> to <code>term</code>.
-        /// If a <code>prefixLength</code> &gt; 0 is specified, a common prefix
-        /// of that length is also required.
-        /// 
-        /// </summary>
-        /// <param name="term">the term to search for
-        /// </param>
-        /// <param name="minimumSimilarity">a value between 0 and 1 to set the required similarity
-        /// between the query term and the matching terms. For example, for a
-        /// <code>minimumSimilarity</code> of <code>0.5</code> a term of the same length
-        /// as the query term is considered similar to the query term if the edit distance
-        /// between both terms is less than <code>length(term)*0.5</code>
-        /// </param>
-        /// <param name="prefixLength">length of common (non-fuzzy) prefix
-        /// </param>
-        /// <throws>  IllegalArgumentException if minimumSimilarity is &gt; 1 or &lt; 0 </throws>
-        /// <summary> or if prefixLength &lt; 0 or &gt; <code>term.text().length()</code>.
-        /// </summary>
-        public FuzzyQuery(Term term, float minimumSimilarity, int prefixLength):base(term)
-        {
-			
-            if (minimumSimilarity > 1.0f)
-                throw new System.ArgumentException("minimumSimilarity > 1");
-            else if (minimumSimilarity < 0.0f)
-                throw new System.ArgumentException("minimumSimilarity < 0");
-            this.minimumSimilarity = minimumSimilarity;
-			
-            if (prefixLength < 0)
-                throw new System.ArgumentException("prefixLength < 0");
-            else if (prefixLength >= term.Text().Length)
-                throw new System.ArgumentException("prefixLength >= term.text().length()");
-            this.prefixLength = prefixLength;
-        }
-		
-        /// <summary> Calls {@link #FuzzyQuery(Term, float) FuzzyQuery(term, minimumSimilarity, 0)}.</summary>
-        public FuzzyQuery(Term term, float minimumSimilarity):this(term, minimumSimilarity, 0)
-        {
-        }
-		
-        /// <summary> Calls {@link #FuzzyQuery(Term, float) FuzzyQuery(term, 0.5f, 0)}.</summary>
-        public FuzzyQuery(Term term):this(term, defaultMinSimilarity, 0)
-        {
-        }
-		
-        /// <summary> Returns the minimum similarity that is required for this query to match.</summary>
-        /// <returns> float value between 0.0 and 1.0
-        /// </returns>
-        public float GetMinSimilarity()
-        {
-            return minimumSimilarity;
-        }
-		
-        /// <summary> Returns the prefix length, i.e. the number of characters at the start
-        /// of a term that must be identical (not fuzzy) to the query term if the query
-        /// is to match that term. 
-        /// </summary>
-        public int GetPrefixLength()
-        {
-            return prefixLength;
-        }
-		
-        protected internal override FilteredTermEnum GetEnum(IndexReader reader)
-        {
-            return new FuzzyTermEnum(reader, GetTerm(), minimumSimilarity, prefixLength);
-        }
-		
-        public override System.String ToString(System.String field)
-        {
-            return base.ToString(field) + '~' + minimumSimilarity.ToString();
-        }
-    }
+	/// <summary>Implements the fuzzy search query. The similiarity measurement
+	/// is based on the Levenshtein (edit distance) algorithm.
+	/// </summary>
+	[Serializable]
+	public sealed class FuzzyQuery : MultiTermQuery
+	{
+		
+		public const float defaultMinSimilarity = 0.5f;
+		public const int defaultPrefixLength = 0;
+		
+		private float minimumSimilarity;
+		private int prefixLength;
+		
+		/// <summary> Create a new FuzzyQuery that will match terms with a similarity 
+		/// of at least <code>minimumSimilarity</code> to <code>term</code>.
+		/// If a <code>prefixLength</code> &gt; 0 is specified, a common prefix
+		/// of that length is also required.
+		/// 
+		/// </summary>
+		/// <param name="term">the term to search for
+		/// </param>
+		/// <param name="minimumSimilarity">a value between 0 and 1 to set the required similarity
+		/// between the query term and the matching terms. For example, for a
+		/// <code>minimumSimilarity</code> of <code>0.5</code> a term of the same length
+		/// as the query term is considered similar to the query term if the edit distance
+		/// between both terms is less than <code>length(term)*0.5</code>
+		/// </param>
+		/// <param name="prefixLength">length of common (non-fuzzy) prefix
+		/// </param>
+		/// <throws>  IllegalArgumentException if minimumSimilarity is &gt;= 1 or &lt; 0 </throws>
+		/// <summary> or if prefixLength &lt; 0
+		/// </summary>
+		public FuzzyQuery(Term term, float minimumSimilarity, int prefixLength):base(term)
+		{
+			
+			if (minimumSimilarity >= 1.0f)
+				throw new System.ArgumentException("minimumSimilarity >= 1");
+			else if (minimumSimilarity < 0.0f)
+				throw new System.ArgumentException("minimumSimilarity < 0");
+			if (prefixLength < 0)
+				throw new System.ArgumentException("prefixLength < 0");
+			
+			this.minimumSimilarity = minimumSimilarity;
+			this.prefixLength = prefixLength;
+		}
+		
+		/// <summary> Calls {@link #FuzzyQuery(Term, float) FuzzyQuery(term, minimumSimilarity, 0)}.</summary>
+		public FuzzyQuery(Term term, float minimumSimilarity):this(term, minimumSimilarity, defaultPrefixLength)
+		{
+		}
+		
+		/// <summary> Calls {@link #FuzzyQuery(Term, float) FuzzyQuery(term, 0.5f, 0)}.</summary>
+		public FuzzyQuery(Term term):this(term, defaultMinSimilarity, defaultPrefixLength)
+		{
+		}
+		
+		/// <summary> Returns the minimum similarity that is required for this query to match.</summary>
+		/// <returns> float value between 0.0 and 1.0
+		/// </returns>
+		public float GetMinSimilarity()
+		{
+			return minimumSimilarity;
+		}
+		
+		/// <summary> Returns the non-fuzzy prefix length. This is the number of characters at the start
+		/// of a term that must be identical (not fuzzy) to the query term if the query
+		/// is to match that term. 
+		/// </summary>
+		public int GetPrefixLength()
+		{
+			return prefixLength;
+		}
+		
+		protected internal override FilteredTermEnum GetEnum(IndexReader reader)
+		{
+			return new FuzzyTermEnum(reader, GetTerm(), minimumSimilarity, prefixLength);
+		}
+		
+		public override Query Rewrite(IndexReader reader)
+		{
+			FilteredTermEnum enumerator = GetEnum(reader);
+			int maxClauseCount = BooleanQuery.GetMaxClauseCount();
+			ScoreTermQueue stQueue = new ScoreTermQueue(maxClauseCount);
+			
+			try
+			{
+				do 
+				{
+					float minScore = 0.0f;
+					float score = 0.0f;
+					Term t = enumerator.Term();
+					if (t != null)
+					{
+						score = enumerator.Difference();
+						// terms come in alphabetical order, therefore if queue is full and score
+						// not bigger than minScore, we can skip
+						if (stQueue.Size() < maxClauseCount || score > minScore)
+						{
+							stQueue.Insert(new ScoreTerm(t, score));
+							minScore = ((ScoreTerm) stQueue.Top()).score; // maintain minScore
+						}
+					}
+				}
+				while (enumerator.Next());
+			}
+			finally
+			{
+				enumerator.Close();
+			}
+			
+			BooleanQuery query = new BooleanQuery(true);
+			int size = stQueue.Size();
+			for (int i = 0; i < size; i++)
+			{
+				ScoreTerm st = (ScoreTerm) stQueue.Pop();
+				TermQuery tq = new TermQuery(st.term); // found a match
+				tq.SetBoost(GetBoost() * st.score); // set the boost
+				query.Add(tq, BooleanClause.Occur.SHOULD); // add to query
+			}
+			
+			return query;
+		}
+		
+		public override System.String ToString(System.String field)
+		{
+			System.Text.StringBuilder buffer = new System.Text.StringBuilder();
+			Term term = GetTerm();
+			if (!term.Field().Equals(field))
+			{
+				buffer.Append(term.Field());
+				buffer.Append(":");
+			}
+			buffer.Append(term.Text());
+			buffer.Append('~');
+			buffer.Append(minimumSimilarity.ToString());
+			buffer.Append(ToStringUtils.Boost(GetBoost()));
+			return buffer.ToString();
+		}
+		
+		private class ScoreTerm
+		{
+			public Term term;
+			public float score;
+			
+			public ScoreTerm(Term term, float score)
+			{
+				this.term = term;
+				this.score = score;
+			}
+		}
+		
+		private class ScoreTermQueue : PriorityQueue
+		{
+			
+			public ScoreTermQueue(int size)
+			{
+				Initialize(size);
+			}
+			
+			/* (non-Javadoc)
+			* @see Lucene.Net.util.PriorityQueue#lessThan(java.lang.Object, java.lang.Object)
+			*/
+			public override bool LessThan(System.Object a, System.Object b)
+			{
+				ScoreTerm termA = (ScoreTerm) a;
+				ScoreTerm termB = (ScoreTerm) b;
+				if (termA.score == termB.score)
+					return termA.term.CompareTo(termB.term) > 0;
+				else
+					return termA.score < termB.score;
+			}
+		}
+		
+		public  override bool Equals(System.Object o)
+		{
+			if (this == o)
+				return true;
+			if (!(o is FuzzyQuery))
+				return false;
+			if (!base.Equals(o))
+				return false;
+			
+			FuzzyQuery fuzzyQuery = (FuzzyQuery) o;
+			
+			if (minimumSimilarity != fuzzyQuery.minimumSimilarity)
+				return false;
+			if (prefixLength != fuzzyQuery.prefixLength)
+				return false;
+			
+			return true;
+		}
+		
+		public override int GetHashCode()
+		{
+			int result = base.GetHashCode();
+            result = 29 * result + minimumSimilarity != + 0.0f ? BitConverter.ToInt32(BitConverter.GetBytes(minimumSimilarity), 0) : 0;
+			result = 29 * result + prefixLength;
+			return result;
+		}
+	}
 }



Mime
View raw message