You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ar...@apache.org on 2008/06/25 04:51:26 UTC

svn commit: r671402 [2/5] - in /incubator/lucene.net/trunk/C#/src/Lucene.Net/Search: ./ Function/ Payload/ Spans/

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=671402&r1=671401&r2=671402&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 Tue Jun 24 19:51:24 2008
@@ -33,9 +33,9 @@
 	/// </author>
 	/// <since>   lucene 1.4
 	/// </since>
-	/// <version>  $Id: FieldSortedHitQueue.java 477084 2006-11-20 07:10:04Z otis $
+	/// <version>  $Id: FieldSortedHitQueue.java 605225 2007-12-18 15:13:05Z gsingers $
 	/// </version>
-	/// <seealso cref="Searcher#Search(Query,Filter,int,Sort)">
+	/// <seealso cref="Searcher.Search(Query,Filter,int,Sort)">
 	/// </seealso>
 	/// <seealso cref="FieldCache">
 	/// </seealso>
@@ -60,18 +60,26 @@
 						break;
 					
 					case SortField.INT: 
-						comparator = Lucene.Net.Search.FieldSortedHitQueue.comparatorInt(reader, fieldname);
+						comparator = Lucene.Net.Search.FieldSortedHitQueue.ComparatorInt(reader, fieldname);
 						break;
 					
 					case SortField.FLOAT: 
-						comparator = Lucene.Net.Search.FieldSortedHitQueue.comparatorFloat(reader, fieldname);
+						comparator = Lucene.Net.Search.FieldSortedHitQueue.ComparatorFloat(reader, fieldname);
+						break;
+					
+					case SortField.LONG: 
+						comparator = Lucene.Net.Search.FieldSortedHitQueue.ComparatorLong(reader, fieldname);
+						break;
+					
+					case SortField.DOUBLE: 
+						comparator = Lucene.Net.Search.FieldSortedHitQueue.ComparatorDouble(reader, fieldname);
 						break;
 					
 					case SortField.STRING: 
 						if (locale != null)
-							comparator = Lucene.Net.Search.FieldSortedHitQueue.comparatorStringLocale(reader, fieldname, locale);
+							comparator = Lucene.Net.Search.FieldSortedHitQueue.ComparatorStringLocale(reader, fieldname, locale);
 						else
-							comparator = Lucene.Net.Search.FieldSortedHitQueue.comparatorString(reader, fieldname);
+							comparator = Lucene.Net.Search.FieldSortedHitQueue.ComparatorString(reader, fieldname);
 						break;
 					
 					case SortField.CUSTOM: 
@@ -120,7 +128,40 @@
 		}
 		private class AnonymousClassScoreDocComparator1 : ScoreDocComparator
 		{
-			public AnonymousClassScoreDocComparator1(float[] fieldOrder)
+			public AnonymousClassScoreDocComparator1(long[] fieldOrder)
+			{
+				InitBlock(fieldOrder);
+			}
+			private void  InitBlock(long[] fieldOrder)
+			{
+				this.fieldOrder = fieldOrder;
+			}
+			private long[] fieldOrder;
+			
+			public int Compare(ScoreDoc i, ScoreDoc j)
+			{
+				long li = fieldOrder[i.doc];
+				long lj = fieldOrder[j.doc];
+				if (li < lj)
+					return - 1;
+				if (li > lj)
+					return 1;
+				return 0;
+			}
+			
+			public virtual System.IComparable SortValue(ScoreDoc i)
+			{
+				return (long) fieldOrder[i.doc];
+			}
+			
+			public virtual int SortType()
+			{
+				return SortField.LONG;
+			}
+		}
+		private class AnonymousClassScoreDocComparator2 : ScoreDocComparator
+		{
+			public AnonymousClassScoreDocComparator2(float[] fieldOrder)
 			{
 				InitBlock(fieldOrder);
 			}
@@ -151,9 +192,42 @@
 				return SortField.FLOAT;
 			}
 		}
-		private class AnonymousClassScoreDocComparator2 : ScoreDocComparator
+		private class AnonymousClassScoreDocComparator3 : ScoreDocComparator
+		{
+			public AnonymousClassScoreDocComparator3(double[] fieldOrder)
+			{
+				InitBlock(fieldOrder);
+			}
+			private void  InitBlock(double[] fieldOrder)
+			{
+				this.fieldOrder = fieldOrder;
+			}
+			private double[] fieldOrder;
+			
+			public int Compare(ScoreDoc i, ScoreDoc j)
+			{
+				double di = fieldOrder[i.doc];
+				double dj = fieldOrder[j.doc];
+				if (di < dj)
+					return - 1;
+				if (di > dj)
+					return 1;
+				return 0;
+			}
+			
+			public virtual System.IComparable SortValue(ScoreDoc i)
+			{
+				return (double) fieldOrder[i.doc];
+			}
+			
+			public virtual int SortType()
+			{
+				return SortField.DOUBLE;
+			}
+		}
+		private class AnonymousClassScoreDocComparator4 : ScoreDocComparator
 		{
-			public AnonymousClassScoreDocComparator2(Lucene.Net.Search.StringIndex index)
+			public AnonymousClassScoreDocComparator4(Lucene.Net.Search.StringIndex index)
 			{
 				InitBlock(index);
 			}
@@ -184,9 +258,9 @@
 				return SortField.STRING;
 			}
 		}
-		private class AnonymousClassScoreDocComparator3 : ScoreDocComparator
+		private class AnonymousClassScoreDocComparator5 : ScoreDocComparator
 		{
-			public AnonymousClassScoreDocComparator3(System.String[] index, System.Globalization.CompareInfo collator)
+			public AnonymousClassScoreDocComparator5(System.String[] index, System.Globalization.CompareInfo collator)
 			{
 				InitBlock(index, collator);
 			}
@@ -277,12 +351,18 @@
 			return maxscore;
 		}
 		
+		// Update maxscore.
+		private void  UpdateMaxScore(FieldDoc fdoc)
+		{
+			maxscore = System.Math.Max(maxscore, fdoc.score);
+		}
+		
 		// 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);
+			UpdateMaxScore(fdoc);
 			return base.Insert(fdoc);
 		}
 		
@@ -294,6 +374,15 @@
 			return Insert((FieldDoc) fdoc);
 		}
 		
+		// This overrides PriorityQueue.insertWithOverflow() so that
+		// updateMaxScore(FieldDoc) that keeps track of the score isn't accidentally
+		// bypassed.
+		public override System.Object InsertWithOverflow(System.Object element)
+		{
+			UpdateMaxScore((FieldDoc) element);
+			return base.InsertWithOverflow(element);
+		}
+		
 		/// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
 		/// <param name="a">ScoreDoc
 		/// </param>
@@ -311,7 +400,7 @@
 			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)
@@ -330,7 +419,7 @@
 		/// </param>
 		/// <returns>  The same FieldDoc passed in.
 		/// </returns>
-		/// <seealso cref="Searchable#Search(Weight,Filter,int,Sort)">
+		/// <seealso cref="Searchable.Search(Weight,Filter,int,Sort)">
 		/// </seealso>
 		internal virtual FieldDoc FillFields(FieldDoc doc)
 		{
@@ -373,13 +462,29 @@
 		/// <returns>  Comparator for sorting hits.
 		/// </returns>
 		/// <throws>  IOException If an error occurs reading the index. </throws>
-		internal static ScoreDocComparator comparatorInt(IndexReader reader, System.String fieldname)
+		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);
 		}
 		
+		/// <summary> Returns a comparator for sorting hits according to a field containing integers.</summary>
+		/// <param name="reader"> Index to use.
+		/// </param>
+		/// <param name="fieldname"> Fieldable containg integer values.
+		/// </param>
+		/// <returns>  Comparator for sorting hits.
+		/// </returns>
+		/// <throws>  IOException If an error occurs reading the index. </throws>
+		internal static ScoreDocComparator ComparatorLong(IndexReader reader, System.String fieldname)
+		{
+			System.String field = String.Intern(fieldname);
+			long[] fieldOrder = Lucene.Net.Search.ExtendedFieldCache_Fields.EXT_DEFAULT.GetLongs(reader, field);
+			return new AnonymousClassScoreDocComparator1(fieldOrder);
+		}
+		
+		
 		/// <summary> Returns a comparator for sorting hits according to a field containing floats.</summary>
 		/// <param name="reader"> Index to use.
 		/// </param>
@@ -388,11 +493,26 @@
 		/// <returns>  Comparator for sorting hits.
 		/// </returns>
 		/// <throws>  IOException If an error occurs reading the index. </throws>
