You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2016/11/25 11:07:22 UTC

[17/26] lucenenet git commit: Repaired several issues that were causing tests to fail. Refactored some of the API, added some missing documentation, and set member accessibility on some members.

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Query/SpatialOperation.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Query/SpatialOperation.cs b/src/Lucene.Net.Spatial/Query/SpatialOperation.cs
index 8d33ecf..5f5aa35 100644
--- a/src/Lucene.Net.Spatial/Query/SpatialOperation.cs
+++ b/src/Lucene.Net.Spatial/Query/SpatialOperation.cs
@@ -13,6 +13,7 @@
  * limitations under the License.
  */
 
+using Lucene.Net.Support;
 using Spatial4n.Core.Shapes;
 using System;
 using System.Collections.Generic;
@@ -21,11 +22,21 @@ using System.Linq;
 
 namespace Lucene.Net.Spatial.Queries
 {
+    /// <summary>
+    /// A clause that compares a stored geometry to a supplied geometry. For more
+    /// explanation of each operation, consider looking at the source implementation
+    /// of <see cref="Evaluate(IShape, IShape)"/>.
+    /// <para>
+    /// See <a href="http://edndoc.esri.com/arcsde/9.1/general_topics/understand_spatial_relations.htm">
+    /// ESRIs docs on spatial relations</a>
+    /// </para>
+    /// @lucene.experimental
+    /// </summary>
     [Serializable]
     public abstract class SpatialOperation
     {
         // Private registry
-        private static readonly Dictionary<string, SpatialOperation> registry = new Dictionary<string, SpatialOperation>();
+        private static readonly IDictionary<string, SpatialOperation> registry = new Dictionary<string, SpatialOperation>();
         private static readonly IList<SpatialOperation> list = new List<SpatialOperation>();
 
         // Geometry Operations
@@ -163,7 +174,7 @@ namespace Lucene.Net.Spatial.Queries
             this.sourceNeedsArea = sourceNeedsArea;
             this.targetNeedsArea = targetNeedsArea;
             registry[name] = this;
-            registry[name.ToUpper(CultureInfo.CreateSpecificCulture("en-US"))] = this;
+            registry[name.ToUpper(CultureInfo.InvariantCulture)] = this;
             list.Add(this);
         }
 
@@ -172,15 +183,15 @@ namespace Lucene.Net.Spatial.Queries
             SpatialOperation op;
             if (!registry.TryGetValue(v, out op) || op == null)
             {
-                if (!registry.TryGetValue(v.ToUpper(CultureInfo.CreateSpecificCulture("en-US")), out op) || op == null)
+                if (!registry.TryGetValue(v.ToUpper(CultureInfo.InvariantCulture), out op) || op == null)
                     throw new ArgumentException("Unknown Operation: " + v, "v");
             }
             return op;
         }
 
-        public static IList<SpatialOperation> Values()
+        public static IList<SpatialOperation> Values
         {
-            return list;
+            get { return list; }
         }
 
         public static bool Is(SpatialOperation op, params SpatialOperation[] tst)
@@ -188,26 +199,30 @@ namespace Lucene.Net.Spatial.Queries
             return tst.Any(t => op == t);
         }
 
+        /// <summary>
+        /// Returns whether the relationship between indexedShape and queryShape is
+        /// satisfied by this operation.
+        /// </summary>
         public abstract bool Evaluate(IShape indexedShape, IShape queryShape);
 
         // ================================================= Getters / Setters =============================================
 
-        public bool IsScoreIsMeaningful()
+        public virtual bool IsScoreIsMeaningful
         {
-            return scoreIsMeaningful;
+            get { return scoreIsMeaningful; }
         }
 
-        public bool IsSourceNeedsArea()
+        public virtual bool IsSourceNeedsArea
         {
-            return sourceNeedsArea;
+            get { return sourceNeedsArea; }
         }
 
-        public bool IsTargetNeedsArea()
+        public virtual bool IsTargetNeedsArea
         {
-            return targetNeedsArea;
+            get { return targetNeedsArea; }
         }
 
-        public string Name
+        public virtual string Name
         {
             get { return name; }
         }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Query/UnsupportedSpatialOperation.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Query/UnsupportedSpatialOperation.cs b/src/Lucene.Net.Spatial/Query/UnsupportedSpatialOperation.cs