-		internal static ScoreDocComparator comparatorFloat(IndexReader reader, System.String fieldname)
+		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);
+			return new AnonymousClassScoreDocComparator2(fieldOrder);
+		}
+		
+		/// <summary> Returns a comparator for sorting hits according to a field containing doubles.</summary>
+		/// <param name="reader"> Index to use.
+		/// </param>
+		/// <param name="fieldname"> Fieldable containg float values.
+		/// </param>
+		/// <returns>  Comparator for sorting hits.
+		/// </returns>
+		/// <throws>  IOException If an error occurs reading the index. </throws>
+		internal static ScoreDocComparator ComparatorDouble(IndexReader reader, System.String fieldname)
+		{
+			System.String field = String.Intern(fieldname);
+			double[] fieldOrder = Lucene.Net.Search.ExtendedFieldCache_Fields.EXT_DEFAULT.GetDoubles(reader, field);
+			return new AnonymousClassScoreDocComparator3(fieldOrder);
 		}
 		
 		/// <summary> Returns a comparator for sorting hits according to a field containing strings.</summary>
@@ -403,11 +523,11 @@
 		/// <returns>  Comparator for sorting hits.
 		/// </returns>
 		/// <throws>  IOException If an error occurs reading the index. </throws>
-		internal static ScoreDocComparator comparatorString(IndexReader reader, System.String fieldname)
+		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);
+			return new AnonymousClassScoreDocComparator4(index);
 		}
 		
 		/// <summary> Returns a comparator for sorting hits according to a field containing strings.</summary>
@@ -418,12 +538,12 @@
 		/// <returns>  Comparator for sorting hits.
 		/// </returns>
 		/// <throws>  IOException If an error occurs reading the index. </throws>
-		internal static ScoreDocComparator comparatorStringLocale(IndexReader reader, System.String fieldname, System.Globalization.CultureInfo locale)
+		internal static ScoreDocComparator ComparatorStringLocale(IndexReader reader, System.String fieldname, System.Globalization.CultureInfo locale)
 		{
 			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(index, collator);
+			return new AnonymousClassScoreDocComparator5(index, collator);
 		}
 		
 		/// <summary> Returns a comparator for sorting hits according to values in the given field.