index 35949bc..e79027f 100644
--- a/src/Lucene.Net.Spatial/Query/UnsupportedSpatialOperation.cs
+++ b/src/Lucene.Net.Spatial/Query/UnsupportedSpatialOperation.cs
@@ -20,7 +20,7 @@ using System;
 namespace Lucene.Net.Spatial.Queries
 {
     [Serializable]
-    public class UnsupportedSpatialOperation : InvalidOperationException
+    public class UnsupportedSpatialOperation : NotSupportedException
     {
         public UnsupportedSpatialOperation(SpatialOperation op)
             : base(op.Name)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Serialized/SerializedDVStrategy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Serialized/SerializedDVStrategy.cs b/src/Lucene.Net.Spatial/Serialized/SerializedDVStrategy.cs
index f3413b2..2358f19 100644
--- a/src/Lucene.Net.Spatial/Serialized/SerializedDVStrategy.cs
+++ b/src/Lucene.Net.Spatial/Serialized/SerializedDVStrategy.cs
@@ -136,11 +136,11 @@ namespace Lucene.Net.Spatial.Serialized
             return new PredicateValueSourceFilter(predicateValueSource);
         }
 
-        /**
-        * Provides access to each shape per document as a ValueSource in which
-        * {@link org.apache.lucene.queries.function.FunctionValues#objectVal(int)} returns a {@link
-        * Shape}.
-        */ //TODO raise to SpatialStrategy
+        /// <summary>
+        /// Provides access to each shape per document as a ValueSource in which
+        /// <see cref="FunctionValues.ObjectVal(int)"/> returns a <see cref="IShape"/>.
+        /// </summary>
+        //TODO raise to SpatialStrategy
         public virtual ValueSource MakeShapeValueSource()
         {
             return new ShapeDocValueSource(this, FieldName, ctx.BinaryCodec);
@@ -148,7 +148,7 @@ namespace Lucene.Net.Spatial.Serialized
 
         /// <summary>
         /// This filter only supports returning a DocSet with a GetBits(). If you try to grab the
-        /// iterator then you'll get an UnsupportedOperationException.
+        /// iterator then you'll get a <see cref="NotSupportedException"/>.
         /// </summary>
         internal class PredicateValueSourceFilter : Filter
         {
@@ -276,10 +276,10 @@ namespace Lucene.Net.Spatial.Serialized
             }
         }//PredicateValueSourceFilter
 
-        /**
-         * Implements a ValueSource by deserializing a Shape in from BinaryDocValues using BinaryCodec.
-         * @see #makeShapeValueSource()
-         */
+        /// <summary>
+        /// Implements a <see cref="ValueSource"/> by deserializing a <see cref="IShape"/> in from <see cref="BinaryDocValues"/> using <see cref="BinaryCodec"/>.
+        /// </summary>
+        /// <seealso cref="MakeShapeValueSource()"/>
         internal class ShapeDocValueSource : ValueSource
         {
             private readonly SerializedDVStrategy outerInstance;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/SpatialStrategy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/SpatialStrategy.cs b/src/Lucene.Net.Spatial/SpatialStrategy.cs
index 5f16c71..3c80f68 100644
--- a/src/Lucene.Net.Spatial/SpatialStrategy.cs
+++ b/src/Lucene.Net.Spatial/SpatialStrategy.cs
@@ -28,11 +28,26 @@ namespace Lucene.Net.Spatial
 {
     /// <summary>
     /// The SpatialStrategy encapsulates an approach to indexing and searching based on shapes.
-    /// <p/>
+    /// <para/>
+    /// Different implementations will support different features. A strategy should
+    /// document these common elements:
+    /// <list type="bullet">
+    ///     <item>Can it index more than one shape per field?</item>
+    ///     <item>What types of shapes can be indexed?</item>
+    ///     <item>What types of query shapes can be used?</item>
+    ///     <item>What types of query operations are supported? This might vary per shape.</item>
+    ///     <item>Does it use the <see cref="FieldCache"/>, or some other type of cache?  When?</item>
+    /// </list>
+    /// If a strategy only supports certain shapes at index or query time, then in
+    /// general it will throw an exception if given an incompatible one.  It will not
+    /// be coerced into compatibility.
+    /// <para/>
     /// Note that a SpatialStrategy is not involved with the Lucene stored field values of shapes, which is
     /// immaterial to indexing and search.
-    /// <p/>
+    /// <para/>
     /// Thread-safe.
+    /// 
+    /// @lucene.experimental
     /// </summary>
     public abstract class SpatialStrategy
     {
@@ -42,8 +57,6 @@ namespace Lucene.Net.Spatial
         /// <summary>
         /// Constructs the spatial strategy with its mandatory arguments.
         /// </summary>
-        /// <param name="ctx"></param>
-        /// <param name="fieldName"> </param>
         protected SpatialStrategy(SpatialContext ctx, string fieldName)
         {
             if (ctx == null)
@@ -54,7 +67,7 @@ namespace Lucene.Net.Spatial
             this.fieldName = fieldName;
         }
 
-        public SpatialContext SpatialContext
+        public virtual SpatialContext SpatialContext
         {
             get { return ctx; }
         }
@@ -64,7 +77,7 @@ namespace Lucene.Net.Spatial
         /// fields needed internally.
         /// </summary>
         /// <returns></returns>
-        public String FieldName
+        public virtual string FieldName
         {
             get { return fieldName; }
         }
@@ -90,7 +103,7 @@ namespace Lucene.Net.Spatial
         /// </summary>
         /// <param name="queryPoint"></param>
         /// <returns></returns>
-        public ValueSource MakeDistanceValueSource(IPoint queryPoint)
+        public virtual ValueSource MakeDistanceValueSource(IPoint queryPoint)
         {
             return MakeDistanceValueSource(queryPoint, 1.0);
         }
@@ -136,8 +149,6 @@ namespace Lucene.Net.Spatial
         /// scores will be 1 for indexed points at the center of the query shape and as
         /// low as ~0.1 at its furthest edges.
         /// </summary>
-        /// <param name="queryShape"></param>
-        /// <returns></returns>
         public ValueSource MakeRecipDistanceValueSource(IShape queryShape)
         {
             IRectangle bbox = queryShape.BoundingBox;
@@ -145,7 +156,7 @@ namespace Lucene.Net.Spatial
                 ctx.MakePoint(bbox.MinX, bbox.MinY), bbox.MaxX, bbox.MaxY);
             double distToEdge = diagonalDist * 0.5;
             float c = (float)distToEdge * 0.1f; //one tenth
-            return new ReciprocalFloatFunction(MakeDistanceValueSource(queryShape.Center), 1f, c, c);
+            return new ReciprocalFloatFunction(MakeDistanceValueSource(queryShape.Center, 1.0), 1f, c, c);
         }
 
         public override string ToString()

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Util/CachingDoubleValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Util/CachingDoubleValueSource.cs b/src/Lucene.Net.Spatial/Util/CachingDoubleValueSource.cs
index 793e10f..a68ed73 100644
--- a/src/Lucene.Net.Spatial/Util/CachingDoubleValueSource.cs
+++ b/src/Lucene.Net.Spatial/Util/CachingDoubleValueSource.cs
@@ -30,9 +30,9 @@ namespace Lucene.Net.Spatial.Util
     /// </summary>
     public class CachingDoubleValueSource : ValueSource
     {
-        protected readonly IDictionary<int, double> cache;
         protected readonly ValueSource source;
-
+        protected readonly IDictionary<int, double> cache;
+        
         public CachingDoubleValueSource(ValueSource source)
         {
             this.source = source;
@@ -51,26 +51,9 @@ namespace Lucene.Net.Spatial.Util
             return new CachingDoubleFunctionValue(@base, vals, cache);
         }
 
-        public override bool Equals(object o)
-        {
-            if (this == o) return true;
-
-            var that = o as CachingDoubleValueSource;
-
-            if (that == null) return false;
-            if (source != null ? !source.Equals(that.source) : that.source != null) return false;
-
-            return true;
-        }
-
-        public override int GetHashCode()
-        {
-            return source != null ? source.GetHashCode() : 0;
-        }
-
         #region Nested type: CachingDoubleFunctionValue
 
-        public class CachingDoubleFunctionValue : FunctionValues
+        internal class CachingDoubleFunctionValue : FunctionValues
         {
             private readonly IDictionary<int, double> cache;
             private readonly int docBase;
@@ -107,5 +90,22 @@ namespace Lucene.Net.Spatial.Util
         }
 
         #endregion
+
+        public override bool Equals(object o)
+        {
+            if (this == o) return true;
+
+            var that = o as CachingDoubleValueSource;
+
+            if (that == null) return false;
+            if (source != null ? !source.Equals(that.source) : that.source != null) return false;
+
+            return true;
+        }
+
+        public override int GetHashCode()
+        {
+            return source != null ? source.GetHashCode() : 0;
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Util/DistanceToShapeValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Util/DistanceToShapeValueSource.cs b/src/Lucene.Net.Spatial/Util/DistanceToShapeValueSource.cs
index 721677c..76fc7bd 100644
--- a/src/Lucene.Net.Spatial/Util/DistanceToShapeValueSource.cs
+++ b/src/Lucene.Net.Spatial/Util/DistanceToShapeValueSource.cs
@@ -65,6 +65,34 @@ namespace Lucene.Net.Spatial.Util
             shapeValueSource.CreateWeight(context, searcher);
         }
 
+        public override FunctionValues GetValues(IDictionary context, AtomicReaderContext readerContext)
+        {
+            FunctionValues shapeValues = shapeValueSource.GetValues(context, readerContext);
+
+            return new DoubleDocValuesAnonymousHelper(this, shapeValues);
+
+            //return new DoubleDocValues(this)
+            //    {
+            //        @Override
+            //  public double doubleVal(int doc)
+            //    {
+            //        Shape shape = (Shape)shapeValues.objectVal(doc);
+            //        if (shape == null || shape.isEmpty())
+            //            return nullValue;
+            //        Point pt = shape.getCenter();
+            //        return distCalc.distance(queryPoint, pt) * multiplier;
+            //    }
+
+            //    @Override
+            //  public Explanation explain(int doc)
+            //    {
+            //        Explanation exp = super.explain(doc);
+            //        exp.addDetail(shapeValues.explain(doc));
+            //        return exp;
+            //    }
+            //};
+        }
+
         internal class DoubleDocValuesAnonymousHelper : DoubleDocValues
         {
             private readonly DistanceToShapeValueSource outerInstance;
@@ -94,34 +122,6 @@ namespace Lucene.Net.Spatial.Util
             }
         }
 
-        public override FunctionValues GetValues(IDictionary context, AtomicReaderContext readerContext)
-        {
-            FunctionValues shapeValues = shapeValueSource.GetValues(context, readerContext);
-
-            return new DoubleDocValuesAnonymousHelper(this, shapeValues);
-
-            //return new DoubleDocValues(this)
-            //    {
-            //        @Override
-            //  public double doubleVal(int doc)
-            //    {
-            //        Shape shape = (Shape)shapeValues.objectVal(doc);
-            //        if (shape == null || shape.isEmpty())
-            //            return nullValue;
-            //        Point pt = shape.getCenter();
-            //        return distCalc.distance(queryPoint, pt) * multiplier;
-            //    }
-
-            //    @Override
-            //  public Explanation explain(int doc)
-            //    {
-            //        Explanation exp = super.explain(doc);
-            //        exp.addDetail(shapeValues.explain(doc));
-            //        return exp;
-            //    }
-            //};
-        }
-
         public override bool Equals(object o)
         {
             if (this == o) return true;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Util/ShapeFieldCache.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Util/ShapeFieldCache.cs b/src/Lucene.Net.Spatial/Util/ShapeFieldCache.cs
index 23d04c4..96cfb3e 100644
--- a/src/Lucene.Net.Spatial/Util/ShapeFieldCache.cs
+++ b/src/Lucene.Net.Spatial/Util/ShapeFieldCache.cs
@@ -23,6 +23,11 @@ namespace Lucene.Net.Spatial.Util
     /// <summary>
     /// Bounded Cache of Shapes associated with docIds.  Note, multiple Shapes can be
     /// associated with a given docId
+    /// <para/>
+    /// WARNING: This class holds the data in an extremely inefficient manner as all Points are in memory as objects and they
+    /// are stored in many ArrayLists (one per document).  So it works but doesn't scale.  It will be replaced in the future.
+    /// <para/>
+    /// @lucene.internal
     /// </summary>
     /// <typeparam name="T"></typeparam>
     public class ShapeFieldCache<T> where T : IShape
@@ -36,7 +41,7 @@ namespace Lucene.Net.Spatial.Util
             this.defaultLength = defaultLength;
         }
 
-        public void Add(int docid, T s)
+        public virtual void Add(int docid, T s)
         {
             IList<T> list = cache[docid];
             if (list == null)
@@ -46,10 +51,9 @@ namespace Lucene.Net.Spatial.Util
             list.Add(s);
         }
 
-        public IList<T> GetShapes(int docid)
+        public virtual IList<T> GetShapes(int docid)
         {
             return cache[docid];
         }
-
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Util/ShapeFieldCacheDistanceValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Util/ShapeFieldCacheDistanceValueSource.cs b/src/Lucene.Net.Spatial/Util/ShapeFieldCacheDistanceValueSource.cs
index c5f4af7..144424e 100644
--- a/src/Lucene.Net.Spatial/Util/ShapeFieldCacheDistanceValueSource.cs
+++ b/src/Lucene.Net.Spatial/Util/ShapeFieldCacheDistanceValueSource.cs
@@ -27,13 +27,18 @@ using Spatial4n.Core.Shapes;
 namespace Lucene.Net.Spatial.Util
 {
     /// <summary>
-    /// An implementation of the Lucene ValueSource model to support spatial relevance ranking.
+    /// An implementation of the Lucene ValueSource that returns the spatial distance
+    /// between an input point and a document's points in
+    /// <see cref="ShapeFieldCacheProvider{T}"/>. The shortest distance is returned if a
+    /// document has more than one point.
+    /// 
+    /// @lucene.internal
     /// </summary>
     public class ShapeFieldCacheDistanceValueSource : ValueSource
     {
-        private readonly ShapeFieldCacheProvider<IPoint> provider;
         private readonly SpatialContext ctx;
         private readonly IPoint from;
+        private readonly ShapeFieldCacheProvider<IPoint> provider;
         private readonly double multiplier;
 
         public ShapeFieldCacheDistanceValueSource(SpatialContext ctx, 
@@ -45,7 +50,17 @@ namespace Lucene.Net.Spatial.Util
             this.multiplier = multiplier;
         }
 
-        public class CachedDistanceFunctionValue : FunctionValues
+        public override string Description
+        {
+            get { return GetType().Name + "(" + provider + ", " + from + ")"; }
+        }
+
+        public override FunctionValues GetValues(IDictionary context, AtomicReaderContext readerContext)
+        {
+            return new CachedDistanceFunctionValue(readerContext.AtomicReader, this);
+        }
+
+        internal class CachedDistanceFunctionValue : FunctionValues
         {
             private readonly ShapeFieldCacheDistanceValueSource enclosingInstance;
             private readonly ShapeFieldCache<IPoint> cache;
@@ -89,22 +104,10 @@ namespace Lucene.Net.Spatial.Util
             }
         }
 
-        public override string Description
-        {
-            get
-            {
-                return GetType().Name + "(" + provider + ", " + from + ")";
-            }
-        }
-
-        public override FunctionValues GetValues(IDictionary context, AtomicReaderContext readerContext)
-        {
-            return new CachedDistanceFunctionValue(readerContext.AtomicReader, this);
-        }
-
         public override bool Equals(object o)
         {
             if (this == o) return true;
+            if (o == null || GetType() != o.GetType()) return false;
 
             var that = o as ShapeFieldCacheDistanceValueSource;
 
@@ -112,6 +115,7 @@ namespace Lucene.Net.Spatial.Util
             if (!ctx.Equals(that.ctx)) return false;
             if (!from.Equals(that.from)) return false;
             if (!provider.Equals(that.provider)) return false;
+            if (multiplier != that.multiplier) return false;
 
             return true;
         }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Util/ShapeFieldCacheProvider.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Util/ShapeFieldCacheProvider.cs b/src/Lucene.Net.Spatial/Util/ShapeFieldCacheProvider.cs
index 1a78210..45cb714 100644
--- a/src/Lucene.Net.Spatial/Util/ShapeFieldCacheProvider.cs
+++ b/src/Lucene.Net.Spatial/Util/ShapeFieldCacheProvider.cs
@@ -14,15 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-using System;
-using System.Runtime.CompilerServices;
 using Lucene.Net.Index;
 using Lucene.Net.Search;
+using Lucene.Net.Support;
 using Lucene.Net.Util;
 using Spatial4n.Core.Shapes;
-#if NET35
-using Lucene.Net.Support;
-#endif
 
 namespace Lucene.Net.Spatial.Util
 {
@@ -30,29 +26,27 @@ namespace Lucene.Net.Spatial.Util
     /// Provides access to a
     /// <see cref="ShapeFieldCache{T}">ShapeFieldCache&lt;T&gt;</see>
     /// for a given
-    /// <see cref="Lucene.Net.Index.AtomicReader">Lucene.Net.Index.AtomicReader
-    /// 	</see>
-    /// .
+    /// <see cref="Lucene.Net.Index.AtomicReader">Lucene.Net.Index.AtomicReader</see>.
+    /// 
     /// If a Cache does not exist for the Reader, then it is built by iterating over
     /// the all terms for a given field, reconstructing the Shape from them, and adding
     /// them to the Cache.
     /// </summary>
-    /// <lucene.internal></lucene.internal>
+    /// @lucene.internal
     public abstract class ShapeFieldCacheProvider<T>
         where T : IShape
     {
         //private Logger log = Logger.GetLogger(GetType().FullName);
 
 #if !NET35
-        private readonly ConditionalWeakTable<IndexReader, ShapeFieldCache<T>> sidx =
-            new ConditionalWeakTable<IndexReader, ShapeFieldCache<T>>(); // WeakHashMap
+        private readonly WeakDictionary<IndexReader, ShapeFieldCache<T>> sidx =
+            new WeakDictionary<IndexReader, ShapeFieldCache<T>>();
 #else
 	    private readonly WeakDictionary<IndexReader, ShapeFieldCache<T>> sidx =
 	        new WeakDictionary<IndexReader, ShapeFieldCache<T>>();
 #endif
 
         protected internal readonly int defaultSize;
-
         protected internal readonly string shapeField;
 
         public ShapeFieldCacheProvider(string shapeField, int defaultSize)
@@ -66,7 +60,6 @@ namespace Lucene.Net.Spatial.Util
 
         private readonly object locker = new object();
 
-        /// <exception cref="System.IO.IOException"></exception>
         public virtual ShapeFieldCache<T> GetCache(AtomicReader reader)
         {
             lock (locker)
@@ -104,7 +97,7 @@ namespace Lucene.Net.Spatial.Util
                         term = te.Next();
                     }
                 }
-                sidx.Add(reader, idx);
+                sidx[reader] = idx;
                 /*long elapsed = Runtime.CurrentTimeMillis() - startTime;
                 log.Fine("Cached: [" + count + " in " + elapsed + "ms] " + idx);*/
                 return idx;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Util/ShapePredicateValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Util/ShapePredicateValueSource.cs b/src/Lucene.Net.Spatial/Util/ShapePredicateValueSource.cs
index fd88f40..7f65893 100644
--- a/src/Lucene.Net.Spatial/Util/ShapePredicateValueSource.cs
+++ b/src/Lucene.Net.Spatial/Util/ShapePredicateValueSource.cs
@@ -65,34 +65,6 @@ namespace Lucene.Net.Spatial.Util
             shapeValuesource.CreateWeight(context, searcher);
         }
 
-        internal class BoolDocValuesAnonymousHelper : BoolDocValues
-        {
-            private readonly ShapePredicateValueSource outerInstance;
-            private readonly FunctionValues shapeValues;
-
-            public BoolDocValuesAnonymousHelper(ShapePredicateValueSource outerInstance, FunctionValues shapeValues)
-                : base(outerInstance)
-            {
-                this.outerInstance = outerInstance;
-                this.shapeValues = shapeValues;
-            }
-
-            public override bool BoolVal(int doc)
-            {
-                IShape indexedShape = (IShape)shapeValues.ObjectVal(doc);
-                if (indexedShape == null)
-                    return false;
-                return outerInstance.op.Evaluate(indexedShape, outerInstance.queryShape);
-            }
-
-            public override Explanation Explain(int doc)
-            {
-                Explanation exp = base.Explain(doc);
-                exp.AddDetail(shapeValues.Explain(doc));
-                return exp;
-            }
-        }
-
         public override FunctionValues GetValues(IDictionary context, AtomicReaderContext readerContext)
         {
             FunctionValues shapeValues = shapeValuesource.GetValues(context, readerContext);
@@ -120,6 +92,33 @@ namespace Lucene.Net.Spatial.Util
             //};
         }
 
+        internal class BoolDocValuesAnonymousHelper : BoolDocValues
+        {
+            private readonly ShapePredicateValueSource outerInstance;
+            private readonly FunctionValues shapeValues;
+
+            public BoolDocValuesAnonymousHelper(ShapePredicateValueSource outerInstance, FunctionValues shapeValues)
+                : base(outerInstance)
+            {
+                this.outerInstance = outerInstance;
+                this.shapeValues = shapeValues;
+            }
+
+            public override bool BoolVal(int doc)
+            {
+                IShape indexedShape = (IShape)shapeValues.ObjectVal(doc);
+                if (indexedShape == null)
+                    return false;
+                return outerInstance.op.Evaluate(indexedShape, outerInstance.queryShape);
+            }
+
+            public override Explanation Explain(int doc)
+            {
+                Explanation exp = base.Explain(doc);
+                exp.AddDetail(shapeValues.Explain(doc));
+                return exp;
+            }
+        }
 
         public override bool Equals(object o)
         {

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Util/ValueSourceFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Util/ValueSourceFilter.cs b/src/Lucene.Net.Spatial/Util/ValueSourceFilter.cs
index bcd73a6..45ffdd6 100644
--- a/src/Lucene.Net.Spatial/Util/ValueSourceFilter.cs
+++ b/src/Lucene.Net.Spatial/Util/ValueSourceFilter.cs
@@ -26,9 +26,12 @@ namespace Lucene.Net.Spatial.Util
     /// <summary>
     /// Filter that matches all documents where a valuesource is
     /// in between a range of <c>min</c> and <c>max</c> inclusive.
+    /// @lucene.internal
     /// </summary>
     public class ValueSourceFilter : Filter
     {
+        //TODO see https://issues.apache.org/jira/browse/LUCENE-4251  (move out of spatial & improve)
+
         readonly Filter startingFilter;
         readonly ValueSource source;
         public readonly double min;
@@ -49,27 +52,26 @@ namespace Lucene.Net.Spatial.Util
         public override DocIdSet GetDocIdSet(AtomicReaderContext context, Bits acceptDocs)
         {
             var values = source.GetValues(null, context);
-            return new ValueSourceFilteredDocIdSet(startingFilter.GetDocIdSet(context, acceptDocs), values, this);
+            return new ValueSourceFilteredDocIdSet(this, startingFilter.GetDocIdSet(context, acceptDocs), values);
         }
 
-        public class ValueSourceFilteredDocIdSet : FilteredDocIdSet
+        internal class ValueSourceFilteredDocIdSet : FilteredDocIdSet
         {
-            private readonly ValueSourceFilter enclosingFilter;
+            private readonly ValueSourceFilter outerInstance;
             private readonly FunctionValues values;
 
-            public ValueSourceFilteredDocIdSet(DocIdSet innerSet, FunctionValues values, ValueSourceFilter caller)
+            public ValueSourceFilteredDocIdSet(ValueSourceFilter outerInstance, DocIdSet innerSet, FunctionValues values)
                 : base(innerSet)
             {
-                this.enclosingFilter = caller;
+                this.outerInstance = outerInstance;
                 this.values = values;
             }
 
             protected override bool Match(int doc)
             {
                 double val = values.DoubleVal(doc);
-                return val >= enclosingFilter.min && val <= enclosingFilter.max;
+                return val >= outerInstance.min && val <= outerInstance.max;
             }
         }
-
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Vector/DistanceValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Vector/DistanceValueSource.cs b/src/Lucene.Net.Spatial/Vector/DistanceValueSource.cs
index 75785f5..a186558 100644
--- a/src/Lucene.Net.Spatial/Vector/DistanceValueSource.cs
+++ b/src/Lucene.Net.Spatial/Vector/DistanceValueSource.cs
@@ -28,7 +28,10 @@ using Spatial4n.Core.Shapes;
 namespace Lucene.Net.Spatial.Vector
 {
     /// <summary>
-    /// An implementation of the Lucene ValueSource model that returns the distance.
+    /// An implementation of the Lucene ValueSource model that returns the distance
+    /// for a <see cref="PointVectorStrategy"/>.
+    /// 
+    /// @lucene.internal
     /// </summary>
     public class DistanceValueSource : ValueSource
     {
@@ -36,6 +39,9 @@ namespace Lucene.Net.Spatial.Vector
         private readonly PointVectorStrategy strategy;
         private readonly double multiplier;
 
+        /// <summary>
+        /// Constructor.
+        /// </summary>
         public DistanceValueSource(PointVectorStrategy strategy, IPoint from, double multiplier)
         {
             this.strategy = strategy;
@@ -43,60 +49,46 @@ namespace Lucene.Net.Spatial.Vector
             this.multiplier = multiplier;
         }
 
+        /// <summary>
+        /// Returns the ValueSource description.
+        /// </summary>
         public override string Description
         {
             get { return "DistanceValueSource(" + strategy + ", " + from + ")"; }
         }
 
+        /// <summary>
+        /// Returns the FunctionValues used by the function query.
+        /// </summary>
         public override FunctionValues GetValues(IDictionary context, AtomicReaderContext readerContext)
         {
             return new DistanceFunctionValue(this, readerContext.AtomicReader);
         }
 
-        public override bool Equals(object o)
-        {
-            if (this == o) return true;
-
-            var that = o as DistanceValueSource;
-            if (that == null) return false;
-
-            if (!from.Equals(that.from)) return false;
-            if (!strategy.Equals(that.strategy)) return false;
-
-            return true;
-        }
-
-        public override int GetHashCode()
-        {
-            return from.GetHashCode();
-        }
-
         #region Nested type: DistanceFunctionValues
 
-        public class DistanceFunctionValue : FunctionValues
+        internal class DistanceFunctionValue : FunctionValues
         {
+            private readonly DistanceValueSource outerInstance;
             private readonly IDistanceCalculator calculator;
-            private readonly DistanceValueSource enclosingInstance;
             private readonly IPoint from;
             private readonly double nullValue;
-            private readonly double multiplier;
 
             private readonly FieldCache.Doubles ptX, ptY;
             private readonly Bits validX, validY;
 
-            public DistanceFunctionValue(DistanceValueSource enclosingInstance, AtomicReader reader)
+            public DistanceFunctionValue(DistanceValueSource outerInstance, AtomicReader reader)
             {
-                this.enclosingInstance = enclosingInstance;
+                this.outerInstance = outerInstance;
 
-                ptX = FieldCache.DEFAULT.GetDoubles(reader, enclosingInstance.strategy.FieldNameX, true);
-                ptY = FieldCache.DEFAULT.GetDoubles(reader, enclosingInstance.strategy.FieldNameY, true);
-                validX = FieldCache.DEFAULT.GetDocsWithField(reader, enclosingInstance.strategy.FieldNameX);
-                validY = FieldCache.DEFAULT.GetDocsWithField(reader, enclosingInstance.strategy.FieldNameY);
+                ptX = FieldCache.DEFAULT.GetDoubles(reader, outerInstance.strategy.FieldNameX, true);
+                ptY = FieldCache.DEFAULT.GetDoubles(reader, outerInstance.strategy.FieldNameY, true);
+                validX = FieldCache.DEFAULT.GetDocsWithField(reader, outerInstance.strategy.FieldNameX);
+                validY = FieldCache.DEFAULT.GetDocsWithField(reader, outerInstance.strategy.FieldNameY);
 
-                from = enclosingInstance.from;
-                multiplier = enclosingInstance.multiplier;
-                calculator = enclosingInstance.strategy.SpatialContext.DistCalc;
-                nullValue = (enclosingInstance.strategy.SpatialContext.IsGeo ? 180 * multiplier : double.MaxValue);
+                from = outerInstance.from;
+                calculator = outerInstance.strategy.SpatialContext.DistCalc;
+                nullValue = (outerInstance.strategy.SpatialContext.IsGeo ? 180 * outerInstance.multiplier : double.MaxValue);
             }
 
             public override float FloatVal(int doc)
@@ -110,17 +102,37 @@ namespace Lucene.Net.Spatial.Vector
                 if (validX.Get(doc))
                 {
                     Debug.Assert(validY.Get(doc));
-                    return calculator.Distance(from, ptX.Get(doc), ptY.Get(doc)) * multiplier;
+                    return calculator.Distance(outerInstance.from, ptX.Get(doc), ptY.Get(doc)) * outerInstance.multiplier;
                 }
                 return nullValue;
             }
 
             public override string ToString(int doc)
             {
-                return enclosingInstance.Description + "=" + FloatVal(doc);
+                return outerInstance.Description + "=" + FloatVal(doc);
             }
         }
 
         #endregion
+
+        public override bool Equals(object o)
+        {
+            if (this == o) return true;
+            if (o == null || GetType() != o.GetType()) return false;
+
+            var that = o as DistanceValueSource;
+            if (that == null) return false;
+
+            if (!from.Equals(that.from)) return false;
+            if (!strategy.Equals(that.strategy)) return false;
+            if (multiplier != that.multiplier) return false;
+
+            return true;
+        }
+
+        public override int GetHashCode()
+        {
+            return from.GetHashCode();
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Spatial/Vector/PointVectorStrategy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Spatial/Vector/PointVectorStrategy.cs b/src/Lucene.Net.Spatial/Vector/PointVectorStrategy.cs
index dcbe259..d46bff0 100644
--- a/src/Lucene.Net.Spatial/Vector/PointVectorStrategy.cs
+++ b/src/Lucene.Net.Spatial/Vector/PointVectorStrategy.cs
@@ -27,26 +27,26 @@ using Spatial4n.Core.Shapes;
 namespace Lucene.Net.Spatial.Vector
 {
     /// <summary>
-    /// Simple {@link SpatialStrategy} which represents Points in two numeric {@link DoubleField}s.
+    /// Simple <see cref="SpatialStrategy"/> which represents Points in two numeric <see cref="DoubleField"/>s.
     /// 
     /// Note, currently only Points can be indexed by this Strategy.  At query time, the bounding
-    /// box of the given Shape is used to create {@link NumericRangeQuery}s to efficiently
+    /// box of the given Shape is used to create <see cref="NumericRangeQuery"/>s to efficiently
     /// find Points within the Shape.
     /// 
     /// Due to the simple use of numeric fields, this Strategy provides support for sorting by
-    /// distance through {@link DistanceValueSource}
+    /// distance through <see cref="DistanceValueSource"/>
     /// </summary>
     public class PointVectorStrategy : SpatialStrategy
     {
-        public static String SUFFIX_X = "__x";
-        public static String SUFFIX_Y = "__y";
+        public static string SUFFIX_X = "__x";
+        public static string SUFFIX_Y = "__y";
 
-        private readonly String fieldNameX;
-        private readonly String fieldNameY;
+        private readonly string fieldNameX;
+        private readonly string fieldNameY;
 
         public int precisionStep = 8; // same as solr default
 
-        public PointVectorStrategy(SpatialContext ctx, String fieldNamePrefix)
+        public PointVectorStrategy(SpatialContext ctx, string fieldNamePrefix)
             : base(ctx, fieldNamePrefix)
         {
             this.fieldNameX = fieldNamePrefix + SUFFIX_X;
@@ -79,20 +79,23 @@ namespace Lucene.Net.Spatial.Vector
             if (point != null)
                 return CreateIndexableFields(point);
 
-            throw new InvalidOperationException("Can only index Point, not " + shape);
+            throw new NotSupportedException("Can only index IPoint, not " + shape);
         }
 
+        /// <summary>
+        /// See <see cref="CreateIndexableFields(IShape)"/>
+        /// </summary>
         public Field[] CreateIndexableFields(IPoint point)
         {
             FieldType doubleFieldType = new FieldType(DoubleField.TYPE_NOT_STORED)
-                                            {
-                                                NumericPrecisionStep = precisionStep
-                                            };
-            var f = new Field[]
-                        {
-                            new DoubleField(fieldNameX, point.X, doubleFieldType),
-                            new DoubleField(fieldNameY, point.Y, doubleFieldType)
-                        };
+            {
+                NumericPrecisionStep = precisionStep
+            };
+            var f = new Field[2]
+            {
+                new DoubleField(fieldNameX, point.X, doubleFieldType),
+                new DoubleField(fieldNameY, point.Y, doubleFieldType)
+            };
             return f;
         }
 
@@ -101,22 +104,36 @@ namespace Lucene.Net.Spatial.Vector
             return new DistanceValueSource(this, queryPoint, multiplier);
         }
 
+        public override Filter MakeFilter(SpatialArgs args)
+        {
+            //unwrap the CSQ from makeQuery
+            ConstantScoreQuery csq = MakeQuery(args);
+            Filter filter = csq.Filter;
+            if (filter != null)
+                return filter;
+            else
+                return new QueryWrapperFilter(csq.Query);
+        }
+
         public override ConstantScoreQuery MakeQuery(SpatialArgs args)
         {
             if (!SpatialOperation.Is(args.Operation,
-                                     SpatialOperation.Intersects,
-                                     SpatialOperation.IsWithin))
+                SpatialOperation.Intersects,
+                SpatialOperation.IsWithin))
+            {
                 throw new UnsupportedSpatialOperation(args.Operation);
+            }
 
             IShape shape = args.Shape;
-            var bbox = shape as IRectangle;
-            if (bbox != null)
-                return new ConstantScoreQuery(new QueryWrapperFilter(MakeWithin(bbox)));
-
-            var circle = shape as ICircle;
-            if (circle != null)
+            if (shape is IRectangle)
             {
-                bbox = circle.BoundingBox;
+                var bbox = (IRectangle)shape;
+                return new ConstantScoreQuery(MakeWithin(bbox));
+            }
+            else if (shape is ICircle)
+            {
+                var circle = (ICircle)shape;
+                var bbox = circle.BoundingBox;
                 var vsf = new ValueSourceFilter(
                     new QueryWrapperFilter(MakeWithin(bbox)),
                     MakeDistanceValueSource(circle.Center),
@@ -124,29 +141,29 @@ namespace Lucene.Net.Spatial.Vector
                     circle.Radius);
                 return new ConstantScoreQuery(vsf);
             }
-
-            throw new NotSupportedException("Only Rectangles and Circles are currently supported, " +
+            
+            throw new NotSupportedException("Only IRectangles and ICircles are currently supported, " +
                                             "found [" + shape.GetType().Name + "]"); //TODO
         }
 
         //TODO this is basically old code that hasn't been verified well and should probably be removed
-        public Search.Query MakeQueryDistanceScore(SpatialArgs args)
+        public Query MakeQueryDistanceScore(SpatialArgs args)
         {
             // For starters, just limit the bbox
             var shape = args.Shape;
             if (!(shape is IRectangle || shape is ICircle))
-                throw new InvalidOperationException("Only Rectangles and Circles are currently supported, found ["
+                throw new NotSupportedException("Only Rectangles and Circles are currently supported, found ["
                     + shape.GetType().Name + "]");//TODO
 
             IRectangle bbox = shape.BoundingBox;
             if (bbox.CrossesDateLine)
             {
-                throw new InvalidOperationException("Crossing dateline not yet supported");
+                throw new NotSupportedException("Crossing dateline not yet supported");
             }
 
             ValueSource valueSource = null;
 
-            Search.Query spatial = null;
+            Query spatial = null;
             SpatialOperation op = args.Operation;
 
             if (SpatialOperation.Is(op,
@@ -160,9 +177,10 @@ namespace Lucene.Net.Spatial.Vector
               SpatialOperation.IsWithin))
             {
                 spatial = MakeWithin(bbox);
-                var circle = args.Shape as ICircle;
-                if (circle != null)
+                if (args.Shape is ICircle)
                 {
+                    var circle = (ICircle)args.Shape;
+
                     // Make the ValueSource
                     valueSource = MakeDistanceValueSource(shape.Center);
 
@@ -190,30 +208,17 @@ namespace Lucene.Net.Spatial.Vector
             {
                 valueSource = MakeDistanceValueSource(shape.Center);
             }
-            Search.Query spatialRankingQuery = new FunctionQuery(valueSource);
+            Query spatialRankingQuery = new FunctionQuery(valueSource);
             var bq = new BooleanQuery();
             bq.Add(spatial, BooleanClause.Occur.MUST);
             bq.Add(spatialRankingQuery, BooleanClause.Occur.MUST);
             return bq;
-
-        }
-
-        public override Filter MakeFilter(SpatialArgs args)
-        {
-            //unwrap the CSQ from makeQuery
-            ConstantScoreQuery csq = MakeQuery(args);
-            Filter filter = csq.Filter;
-            if (filter != null)
-                return filter;
-            else
-                return new QueryWrapperFilter(csq);
         }
 
         /// <summary>
         /// Constructs a query to retrieve documents that fully contain the input envelope.
         /// </summary>
-        /// <param name="bbox"></param>
-        private Search.Query MakeWithin(IRectangle bbox)
+        private Query MakeWithin(IRectangle bbox)
         {
             var bq = new BooleanQuery();
             const BooleanClause.Occur MUST = BooleanClause.Occur.MUST;
@@ -232,7 +237,7 @@ namespace Lucene.Net.Spatial.Vector
             return bq;
         }
 
-        private NumericRangeQuery<Double> RangeQuery(String fieldName, double? min, double? max)
+        private NumericRangeQuery<double> RangeQuery(string fieldName, double? min, double? max)
         {
             return NumericRangeQuery.NewDoubleRange(
                 fieldName,
@@ -246,14 +251,16 @@ namespace Lucene.Net.Spatial.Vector
         /// <summary>
         /// Constructs a query to retrieve documents that fully contain the input envelope.
         /// </summary>
-        /// <param name="bbox"></param>
-        private Search.Query MakeDisjoint(IRectangle bbox)
+        private Query MakeDisjoint(IRectangle bbox)
         {
             if (bbox.CrossesDateLine)
-                throw new InvalidOperationException("MakeDisjoint doesn't handle dateline cross");
-            Search.Query qX = RangeQuery(fieldNameX, bbox.MinX, bbox.MaxX);
-            Search.Query qY = RangeQuery(fieldNameY, bbox.MinY, bbox.MaxY);
-            var bq = new BooleanQuery { { qX, BooleanClause.Occur.MUST_NOT }, { qY, BooleanClause.Occur.MUST_NOT } };
+                throw new NotSupportedException("MakeDisjoint doesn't handle dateline cross");
+            Query qX = RangeQuery(fieldNameX, bbox.MinX, bbox.MaxX);
+            Query qY = RangeQuery(fieldNameY, bbox.MinY, bbox.MaxY);
+
+            var bq = new BooleanQuery();
+            bq.Add(qX, BooleanClause.Occur.MUST_NOT);
+            bq.Add(qY, BooleanClause.Occur.MUST_NOT);
             return bq;
         }
     }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/df3f64d7/src/Lucene.Net.Tests.Spatial/Prefix/SpatialOpRecursivePrefixTreeTest.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Spatial/Prefix/SpatialOpRecursivePrefixTreeTest.cs b/src/Lucene.Net.Tests.Spatial/Prefix/SpatialOpRecursivePrefixTreeTest.cs
index d7d3fb7..d73667d 100644
--- a/src/Lucene.Net.Tests.Spatial/Prefix/SpatialOpRecursivePrefixTreeTest.cs
+++ b/src/Lucene.Net.Tests.Spatial/Prefix/SpatialOpRecursivePrefixTreeTest.cs
@@ -422,6 +422,7 @@ namespace Lucene.Net.Spatial.Prefix
             public ShapePair(IShape shape1, IShape shape2, bool containsThenWithin, SpatialContext ctx)
                         : base(Arrays.AsList(shape1, shape2), ctx)
             {
+                this.ctx = ctx;
 
                 this.shape1 = shape1;
                 this.shape2 = shape2;