@@ -441,22 +561,26 @@
 		internal static ScoreDocComparator ComparatorAuto(IndexReader reader, System.String fieldname)
 		{
 			System.String field = String.Intern(fieldname);
-			System.Object lookupArray = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetAuto(reader, field);
+			System.Object lookupArray = Lucene.Net.Search.ExtendedFieldCache_Fields.EXT_DEFAULT.GetAuto(reader, field);
 			if (lookupArray is Lucene.Net.Search.StringIndex)
 			{
-				return comparatorString(reader, field);
+				return ComparatorString(reader, field);
 			}
 			else if (lookupArray is int[])
 			{
-				return comparatorInt(reader, field);
+				return ComparatorInt(reader, field);
+			}
+			else if (lookupArray is long[])
+			{
+				return ComparatorLong(reader, field);
 			}
 			else if (lookupArray is float[])
 			{
-				return comparatorFloat(reader, field);
+				return ComparatorFloat(reader, field);
 			}
 			else if (lookupArray is System.String[])
 			{
-				return comparatorString(reader, field);
+				return ComparatorString(reader, field);
 			}
 			else
 			{

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FilterManager.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FilterManager.cs?rev=671402&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FilterManager.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FilterManager.cs Tue Jun 24 19:51:24 2008
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Lucene.Net.Search
+{
+	
+	/// <summary> Filter caching singleton.  It can be used by {@link Lucene.Net.Search.RemoteCachingWrapperFilter}
+	/// or just to save filters locally for reuse.
+	/// This class makes it possble to cache Filters even when using RMI, as it
+	/// keeps the cache on the seaercher side of the RMI connection.
+	/// 
+	/// Also could be used as a persistent storage for any filter as long as the
+	/// filter provides a proper hashCode(), as that is used as the key in the cache.
+	/// 
+	/// The cache is periodically cleaned up from a separate thread to ensure the
+	/// cache doesn't exceed the maximum size.
+	/// </summary>
+	/// <author>  Matt Ericson
+	/// </author>
+	public class FilterManager
+	{
+		
+		protected internal static FilterManager manager;
+		
+		/// <summary>The default maximum number of Filters in the cache </summary>
+		protected internal const int DEFAULT_CACHE_CLEAN_SIZE = 100;
+		/// <summary>The default frequency of cache clenup </summary>
+		protected internal const long DEFAULT_CACHE_SLEEP_TIME = 1000 * 60 * 10;
+		
+		/// <summary>The cache itself </summary>
+		protected internal System.Collections.IDictionary cache;
+		/// <summary>Maximum allowed cache size </summary>
+		protected internal int cacheCleanSize;
+		/// <summary>Cache cleaning frequency </summary>
+		protected internal long cleanSleepTime;
+		/// <summary>Cache cleaner that runs in a separate thread </summary>
+		protected internal FilterCleaner filterCleaner;
+		
+		public static FilterManager GetInstance()
+		{
+			lock (typeof(Lucene.Net.Search.FilterManager))
+			{
+				if (manager == null)
+				{
+					manager = new FilterManager();
+				}
+				return manager;
+			}
+		}
+		
+		/// <summary> Sets up the FilterManager singleton.</summary>
+		protected internal FilterManager()
+		{
+			cache = new System.Collections.Hashtable();
+			cacheCleanSize = DEFAULT_CACHE_CLEAN_SIZE; // Let the cache get to 100 items
+			cleanSleepTime = DEFAULT_CACHE_SLEEP_TIME; // 10 minutes between cleanings
+			
+			filterCleaner = new FilterCleaner(this);
+			SupportClass.ThreadClass fcThread = new SupportClass.ThreadClass(new System.Threading.ThreadStart(filterCleaner.Run));
+			// setto be a Daemon so it doesn't have to be stopped
+			fcThread.IsBackground = true;
+			fcThread.Start();
+		}
+		
+		/// <summary> Sets the max size that cache should reach before it is cleaned up</summary>
+		/// <param name="cacheCleanSize">maximum allowed cache size
+		/// </param>
+		public virtual void  SetCacheSize(int cacheCleanSize)
+		{
+			this.cacheCleanSize = cacheCleanSize;
+		}
+		
+		/// <summary> Sets the cache cleaning frequency in milliseconds.</summary>
+		/// <param name="cleanSleepTime">cleaning frequency in millioseconds
+		/// </param>
+		public virtual void  SetCleanThreadSleepTime(long cleanSleepTime)
+		{
+			this.cleanSleepTime = cleanSleepTime;
+		}
+		
+		/// <summary> Returns the cached version of the filter.  Allows the caller to pass up
+		/// a small filter but this will keep a persistent version around and allow
+		/// the caching filter to do its job.
+		/// 
+		/// </summary>
+		/// <param name="filter">The input filter
+		/// </param>
+		/// <returns> The cached version of the filter
+		/// </returns>
+		public virtual Filter GetFilter(Filter filter)
+		{
+			lock (cache.SyncRoot)
+			{
+				FilterItem fi = null;
+				fi = (FilterItem) cache[(System.Int32) filter.GetHashCode()];
+				if (fi != null)
+				{
+					fi.timestamp = System.DateTime.Now.Millisecond; // {{Aroush-2.3.1}} do we want Millisecond or Ticks here?
+					return fi.filter;
+				}
+				cache[(System.Int32) filter.GetHashCode()] = new FilterItem(this, filter);
+				return filter;
+			}
+		}
+		
+		/// <summary> Holds the filter and the last time the filter was used, to make LRU-based
+		/// cache cleaning possible.
+		/// TODO: Clean this up when we switch to Java 1.5
+		/// </summary>
+		protected internal class FilterItem
+		{
+			private void  InitBlock(FilterManager enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private FilterManager enclosingInstance;
+			public FilterManager Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			public Filter filter;
+			public long timestamp;
+			
+			public FilterItem(FilterManager enclosingInstance, Filter filter)
+			{
+				InitBlock(enclosingInstance);
+				this.filter = filter;
+				this.timestamp = System.DateTime.Now.Millisecond; // {{Aroush-2.3.1}} do we want Millisecond or Ticks here?
+			}
+		}
+		
+		
+		/// <summary> Keeps the cache from getting too big.
+		/// If we were using Java 1.5, we could use LinkedHashMap and we would not need this thread
+		/// to clean out the cache.
+		/// 
+		/// The SortedSet sortedFilterItems is used only to sort the items from the cache,
+		/// so when it's time to clean up we have the TreeSet sort the FilterItems by
+		/// timestamp.
+		/// 
+		/// Removes 1.5 * the numbers of items to make the cache smaller.
+		/// For example:
+		/// If cache clean size is 10, and the cache is at 15, we would remove (15 - 10) * 1.5 = 7.5 round up to 8.
+		/// This way we clean the cache a bit more, and avoid having the cache cleaner having to do it frequently.
+		/// </summary>
+		protected internal class FilterCleaner : IThreadRunnable
+		{
+			private class AnonymousClassComparator : System.Collections.Generic.IComparer<Object>
+			{
+				public AnonymousClassComparator(FilterCleaner enclosingInstance)
+				{
+					InitBlock(enclosingInstance);
+				}
+				private void  InitBlock(FilterCleaner enclosingInstance)
+				{
+					this.enclosingInstance = enclosingInstance;
+				}
+				private FilterCleaner enclosingInstance;
+				public FilterCleaner Enclosing_Instance
+				{
+					get
+					{
+						return enclosingInstance;
+					}
+					
+				}
+				public virtual int Compare(System.Object a, System.Object b)
+				{
+					if (a is System.Collections.DictionaryEntry && b is System.Collections.DictionaryEntry)
+					{
+						FilterItem fia = (FilterItem) ((System.Collections.DictionaryEntry) a).Value;
+						FilterItem fib = (FilterItem) ((System.Collections.DictionaryEntry) b).Value;
+						if (fia.timestamp == fib.timestamp)
+						{
+							return 0;
+						}
+						// smaller timestamp first
+						if (fia.timestamp < fib.timestamp)
+						{
+							return - 1;
+						}
+						// larger timestamp last
+						return 1;
+					}
+					else
+					{
+						throw new System.InvalidCastException("Objects are not Map.Entry");
+					}
+				}
+			}
+			private void  InitBlock(FilterManager enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private FilterManager enclosingInstance;
+			public FilterManager Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			
+			private bool running = true;
+			System.Collections.Generic.SortedDictionary<Object, Object> sortedFilterItems;
+			
+			public FilterCleaner(FilterManager enclosingInstance)
+			{
+				InitBlock(enclosingInstance);
+				sortedFilterItems = new System.Collections.Generic.SortedDictionary<Object, Object>(new AnonymousClassComparator(this));
+			}
+			
+			public virtual void  Run()
+			{
+				while (running)
+				{
+					
+					// sort items from oldest to newest 
+					// we delete the oldest filters 
+					if (Enclosing_Instance.cache.Count > Enclosing_Instance.cacheCleanSize)
+					{
+						// empty the temporary set
+						sortedFilterItems.Clear();
+						lock (Enclosing_Instance.cache.SyncRoot)
+						{
+                            System.Collections.IDictionaryEnumerator entries = Enclosing_Instance.cache.GetEnumerator();
+                            while (entries.MoveNext())
+                            {
+                                sortedFilterItems.Add(entries.Entry.Key, entries.Entry.Value);
+                            }
+							System.Collections.IEnumerator it = sortedFilterItems.GetEnumerator();
+							int numToDelete = (int) ((Enclosing_Instance.cache.Count - Enclosing_Instance.cacheCleanSize) * 1.5);
+							int counter = 0;
+							// loop over the set and delete all of the cache entries not used in a while
+							while (it.MoveNext() && counter++ < numToDelete)
+							{
+								System.Collections.DictionaryEntry entry = (System.Collections.DictionaryEntry) it.Current;
+								Enclosing_Instance.cache.Remove(entry.Key);
+							}
+						}
+						// empty the set so we don't tie up the memory
+						sortedFilterItems.Clear();
+					}
+					// take a nap
+					try
+					{
+						System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * Enclosing_Instance.cleanSleepTime));
+					}
+					catch (System.Threading.ThreadInterruptedException e)
+					{
+						// just keep going
+					}
+				}
+			}
+		}
+	}
+}
\ No newline at end of file

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=671402&r1=671401&r2=671402&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 Tue Jun 24 19:51:24 2008
@@ -37,8 +37,8 @@
 	/// </author>
 	/// <since>   1.4
 	/// </since>
-	/// <version>  $Id: FilteredQuery.java 472959 2006-11-09 16:21:50Z yonik $
-	/// </version>
+    /// <version>  $Id: FilteredQuery.java 544254 2007-06-04 20:41:06Z doronc $
+    /// </version>
 	/// <seealso cref="CachingWrapperFilter">
 	/// </seealso>
 	[Serializable]
@@ -119,13 +119,15 @@
 				
 				public override float Score()
 				{
-					return scorer.Score();
+					return Enclosing_Instance.Enclosing_Instance.GetBoost() * scorer.Score();
 				}
 				
 				// add an explanation about whether the document was filtered
 				public override Explanation Explain(int i)
 				{
 					Explanation exp = scorer.Explain(i);
+					exp.SetValue(Enclosing_Instance.Enclosing_Instance.GetBoost() * exp.GetValue());
+					
 					if (bitset.Get(i))
 						exp.SetDescription("allowed by filter: " + exp.GetDescription());
 					else
@@ -150,23 +152,32 @@
 				}
 				
 			}
+			private float value_Renamed;
 			
 			// pass these methods through to enclosed query's weight
 			public virtual float GetValue()
 			{
-				return weight.GetValue();
-			}
+                return value_Renamed;
+            }
 			public virtual float SumOfSquaredWeights()
 			{
-				return weight.SumOfSquaredWeights();
+				return weight.SumOfSquaredWeights() * Enclosing_Instance.GetBoost() * Enclosing_Instance.GetBoost();
 			}
 			public virtual void  Normalize(float v)
 			{
 				weight.Normalize(v);
+				value_Renamed = weight.GetValue() * Enclosing_Instance.GetBoost();
 			}
 			public virtual Explanation Explain(IndexReader ir, int i)
 			{
 				Explanation inner = weight.Explain(ir, i);
+				if (Enclosing_Instance.GetBoost() != 1)
+				{
+					Explanation preBoost = inner;
+					inner = new Explanation(inner.GetValue() * Enclosing_Instance.GetBoost(), "product of:");
+					inner.AddDetail(new Explanation(Enclosing_Instance.GetBoost(), "boost"));
+					inner.AddDetail(preBoost);
+				}
 				Filter f = Enclosing_Instance.filter;
 				System.Collections.BitArray matches = f.Bits(ir);
 				if (matches.Get(i))

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/ByteFieldSource.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Function/ByteFieldSource.cs?rev=671402&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/ByteFieldSource.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/ByteFieldSource.cs Tue Jun 24 19:51:24 2008
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+using IndexReader = Lucene.Net.Index.IndexReader;
+using FieldCache = Lucene.Net.Search.FieldCache;
+
+namespace Lucene.Net.Search.Function
+{
+	
+	/// <summary> Expert: obtains single byte field values from the 
+	/// {@link Lucene.Net.Search.FieldCache FieldCache}
+	/// using <code>getBytes()</code> and makes those values 
+	/// available as other numeric types, casting as needed.
+	/// 
+	/// <p><font color="#FF0000">
+	/// WARNING: The status of the <b>search.function</b> package is experimental. 
+	/// The APIs introduced here might change in the future and will not be 
+	/// supported anymore in such a case.</font>
+	/// 
+	/// </summary>
+	/// <seealso cref="Lucene.Net.Search.Function.FieldCacheSource for requirements">
+	/// on the field. 
+	/// </seealso>
+	[Serializable]
+	public class ByteFieldSource : FieldCacheSource
+	{
+		private class AnonymousClassDocValues : DocValues
+		{
+			public AnonymousClassDocValues(byte[] arr, ByteFieldSource enclosingInstance)
+			{
+				InitBlock(arr, enclosingInstance);
+			}
+			private void  InitBlock(byte[] arr, ByteFieldSource enclosingInstance)
+			{
+				this.arr = arr;
+				this.enclosingInstance = enclosingInstance;
+			}
+			private byte[] arr;
+			private ByteFieldSource enclosingInstance;
+			public ByteFieldSource Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#floatVal(int) */
+			public override float FloatVal(int doc)
+			{
+				return (float) arr[doc];
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#intVal(int) */
+			public override int IntVal(int doc)
+			{
+				return arr[doc];
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#toString(int) */
+			public override System.String ToString(int doc)
+			{
+				return Enclosing_Instance.Description() + '=' + IntVal(doc);
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#getInnerArray() */
+			internal override System.Object GetInnerArray()
+			{
+				return arr;
+			}
+		}
+		private Lucene.Net.Search.ByteParser parser;
+		
+		/// <summary> Create a cached byte field source with default string-to-byte parser. </summary>
+		public ByteFieldSource(System.String field):this(field, null)
+		{
+		}
+		
+		/// <summary> Create a cached byte field source with a specific string-to-byte parser. </summary>
+		public ByteFieldSource(System.String field, Lucene.Net.Search.ByteParser parser):base(field)
+		{
+			this.parser = parser;
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.ValueSource#description() */
+		public override System.String Description()
+		{
+			return "byte(" + base.Description() + ')';
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.FieldCacheSource#getCachedValues(Lucene.Net.Search.FieldCache, java.lang.String, Lucene.Net.Index.IndexReader) */
+		public override DocValues GetCachedFieldValues(FieldCache cache, System.String field, IndexReader reader)
+		{
+			byte[] arr = (parser == null) ? cache.GetBytes(reader, field) : cache.GetBytes(reader, field, parser);
+			return new AnonymousClassDocValues(arr, this);
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.FieldCacheSource#cachedFieldSourceEquals(Lucene.Net.Search.Function.FieldCacheSource) */
+		public override bool CachedFieldSourceEquals(FieldCacheSource o)
+		{
+			if (o.GetType() != typeof(ByteFieldSource))
+			{
+				return false;
+			}
+			ByteFieldSource other = (ByteFieldSource) o;
+			return this.parser == null ? other.parser == null : this.parser.GetType() == other.parser.GetType();
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.FieldCacheSource#cachedFieldSourceHashCode() */
+		public override int CachedFieldSourceHashCode()
+		{
+			return parser == null ? typeof(System.SByte).GetHashCode() : parser.GetType().GetHashCode();
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/CustomScoreQuery.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Function/CustomScoreQuery.cs?rev=671402&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/CustomScoreQuery.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/CustomScoreQuery.cs Tue Jun 24 19:51:24 2008
@@ -0,0 +1,555 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+using IndexReader = Lucene.Net.Index.IndexReader;
+using ToStringUtils = Lucene.Net.Util.ToStringUtils;
+using ComplexExplanation = Lucene.Net.Search.ComplexExplanation;
+using Explanation = Lucene.Net.Search.Explanation;
+using Query = Lucene.Net.Search.Query;
+using Scorer = Lucene.Net.Search.Scorer;
+using Searcher = Lucene.Net.Search.Searcher;
+using Similarity = Lucene.Net.Search.Similarity;
+using Weight = Lucene.Net.Search.Weight;
+
+namespace Lucene.Net.Search.Function
+{
+	
+	/// <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 ValueSourtceQuery (or queries),
+	/// for most simple/convineient use case this query would be a 
+	/// {@link Lucene.Net.Search.Function.FieldScoreQuery FieldScoreQuery}</li>
+	/// </ol>
+	/// Subclasses can modify the computation by overriding {@link #CustomScore(int, float, float)}.
+	/// 
+	/// <p><font color="#FF0000">
+	/// WARNING: The status of the <b>search.function</b> package is experimental. 
+	/// The APIs introduced here might change in the future and will not be 
+	/// supported anymore in such a case.</font>
+	/// </summary>
+	[Serializable]
+	public class CustomScoreQuery : Query, System.ICloneable
+	{
+		
+		private Query subQuery;
+		private ValueSourceQuery[] valSrcQueries; // 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 customed. Must not be null. 
+		/// </param>
+		public CustomScoreQuery(Query subQuery) : this(subQuery, new ValueSourceQuery[0])
+		{
+		}
+		
+		/// <summary> Create a CustomScoreQuery over input subQuery and a {@link ValueSourceQuery}.</summary>
+		/// <param name="subQuery">the sub query whose score is being customed. Must not be null.
+		/// </param>
+		/// <param name="valSrcQuery">a value source query whose scores are used in the custom score
+		/// computation. For most simple/convineient use case this would be a 
+		/// {@link Lucene.Net.Search.Function.FieldScoreQuery FieldScoreQuery}.
+		/// This parameter is optional - it can be null.
+		/// </param>
+		public CustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) : this(subQuery, valSrcQuery != null ? new ValueSourceQuery[]{valSrcQuery} : new ValueSourceQuery[0])
+		{
+		}
+		
+		/// <summary> Create a CustomScoreQuery over input subQuery and a {@link ValueSourceQuery}.</summary>
+		/// <param name="subQuery">the sub query whose score is being customed. Must not be null.
+		/// </param>
+		/// <param name="valSrcQueries">value source queries whose scores are used in the custom score
+		/// computation. For most simple/convineient use case these would be 
+		/// {@link Lucene.Net.Search.Function.FieldScoreQuery FieldScoreQueries}.
+		/// This parameter is optional - it can be null or even an empty array.
+		/// </param>
+		public CustomScoreQuery(Query subQuery, ValueSourceQuery[] valSrcQueries) : base()
+		{
+			this.subQuery = subQuery;
+			this.valSrcQueries = valSrcQueries != null ? valSrcQueries : new ValueSourceQuery[0];
+			if (subQuery == null)
+				throw new System.ArgumentException("<subquery> must not be null!");
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Query#rewrite(Lucene.Net.Index.IndexReader) */
+		public override Query Rewrite(IndexReader reader)
+		{
+			subQuery = subQuery.Rewrite(reader);
+			for (int i = 0; i < valSrcQueries.Length; i++)
+			{
+				valSrcQueries[i] = (ValueSourceQuery) valSrcQueries[i].Rewrite(reader);
+			}
+			return this;
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Query#extractTerms(java.util.Set) */
+		public override void  ExtractTerms(System.Collections.Hashtable terms)
+		{
+			subQuery.ExtractTerms(terms);
+			for (int i = 0; i < valSrcQueries.Length; i++)
+			{
+				valSrcQueries[i].ExtractTerms(terms);
+			}
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Query#clone() */
+		public override System.Object Clone()
+		{
+			CustomScoreQuery clone = (CustomScoreQuery) base.Clone();
+			clone.subQuery = (Query) subQuery.Clone();
+			clone.valSrcQueries = new ValueSourceQuery[valSrcQueries.Length];
+			for (int i = 0; i < valSrcQueries.Length; i++)
+			{
+				clone.valSrcQueries[i] = (ValueSourceQuery) valSrcQueries[i].Clone();
+			}
+			return clone;
+		}
+		
+		/* (non-Javadoc) @see Lucene.Net.Search.Query#toString(java.lang.String) */
+		public override System.String ToString(System.String field)
+		{
+			System.Text.StringBuilder sb = new System.Text.StringBuilder(Name()).Append("(");
+			sb.Append(subQuery.ToString(field));
+			for (int i = 0; i < valSrcQueries.Length; i++)
+			{
+				sb.Append(", ").Append(valSrcQueries[i].ToString(field));
+			}
+			sb.Append(")");
+			sb.Append(strict ? " STRICT" : "");
+			return sb.ToString() + ToStringUtils.Boost(GetBoost());
+		}
+		
+		/// <summary>Returns true if <code>o</code> is equal to this. </summary>
+		public  override bool Equals(System.Object o)
+		{
+			if (GetType() != o.GetType())
+			{
+				return false;
+			}
+			CustomScoreQuery other = (CustomScoreQuery) o;
+			if (this.GetBoost() != other.GetBoost() || !this.subQuery.Equals(other.subQuery) || this.valSrcQueries.Length != other.valSrcQueries.Length)
+			{
+				return false;
+			}
+			for (int i = 0; i < valSrcQueries.Length; i++)
+			{
+				//TODO simplify with Arrays.deepEquals() once moving to Java 1.5
+				if (!valSrcQueries[i].Equals(other.valSrcQueries[i]))
+				{
+					return false;
+				}
+			}
+			return true;
+		}
+		
+		/// <summary>Returns a hash code value for this object. </summary>
+		public override int GetHashCode()
+		{
+			int valSrcHash = 0;
+			for (int i = 0; i < valSrcQueries.Length; i++)
+			{
+				//TODO simplify with Arrays.deepHashcode() once moving to Java 1.5
+				valSrcHash += valSrcQueries[i].GetHashCode();
+			}
+			return (GetType().GetHashCode() + subQuery.GetHashCode() + valSrcHash) ^ BitConverter.ToInt32(BitConverter.GetBytes(GetBoost()), 0);
+		}
+		
+		/// <summary> Compute a custom score by the subQuery score and a number of 
+		/// ValueSourceQuery scores.
+		/// <p> 
+		/// Subclasses can override this method to modify the custom score.  
+		/// <p>
+		/// 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 ValueSourceQueries is always &lt; 2 it is 
+		/// sufficient to override the other 
+		/// {@link #CustomScore(int, float, float) costomScore()} 
+		/// method, which is simpler. 
+		/// <p>
+		/// The default computation herein is:
+		/// <pre>
+		/// ModifiedScore = valSrcScore * subQueryScore[0] * subQueryScore[1] * ...
+		/// </pre>
+		/// 
+		/// </summary>
+		/// <param name="doc">id of scored doc. 
+		/// </param>
+		/// <param name="subQueryScore">score of that doc by the subQuery.
+		/// </param>
+		/// <param name="valSrcScores">score of that doc by the ValueSourceQuery.
+		/// </param>
+		/// <returns> custom score.
+		/// </returns>
+		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;
+			for (int i = 0; i < valSrcScores.Length; i++)
+			{
+				score *= valSrcScores[i];
+			}
+			return score;
+		}
+		
+		/// <summary> Compute a custom score by the subQuery score and the ValueSourceQuery score.
+		/// <p> 
+		/// Subclasses can override this method to modify the custom score.
+		/// <p>
+		/// 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 ValueSourceQueries is always &lt; 2 it is 
+		/// sufficient to override this costomScore() method, which is simpler. 
+		/// <p>
+		/// The default computation herein is:
+		/// <pre>
+		/// ModifiedScore = valSrcScore * subQueryScore
+		/// </pre>
+		/// 
+		/// </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 ValueSourceQuery.
+		/// </param>
+		/// <returns> custom score.
+		/// </returns>
+		public virtual float CustomScore(int doc, float subQueryScore, float valSrcScore)
+		{
+			return subQueryScore * valSrcScore;
+		}
+		
+		/// <summary> Explain the custom score.
+		/// Whenever overriding {@link #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>
+		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;
+			for (int i = 0; i < valSrcExpls.Length; i++)
+			{
+				valSrcScore *= valSrcExpls[i].GetValue();
+			}
+			Explanation exp = new Explanation(valSrcScore * subQueryExpl.GetValue(), "custom score: product of:");
+			exp.AddDetail(subQueryExpl);
+			for (int i = 0; i < valSrcExpls.Length; i++)
+			{
+				exp.AddDetail(valSrcExpls[i]);
+			}
+			return exp;
+		}
+		
+		/// <summary> Explain the custom score.
+		/// Whenever overriding {@link #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>
+		public virtual Explanation CustomExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl)
+		{
+			float valSrcScore = 1;
+			if (valSrcExpl != null)
+			{
+				valSrcScore *= valSrcExpl.GetValue();
+			}
+			Explanation exp = new Explanation(valSrcScore * subQueryExpl.GetValue(), "custom score: product of:");
+			exp.AddDetail(subQueryExpl);
+			exp.AddDetail(valSrcExpl);
+			return exp;
+		}
+		
+		//=========================== W E I G H T ============================
+		
+		[Serializable]
+		private class CustomWeight : Weight
+		{
+			private void  InitBlock(CustomScoreQuery enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private CustomScoreQuery enclosingInstance;
+			public CustomScoreQuery Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			internal Similarity similarity;
+			internal Weight subQueryWeight;
+			internal Weight[] valSrcWeights;
+			internal bool qStrict;
+			
+			public CustomWeight(CustomScoreQuery enclosingInstance, Searcher searcher)
+			{
+				InitBlock(enclosingInstance);
+				this.similarity = Enclosing_Instance.GetSimilarity(searcher);
+				this.subQueryWeight = Enclosing_Instance.subQuery.Weight(searcher);
+				this.subQueryWeight = Enclosing_Instance.subQuery.Weight(searcher);
+				this.valSrcWeights = new Weight[Enclosing_Instance.valSrcQueries.Length];
+				for (int i = 0; i < Enclosing_Instance.valSrcQueries.Length; i++)
+				{
+					this.valSrcWeights[i] = Enclosing_Instance.valSrcQueries[i].CreateWeight(searcher);
+				}
+				this.qStrict = Enclosing_Instance.strict;
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Weight#getQuery() */
+			public virtual Query GetQuery()
+			{
+				return Enclosing_Instance;
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Weight#getValue() */
+			public virtual float GetValue()
+			{
+				return Enclosing_Instance.GetBoost();
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Weight#sumOfSquaredWeights() */
+			public virtual float SumOfSquaredWeights()
+			{
+				float sum = subQueryWeight.SumOfSquaredWeights();
+				for (int i = 0; i < valSrcWeights.Length; i++)
+				{
+					if (qStrict)
+					{
+						valSrcWeights[i].SumOfSquaredWeights(); // do not include ValueSource part in the query normalization
+					}
+					else
+					{
+						sum += valSrcWeights[i].SumOfSquaredWeights();
+					}
+				}
+				sum *= Enclosing_Instance.GetBoost() * Enclosing_Instance.GetBoost(); // boost each sub-weight
+				return sum;
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Weight#normalize(float) */
+			public virtual void  Normalize(float norm)
+			{
+				norm *= Enclosing_Instance.GetBoost(); // incorporate boost
+				subQueryWeight.Normalize(norm);
+				for (int i = 0; i < valSrcWeights.Length; i++)
+				{
+					if (qStrict)
+					{
+						valSrcWeights[i].Normalize(1); // do not normalize the ValueSource part
+					}
+					else
+					{
+						valSrcWeights[i].Normalize(norm);
+					}
+				}
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Weight#scorer(Lucene.Net.Index.IndexReader) */
+			public virtual Scorer Scorer(IndexReader reader)
+			{
+				Scorer subQueryScorer = subQueryWeight.Scorer(reader);
+				Scorer[] valSrcScorers = new Scorer[valSrcWeights.Length];
+				for (int i = 0; i < valSrcScorers.Length; i++)
+				{
+					valSrcScorers[i] = valSrcWeights[i].Scorer(reader);
+				}
+				return new CustomScorer(enclosingInstance, similarity, reader, this, subQueryScorer, valSrcScorers);
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Weight#explain(Lucene.Net.Index.IndexReader, int) */
+			public virtual Explanation Explain(IndexReader reader, int doc)
+			{
+				return Scorer(reader).Explain(doc);
+			}
+		}
+		
+		
+		//=========================== 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 void  InitBlock(CustomScoreQuery enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private CustomScoreQuery enclosingInstance;
+			public CustomScoreQuery Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			private CustomWeight weight;
+			private float qWeight;
+			private Scorer subQueryScorer;
+			private Scorer[] valSrcScorers;
+			private IndexReader reader;
+			private float[] vScores; // reused in score() to avoid allocating this array for each doc 
+			
+			// constructor
+			internal CustomScorer(CustomScoreQuery enclosingInstance, Similarity similarity, IndexReader reader, CustomWeight w, Scorer subQueryScorer, Scorer[] valSrcScorers) : base(similarity)
+			{
+				InitBlock(enclosingInstance);
+				this.weight = w;
+				this.qWeight = w.GetValue();
+				this.subQueryScorer = subQueryScorer;
+				this.valSrcScorers = valSrcScorers;
+				this.reader = reader;
+				this.vScores = new float[valSrcScorers.Length];
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Scorer#next() */
+			public override bool Next()
+			{
+				bool hasNext = subQueryScorer.Next();
+				if (hasNext)
+				{
+					for (int i = 0; i < valSrcScorers.Length; i++)
+					{
+						valSrcScorers[i].SkipTo(subQueryScorer.Doc());
+					}
+				}
+				return hasNext;
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Scorer#doc() */
+			public override int Doc()
+			{
+				return subQueryScorer.Doc();
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Scorer#score() */
+			public override float Score()
+			{
+				for (int i = 0; i < valSrcScorers.Length; i++)
+				{
+					vScores[i] = valSrcScorers[i].Score();
+				}
+				return qWeight * Enclosing_Instance.CustomScore(subQueryScorer.Doc(), subQueryScorer.Score(), vScores);
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Scorer#skipTo(int) */
+			public override bool SkipTo(int target)
+			{
+				bool hasNext = subQueryScorer.SkipTo(target);
+				if (hasNext)
+				{
+					for (int i = 0; i < valSrcScorers.Length; i++)
+					{
+						valSrcScorers[i].SkipTo(subQueryScorer.Doc());
+					}
+				}
+				return hasNext;
+			}
+			
+			/*(non-Javadoc) @see Lucene.Net.Search.Scorer#explain(int) */
+			public override Explanation Explain(int doc)
+			{
+				Explanation subQueryExpl = weight.subQueryWeight.Explain(reader, doc);
+				if (!subQueryExpl.IsMatch())
+				{
+					return subQueryExpl;
+				}
+				// match
+				Explanation[] valSrcExpls = new Explanation[valSrcScorers.Length];
+				for (int i = 0; i < valSrcScorers.Length; i++)
+				{
+					valSrcExpls[i] = valSrcScorers[i].Explain(doc);
+				}
+				Explanation customExp = Enclosing_Instance.CustomExplain(doc, subQueryExpl, valSrcExpls);
+				float sc = qWeight * customExp.GetValue();
+				Explanation res = new ComplexExplanation(true, sc, Enclosing_Instance.ToString() + ", product of:");
+				res.AddDetail(customExp);
+				res.AddDetail(new Explanation(qWeight, "queryBoost")); // actually using the q boost as q weight (== weight value)
+				return res;
+			}
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Query#createWeight(Lucene.Net.Search.Searcher) */
+		protected internal override Weight CreateWeight(Searcher searcher)
+		{
+			return new CustomWeight(this, searcher);
+		}
+		
+		/// <summary> Checks if this is strict custom scoring.
+		/// In strict custom scoring, the ValueSource part of 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 ValueSource part.
+		/// One particular case where this is useful if for testing this query.   
+		/// <P>
+		/// Note: only has effect when the ValueSource part is not null.
+		/// </summary>
+		public virtual bool IsStrict()
+		{
+			return strict;
+		}
+		
+		/// <summary> Set the strict mode of this query. </summary>
+		/// <param name="strict">The strict mode to set.
+		/// </param>
+		/// <seealso cref="IsStrict()">
+		/// </seealso>
+		public virtual void  SetStrict(bool strict)
+		{
+			this.strict = strict;
+		}
+		
+		/// <summary> A short name of this query, used in {@link #ToString(String)}.</summary>
+		public virtual System.String Name()
+		{
+			return "custom";
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/DocValues.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Function/DocValues.cs?rev=671402&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/DocValues.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/DocValues.cs Tue Jun 24 19:51:24 2008
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+using Explanation = Lucene.Net.Search.Explanation;
+
+namespace Lucene.Net.Search.Function
+{
+	
+	/// <summary> Expert: represents field values as different types.
+	/// Normally created via a 
+	/// {@link Lucene.Net.Search.Function.ValueSource ValueSuorce} 
+	/// for a particular field and reader.
+	/// 
+	/// <p><font color="#FF0000">
+	/// WARNING: The status of the <b>search.function</b> package is experimental. 
+	/// The APIs introduced here might change in the future and will not be 
+	/// supported anymore in such a case.</font>
+	/// 
+	/// 
+	/// </summary>
+	public abstract class DocValues
+	{
+		/*
+		* DocValues 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
+		*/
+		
+		/// <summary> Return doc value as a float. 
+		/// <P>Mandatory: every DocValues implementation must implement at least this method. 
+		/// </summary>
+		/// <param name="doc">document whose float value is requested. 
+		/// </param>
+		public abstract float FloatVal(int doc);
+		
+		/// <summary> Return doc value as an int. 
+		/// <P>Optional: DocValues implementation can (but don't have to) override this method. 
+		/// </summary>
+		/// <param name="doc">document whose int value is requested.
+		/// </param>
+		public virtual int IntVal(int doc)
+		{
+			return (int) FloatVal(doc);
+		}
+		
+		/// <summary> Return doc value as a long. 
+		/// <P>Optional: DocValues implementation can (but don't have to) override this method. 
+		/// </summary>
+		/// <param name="doc">document whose long value is requested.
+		/// </param>
+		public virtual long LongVal(int doc)
+		{
+			return (long) FloatVal(doc);
+		}
+		
+		/// <summary> Return doc value as a double. 
+		/// <P>Optional: DocValues implementation can (but don't have to) override this method. 
+		/// </summary>
+		/// <param name="doc">document whose double value is requested.
+		/// </param>
+		public virtual double DoubleVal(int doc)
+		{
+			return (double) FloatVal(doc);
+		}
+		
+		/// <summary> Return doc value as a string. 
+		/// <P>Optional: DocValues implementation can (but don't have to) override this method. 
+		/// </summary>
+		/// <param name="doc">document whose string value is requested.
+		/// </param>
+		public virtual System.String StrVal(int doc)
+		{
+			return FloatVal(doc).ToString();
+		}
+		
+		/// <summary> Return a string representation of a doc value, as reuired for Explanations.</summary>
+		public abstract System.String ToString(int doc);
+		
+		/// <summary> Explain the scoring value for the input doc.</summary>
+		public virtual Explanation Explain(int doc)
+		{
+			return new Explanation(FloatVal(doc), ToString(doc));
+		}
+		
+		/// <summary> Expert: for test purposes only, return the inner array of values, or null if not applicable.
+		/// <p>
+		/// Allows tests to verify that loaded values are:
+		/// <ol>
+		/// <li>indeed cached/reused.</li>
+		/// <li>stored in the expected size/type (byte/short/int/float).</li>
+		/// </ol>
+		/// Note: implementations of DocValues must override this method for 
+		/// these test elements to be tested, Otherwise the test would not fail, just 
+		/// print a warning.
+		/// </summary>
+		internal virtual System.Object GetInnerArray()
+		{
+			throw new System.NotSupportedException("this optional method is for test purposes only");
+		}
+		
+		// --- some simple statistics on values
+		private float minVal;
+		private float maxVal;
+		private float avgVal;
+		private bool computed = false;
+		// compute optional values
+		private void  Compute()
+		{
+			if (computed)
+			{
+				return ;
+			}
+			minVal = System.Single.MaxValue;
+			maxVal = 0;
+			float sum = 0;
+			int n = 0;
+			while (true)
+			{
+				float val;
+				try
+				{
+					val = FloatVal(n);
+				}
+				catch (System.IndexOutOfRangeException e)
+				{
+					break;
+				}
+				sum += val;
+				minVal = System.Math.Min(minVal, val);
+				maxVal = System.Math.Max(maxVal, val);
+			}
+			avgVal = sum / n;
+			computed = true;
+		}
+		/// <summary> Optional op.
+		/// Returns the minimum of all values.
+		/// </summary>
+		public virtual float GetMinValue()
+		{
+			Compute();
+			return minVal;
+		}
+		
+		/// <summary> Optional op.
+		/// Returns the maximum of all values. 
+		/// </summary>
+		public virtual float GetMaxValue()
+		{
+			Compute();
+			return maxVal;
+		}
+		
+		/// <summary> Returns the average of all values. </summary>
+		public virtual float GetAverageValue()
+		{
+			Compute();
+			return avgVal;
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/FieldCacheSource.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Function/FieldCacheSource.cs?rev=671402&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/FieldCacheSource.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/FieldCacheSource.cs Tue Jun 24 19:51:24 2008
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+using IndexReader = Lucene.Net.Index.IndexReader;
+using FieldCache = Lucene.Net.Search.FieldCache;
+
+namespace Lucene.Net.Search.Function
+{
+	
+	/// <summary> Expert: A base class for ValueSource implementations that retrieve values for
+	/// a single field from the {@link Lucene.Net.Search.FieldCache FieldCache}.
+	/// <p>
+	/// Fields used herein nust be indexed (doesn't matter if these fields are stored or not).
+	/// <p> 
+	/// It is assumed that each such indexed field is untokenized, or at least has a single token in a document.
+	/// For documents with multiple tokens of the same field, behavior is undefined (It is likely that current 
+	/// code would use the value of one of these tokens, but this is not guaranteed).
+	/// <p>
+	/// Document with no tokens in this field are assigned the <code>Zero</code> value.    
+	/// 
+	/// <p><font color="#FF0000">
+	/// WARNING: The status of the <b>search.function</b> package is experimental. 
+	/// The APIs introduced here might change in the future and will not be 
+	/// supported anymore in such a case.</font>
+	/// 
+	/// </summary>
+	/// <author>  yonik
+	/// </author>
+	[Serializable]
+	public abstract class FieldCacheSource : ValueSource
+	{
+		private System.String field;
+		
+		/// <summary> Create a cached field source for the input field.  </summary>
+		public FieldCacheSource(System.String field)
+		{
+			this.field = field;
+		}
+		
+		/* (non-Javadoc) @see Lucene.Net.Search.Function.ValueSource#getValues(Lucene.Net.Index.IndexReader) */
+		public override DocValues GetValues(IndexReader reader)
+		{
+			return GetCachedFieldValues(Lucene.Net.Search.FieldCache_Fields.DEFAULT, field, reader);
+		}
+		
+		/* (non-Javadoc) @see Lucene.Net.Search.Function.ValueSource#description() */
+		public override System.String Description()
+		{
+			return field;
+		}
+		
+		/// <summary> Return cached DocValues for input field and reader.</summary>
+		/// <param name="cache">FieldCache so that values of a field are loaded once per reader (RAM allowing)
+		/// </param>
+		/// <param name="field">Field for which values are required.
+		/// </param>
+		/// <seealso cref="ValueSource">
+		/// </seealso>
+		public abstract DocValues GetCachedFieldValues(FieldCache cache, System.String field, IndexReader reader);
+		
+		/*(non-Javadoc) @see java.lang.Object#equals(java.lang.Object) */
+		public  override bool Equals(System.Object o)
+		{
+			if (!(o is FieldCacheSource))
+			{
+				return false;
+			}
+			FieldCacheSource other = (FieldCacheSource) o;
+			return this.field.Equals(other.field) && CachedFieldSourceEquals(other);
+		}
+		
+		/*(non-Javadoc) @see java.lang.Object#hashCode() */
+		public override int GetHashCode()
+		{
+			return field.GetHashCode() + CachedFieldSourceHashCode();
+		}
+		
+		/// <summary> Check if equals to another {@link FieldCacheSource}, already knowing that cache and field are equal.  </summary>
+		/// <seealso cref="Object.equals(java.lang.Object)">
+		/// </seealso>
+		public abstract bool CachedFieldSourceEquals(FieldCacheSource other);
+		
+		/// <summary> Return a hash code of a {@link FieldCacheSource}, without the hash-codes of the field 
+		/// and the cache (those are taken care of elsewhere).  
+		/// </summary>
+		/// <seealso cref="Object.hashCode()">
+		/// </seealso>
+		public abstract int CachedFieldSourceHashCode();
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/FieldScoreQuery.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Function/FieldScoreQuery.cs?rev=671402&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/FieldScoreQuery.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/FieldScoreQuery.cs Tue Jun 24 19:51:24 2008
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Lucene.Net.Search.Function
+{
+	
+	/// <summary> A query that scores each document as the value of the numeric input field.
+	/// <p> 
+	/// The query matches all documents, and scores each document according to the numeric 
+	/// value of that field. 
+	/// <p>
+	/// It is assumed, and expected, that:
+	/// <ul>
+	/// <li>The field used here is indexed, and has exactly 
+	/// one token in every scored document.</li> 
+	/// <li>Best if this field is un_tokenized.</li>
+	/// <li>That token is parsable to the selected type.</li>
+	/// </ul>
+	/// <p>  
+	/// Combining this query in a FunctionQuery allows much freedom in affecting document scores.
+	/// Note, that with this freedom comes responsibility: it is more than likely that the
+	/// default Lucene scoring is superior in quality to scoring modified as explained here.
+	/// However, in some cases, and certainly for research experiments, this capability may turn useful.
+	/// <p>
+	/// When contructing this query, select the appropriate type. That type should match the data stored in the
+	/// field. So in fact the "right" type should be selected before indexing. Type selection
+	/// has effect on the RAM usage: 
+	/// <ul>
+	/// <li>{@link Type#BYTE} consumes 1 * maxDocs bytes.</li>
+	/// <li>{@link Type#SHORT} consumes 2 * maxDocs bytes.</li>
+	/// <li>{@link Type#INT} consumes 4 * maxDocs bytes.</li>
+	/// <li>{@link Type#FLOAT} consumes 8 * maxDocs bytes.</li>
+	/// </ul>
+	/// <p>
+	/// <b>Caching:</b>
+	/// Values for the numeric field are loaded once and cached in memory for further use with the same IndexReader. 
+	/// To take advantage of this, it is extremely important to reuse index-readers or index-searchers, 
+	/// otherwise, for instance if for each query a new index reader is opened, large penalties would be 
+	/// payd for loading the field values into memory over and over again!
+	/// 
+	/// <p><font color="#FF0000">
+	/// WARNING: The status of the <b>search.function</b> package is experimental. 
+	/// The APIs introduced here might change in the future and will not be 
+	/// supported anymore in such a case.</font>
+	/// </summary>
+	[Serializable]
+	public class FieldScoreQuery : ValueSourceQuery
+	{
+		
+		/// <summary> Type of score field, indicating how field values are interpreted/parsed.  
+		/// <p>
+		/// The type selected at search search time should match the data stored in the field. 
+		/// Different types have different RAM requirements: 
+		/// <ul>
+		/// <li>{@link #BYTE} consumes 1 * maxDocs bytes.</li>
+		/// <li>{@link #SHORT} consumes 2 * maxDocs bytes.</li>
+		/// <li>{@link #INT} consumes 4 * maxDocs bytes.</li>
+		/// <li>{@link #FLOAT} consumes 8 * maxDocs bytes.</li>
+		/// </ul>
+		/// </summary>
+		public class Type
+		{
+			
+			/// <summary>field values are interpreted as numeric byte values. </summary>
+			public static readonly Type BYTE = new Type("byte");
+			
+			/// <summary>field values are interpreted as numeric short values. </summary>
+			public static readonly Type SHORT = new Type("short");
+			
+			/// <summary>field values are interpreted as numeric int values. </summary>
+			public static readonly Type INT = new Type("int");
+			
+			/// <summary>field values are interpreted as numeric float values. </summary>
+			public static readonly Type FLOAT = new Type("float");
+			
+			private System.String typeName;
+			internal Type(System.String name)
+			{
+				this.typeName = name;
+			}
+			/*(non-Javadoc) @see java.lang.Object#toString() */
+			public override System.String ToString()
+			{
+				return GetType().FullName + "::" + typeName;
+			}
+		}
+		
+		/// <summary> Create a FieldScoreQuery - a query that scores each document as the value of the numeric input field.
+		/// <p>
+		/// The <code>type</code> param tells how to parse the field string values into a numeric score value.
+		/// </summary>
+		/// <param name="field">the numeric field to be used.
+		/// </param>
+		/// <param name="type">the type of the field: either
+		/// {@link Type#BYTE}, {@link Type#SHORT}, {@link Type#INT}, or {@link Type#FLOAT}. 
+		/// </param>
+		public FieldScoreQuery(System.String field, Type type) : base(GetValueSource(field, type))
+		{
+		}
+		
+		// create the appropriate (cached) field value source.  
+		private static ValueSource GetValueSource(System.String field, Type type)
+		{
+			if (type == Type.BYTE)
+			{
+				return new ByteFieldSource(field);
+			}
+			if (type == Type.SHORT)
+			{
+				return new ShortFieldSource(field);
+			}
+			if (type == Type.INT)
+			{
+				return new IntFieldSource(field);
+			}
+			if (type == Type.FLOAT)
+			{
+				return new FloatFieldSource(field);
+			}
+			throw new System.ArgumentException(type + " is not a known Field Score Query Type!");
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/FloatFieldSource.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Function/FloatFieldSource.cs?rev=671402&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/FloatFieldSource.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/FloatFieldSource.cs Tue Jun 24 19:51:24 2008
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+using IndexReader = Lucene.Net.Index.IndexReader;
+using FieldCache = Lucene.Net.Search.FieldCache;
+
+namespace Lucene.Net.Search.Function
+{
+	
+	/// <summary> Expert: obtains float field values from the 
+	/// {@link Lucene.Net.Search.FieldCache FieldCache}
+	/// using <code>getFloats()</code> and makes those values 
+	/// available as other numeric types, casting as needed.
+	/// 
+	/// <p><font color="#FF0000">
+	/// WARNING: The status of the <b>search.function</b> package is experimental. 
+	/// The APIs introduced here might change in the future and will not be 
+	/// supported anymore in such a case.</font>
+	/// 
+	/// </summary>
+	/// <seealso cref="Lucene.Net.Search.Function.FieldCacheSource for requirements">
+	/// on the field.
+	/// 
+	/// </seealso>
+	/// <author>  yonik
+	/// </author>
+	[Serializable]
+	public class FloatFieldSource : FieldCacheSource
+	{
+		private class AnonymousClassDocValues : DocValues
+		{
+			public AnonymousClassDocValues(float[] arr, FloatFieldSource enclosingInstance)
+			{
+				InitBlock(arr, enclosingInstance);
+			}
+			private void  InitBlock(float[] arr, FloatFieldSource enclosingInstance)
+			{
+				this.arr = arr;
+				this.enclosingInstance = enclosingInstance;
+			}
+			private float[] arr;
+			private FloatFieldSource enclosingInstance;
+			public FloatFieldSource Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#floatVal(int) */
+			public override float FloatVal(int doc)
+			{
+				return arr[doc];
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#toString(int) */
+			public override System.String ToString(int doc)
+			{
+				return Enclosing_Instance.Description() + '=' + arr[doc];
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#getInnerArray() */
+			internal override System.Object GetInnerArray()
+			{
+				return arr;
+			}
+		}
+		private Lucene.Net.Search.FloatParser parser;
+		
+		/// <summary> Create a cached float field source with default string-to-float parser. </summary>
+		public FloatFieldSource(System.String field) : this(field, null)
+		{
+		}
+		
+		/// <summary> Create a cached float field source with a specific string-to-float parser. </summary>
+		public FloatFieldSource(System.String field, Lucene.Net.Search.FloatParser parser) : base(field)
+		{
+			this.parser = parser;
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.ValueSource#description() */
+		public override System.String Description()
+		{
+			return "float(" + base.Description() + ')';
+		}
+		
+		public override DocValues GetCachedFieldValues(FieldCache cache, System.String field, IndexReader reader)
+		{
+			float[] arr = (parser == null) ? cache.GetFloats(reader, field) : cache.GetFloats(reader, field, parser);
+			return new AnonymousClassDocValues(arr, this);
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.FieldCacheSource#cachedFieldSourceEquals(Lucene.Net.Search.Function.FieldCacheSource) */
+		public override bool CachedFieldSourceEquals(FieldCacheSource o)
+		{
+			if (o.GetType() != typeof(FloatFieldSource))
+			{
+				return false;
+			}
+			FloatFieldSource other = (FloatFieldSource) o;
+			return this.parser == null ? other.parser == null : this.parser.GetType() == other.parser.GetType();
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.FieldCacheSource#cachedFieldSourceHashCode() */
+		public override int CachedFieldSourceHashCode()
+		{
+			return parser == null ? typeof(System.Single).GetHashCode() : parser.GetType().GetHashCode();
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/IntFieldSource.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Function/IntFieldSource.cs?rev=671402&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/IntFieldSource.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/IntFieldSource.cs Tue Jun 24 19:51:24 2008
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+using IndexReader = Lucene.Net.Index.IndexReader;
+using FieldCache = Lucene.Net.Search.FieldCache;
+
+namespace Lucene.Net.Search.Function
+{
+	
+	/// <summary> Expert: obtains int field values from the 
+	/// {@link Lucene.Net.Search.FieldCache FieldCache}
+	/// using <code>getInts()</code> and makes those values 
+	/// available as other numeric types, casting as needed.
+	/// 
+	/// <p><font color="#FF0000">
+	/// WARNING: The status of the <b>search.function</b> package is experimental. 
+	/// The APIs introduced here might change in the future and will not be 
+	/// supported anymore in such a case.</font>
+	/// 
+	/// </summary>
+	/// <seealso cref="Lucene.Net.Search.Function.FieldCacheSource for requirements">
+	/// on the field.
+	/// 
+	/// 
+	/// </seealso>
+	[Serializable]
+	public class IntFieldSource : FieldCacheSource
+	{
+		private class AnonymousClassDocValues : DocValues
+		{
+			public AnonymousClassDocValues(int[] arr, IntFieldSource enclosingInstance)
+			{
+				InitBlock(arr, enclosingInstance);
+			}
+			private void  InitBlock(int[] arr, IntFieldSource enclosingInstance)
+			{
+				this.arr = arr;
+				this.enclosingInstance = enclosingInstance;
+			}
+			private int[] arr;
+			private IntFieldSource enclosingInstance;
+			public IntFieldSource Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#floatVal(int) */
+			public override float FloatVal(int doc)
+			{
+				return (float) arr[doc];
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#intVal(int) */
+			public override int IntVal(int doc)
+			{
+				return arr[doc];
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#toString(int) */
+			public override System.String ToString(int doc)
+			{
+				return Enclosing_Instance.Description() + '=' + IntVal(doc);
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#getInnerArray() */
+			internal override System.Object GetInnerArray()
+			{
+				return arr;
+			}
+		}
+		private Lucene.Net.Search.IntParser parser;
+		
+		/// <summary> Create a cached int field source with default string-to-int parser. </summary>
+		public IntFieldSource(System.String field) : this(field, null)
+		{
+		}
+		
+		/// <summary> Create a cached int field source with a specific string-to-int parser. </summary>
+		public IntFieldSource(System.String field, Lucene.Net.Search.IntParser parser) : base(field)
+		{
+			this.parser = parser;
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.ValueSource#description() */
+		public override System.String Description()
+		{
+			return "int(" + base.Description() + ')';
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.FieldCacheSource#getCachedValues(Lucene.Net.Search.FieldCache, java.lang.String, Lucene.Net.Index.IndexReader) */
+		public override DocValues GetCachedFieldValues(FieldCache cache, System.String field, IndexReader reader)
+		{
+			int[] arr = (parser == null) ? cache.GetInts(reader, field) : cache.GetInts(reader, field, parser);
+			return new AnonymousClassDocValues(arr, this);
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.FieldCacheSource#cachedFieldSourceEquals(Lucene.Net.Search.Function.FieldCacheSource) */
+		public override bool CachedFieldSourceEquals(FieldCacheSource o)
+		{
+			if (o.GetType() != typeof(IntFieldSource))
+			{
+				return false;
+			}
+			IntFieldSource other = (IntFieldSource) o;
+			return this.parser == null ? other.parser == null : this.parser.GetType() == other.parser.GetType();
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.FieldCacheSource#cachedFieldSourceHashCode() */
+		public override int CachedFieldSourceHashCode()
+		{
+			return parser == null ? typeof(System.Int32).GetHashCode() : parser.GetType().GetHashCode();
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/OrdFieldSource.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/Function/OrdFieldSource.cs?rev=671402&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/OrdFieldSource.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/Function/OrdFieldSource.cs Tue Jun 24 19:51:24 2008
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+using System;
+
+using IndexReader = Lucene.Net.Index.IndexReader;
+using FieldCache = Lucene.Net.Search.FieldCache;
+
+namespace Lucene.Net.Search.Function
+{
+	
+	/// <summary> Expert: obtains the ordinal of the field value from the default Lucene 
+	/// {@link Lucene.Net.Search.FieldCache Fieldcache} using getStringIndex().
+	/// <p>
+	/// The native lucene index order is used to assign an ordinal value for each field value.
+	/// <p
+	/// Field values (terms) are lexicographically ordered by unicode value, and numbered starting at 1.
+	/// <p>
+	/// Example:
+	/// <br>If there were only three field values: "apple","banana","pear"
+	/// <br>then ord("apple")=1, ord("banana")=2, ord("pear")=3
+	/// <p>
+	/// 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. 
+	/// 
+	/// <p><font color="#FF0000">
+	/// WARNING: The status of the <b>search.function</b> package is experimental. 
+	/// The APIs introduced here might change in the future and will not be 
+	/// supported anymore in such a case.</font>
+	/// 
+	/// </summary>
+	/// <author>  yonik
+	/// </author>
+	
+	[Serializable]
+	public class OrdFieldSource : ValueSource
+	{
+		private class AnonymousClassDocValues : DocValues
+		{
+			public AnonymousClassDocValues(int[] arr, OrdFieldSource enclosingInstance)
+			{
+				InitBlock(arr, enclosingInstance);
+			}
+			private void  InitBlock(int[] arr, OrdFieldSource enclosingInstance)
+			{
+				this.arr = arr;
+				this.enclosingInstance = enclosingInstance;
+			}
+			private int[] arr;
+			private OrdFieldSource enclosingInstance;
+			public OrdFieldSource Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#floatVal(int) */
+			public override float FloatVal(int doc)
+			{
+				return (float) arr[doc];
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#strVal(int) */
+			public override System.String StrVal(int doc)
+			{
+				// the string value of the ordinal, not the string itself
+				return System.Convert.ToString(arr[doc]);
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#toString(int) */
+			public override System.String ToString(int doc)
+			{
+				return Enclosing_Instance.Description() + '=' + IntVal(doc);
+			}
+			/*(non-Javadoc) @see Lucene.Net.Search.Function.DocValues#getInnerArray() */
+			internal override System.Object GetInnerArray()
+			{
+				return arr;
+			}
+		}
+		protected internal System.String field;
+		
+		/// <summary> Contructor for a certain field.</summary>
+		/// <param name="field">field whose values order is used.  
+		/// </param>
+		public OrdFieldSource(System.String field)
+		{
+			this.field = field;
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.ValueSource#description() */
+		public override System.String Description()
+		{
+			return "ord(" + field + ')';
+		}
+		
+		/*(non-Javadoc) @see Lucene.Net.Search.Function.ValueSource#getValues(Lucene.Net.Index.IndexReader) */
+		public override DocValues GetValues(IndexReader reader)
+		{
+			int[] arr = Lucene.Net.Search.FieldCache_Fields.DEFAULT.GetStringIndex(reader, field).order;
+			return new AnonymousClassDocValues(arr, this);
+		}
+		
+		/*(non-Javadoc) @see java.lang.Object#equals(java.lang.Object) */
+		public  override bool Equals(System.Object o)
+		{
+			if (o.GetType() != typeof(OrdFieldSource))
+				return false;
+			OrdFieldSource other = (OrdFieldSource) o;
+			return this.field.Equals(other.field);
+		}
+		
+		private static readonly int hcode;
+		
+		/*(non-Javadoc) @see java.lang.Object#hashCode() */
+		public override int GetHashCode()
+		{
+			return hcode + field.GetHashCode();
+		}
+		static OrdFieldSource()
+		{
+			hcode = typeof(OrdFieldSource).GetHashCode();
+		}
+	}
+}
\ No newline at end of file