lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From paulir...@apache.org
Subject [10/53] [abbrv] git commit: Finish Contrib.QueryParsers and Sandbox
Date Thu, 07 Nov 2013 13:53:25 GMT
Finish Contrib.QueryParsers and Sandbox


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/b43f529b
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/b43f529b
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/b43f529b

Branch: refs/heads/branch_4x
Commit: b43f529b0547f6ccd70d00a7ff1017bb94b80baa
Parents: 21ac0fa
Author: Paul Irwin <paulirwin@gmail.com>
Authored: Fri Oct 25 17:23:39 2013 -0400
Committer: Paul Irwin <paulirwin@gmail.com>
Committed: Fri Oct 25 17:23:39 2013 -0400

----------------------------------------------------------------------
 build/vs2012/Lucene.Net.All/Lucene.Net.All.sln  |  11 +
 src/contrib/Queries/Mlt/MoreLikeThisQuery.cs    |   8 +-
 .../QueryParsers/Contrib.QueryParsers.csproj    |  30 ++
 .../QueryParsers/Support/StringExtensions.cs    |   5 +
 .../Xml/Builders/BoostingQueryBuilder.cs        |  35 +++
 .../Xml/Builders/BoostingTermBuilder.cs         |  23 ++
 .../Xml/Builders/CachedFilterBuilder.cs         |  82 +++++
 .../Xml/Builders/ConstantScoreQueryBuilder.cs   |  27 ++
 .../Xml/Builders/DisjunctionMaxQueryBuilder.cs  |  38 +++
 .../Xml/Builders/DuplicateFilterBuilder.cs      |  49 +++
 .../Xml/Builders/FilteredQueryBuilder.cs        |  34 ++
 .../Xml/Builders/FuzzyLikeThisQueryBuilder.cs   |  45 +++
 .../Xml/Builders/ISpanQueryBuilder.cs           |  14 +
 .../Xml/Builders/LikeThisQueryBuilder.cs        |  83 +++++
 .../Xml/Builders/MatchAllDocsQueryBuilder.cs    |  17 +
 .../Xml/Builders/NumericRangeFilterBuilder.cs   |  77 +++++
 .../Xml/Builders/NumericRangeQueryBuilder.cs    |  55 ++++
 .../Xml/Builders/RangeFilterBuilder.cs          |  22 ++
 .../Xml/Builders/SpanBuilderBase.cs             |  20 ++
 .../Xml/Builders/SpanFirstBuilder.cs            |  29 ++
 .../Xml/Builders/SpanNearBuilder.cs             |  38 +++
 .../QueryParsers/Xml/Builders/SpanNotBuilder.cs |  32 ++
 .../QueryParsers/Xml/Builders/SpanOrBuilder.cs  |  38 +++
 .../Xml/Builders/SpanOrTermsBuilder.cs          |  54 ++++
 .../Xml/Builders/SpanQueryBuilderFactory.cs     |  37 +++
 .../Xml/Builders/SpanTermBuilder.cs             |  22 ++
 .../Xml/Builders/TermQueryBuilder.cs            |  22 ++
 .../Xml/Builders/TermsFilterBuilder.cs          |  53 ++++
 .../Xml/Builders/TermsQueryBuilder.cs           |  56 ++++
 .../Xml/Builders/UserInputQueryBuilder.cs       |  63 ++++
 src/contrib/QueryParsers/Xml/CoreParser.cs      |  15 +-
 src/contrib/QueryParsers/Xml/DOMUtils.cs        |   2 +-
 src/contrib/QueryParsers/Xml/IFilterBuilder.cs  |   2 +-
 src/contrib/QueryParsers/Xml/IQueryBuilder.cs   |   2 +-
 src/contrib/Sandbox/Contrib.Sandbox.csproj      |  68 ++++
 src/contrib/Sandbox/Properties/AssemblyInfo.cs  |  36 +++
 src/contrib/Sandbox/Queries/DuplicateFilter.cs  | 222 +++++++++++++
 .../Sandbox/Queries/FuzzyLikeThisQuery.cs       | 315 +++++++++++++++++++
 .../Queries/SlowCollatedStringComparer.cs       | 135 ++++++++
 .../Queries/SlowCollatedTermRangeFilter.cs      |  41 +++
 .../Queries/SlowCollatedTermRangeQuery.cs       | 145 +++++++++
 .../Queries/SlowCollatedTermRangeTermsEnum.cs   |  46 +++
 src/contrib/Sandbox/Queries/SlowFuzzyQuery.cs   | 136 ++++++++
 .../Sandbox/Queries/SlowFuzzyTermsEnum.cs       | 142 +++++++++
 src/core/Search/FuzzyTermsEnum.cs               |   4 +-
 45 files changed, 2412 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/build/vs2012/Lucene.Net.All/Lucene.Net.All.sln
----------------------------------------------------------------------
diff --git a/build/vs2012/Lucene.Net.All/Lucene.Net.All.sln b/build/vs2012/Lucene.Net.All/Lucene.Net.All.sln
index 0b9121d..dfa5f05 100644
--- a/build/vs2012/Lucene.Net.All/Lucene.Net.All.sln
+++ b/build/vs2012/Lucene.Net.All/Lucene.Net.All.sln
@@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contrib.WordNet.Syns2Index"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contrib.QueryParsers", "..\..\..\src\contrib\QueryParsers\Contrib.QueryParsers.csproj", "{56438272-B00E-40DE-9C9A-0785E705E7D9}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contrib.Sandbox", "..\..\..\src\contrib\Sandbox\Contrib.Sandbox.csproj", "{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -183,6 +185,14 @@ Global
 		{56438272-B00E-40DE-9C9A-0785E705E7D9}.Release|Any CPU.Build.0 = Release|Any CPU
 		{56438272-B00E-40DE-9C9A-0785E705E7D9}.Release35|Any CPU.ActiveCfg = Release|Any CPU
 		{56438272-B00E-40DE-9C9A-0785E705E7D9}.Release35|Any CPU.Build.0 = Release|Any CPU
+		{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}.Debug35|Any CPU.ActiveCfg = Debug|Any CPU
+		{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}.Debug35|Any CPU.Build.0 = Debug|Any CPU
+		{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}.Release35|Any CPU.ActiveCfg = Release|Any CPU
+		{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}.Release35|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -205,5 +215,6 @@ Global
 		{2CA12E3F-76E1-4FA6-9E87-37079A7B7C69} = {7E19085A-545B-4DE8-BBF5-B1DBC370FD37}
 		{7563D4D9-AE91-42BA-A270-1D264660F6DF} = {7E19085A-545B-4DE8-BBF5-B1DBC370FD37}
 		{56438272-B00E-40DE-9C9A-0785E705E7D9} = {7E19085A-545B-4DE8-BBF5-B1DBC370FD37}
+		{1DE43B60-4041-4A2E-9717-5B4CA891D0FD} = {7E19085A-545B-4DE8-BBF5-B1DBC370FD37}
 	EndGlobalSection
 EndGlobal

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/Queries/Mlt/MoreLikeThisQuery.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Queries/Mlt/MoreLikeThisQuery.cs b/src/contrib/Queries/Mlt/MoreLikeThisQuery.cs
index dc2a05c..94c6778 100644
--- a/src/contrib/Queries/Mlt/MoreLikeThisQuery.cs
+++ b/src/contrib/Queries/Mlt/MoreLikeThisQuery.cs
@@ -48,16 +48,12 @@ namespace Lucene.Net.Search.Mlt
         private int minDocFreq = -1;
 
 
-        /*<summary></summary>
-         * <param name="moreLikeFields"></param>
-         * <param name="likeText"></param>
-         * <param name="analyzer"></param>
-         */
-        public MoreLikeThisQuery(string likeText, string[] moreLikeFields, Analyzer analyzer)
+        public MoreLikeThisQuery(String likeText, String[] moreLikeFields, Analyzer analyzer, String fieldName)
         {
             this.likeText = likeText;
             this.moreLikeFields = moreLikeFields;
             this.analyzer = analyzer;
+            this.fieldName = fieldName;
         }
 
         public override Query Rewrite(IndexReader reader)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Contrib.QueryParsers.csproj
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Contrib.QueryParsers.csproj b/src/contrib/QueryParsers/Contrib.QueryParsers.csproj
index e70187f..421620c 100644
--- a/src/contrib/QueryParsers/Contrib.QueryParsers.csproj
+++ b/src/contrib/QueryParsers/Contrib.QueryParsers.csproj
@@ -214,6 +214,32 @@
     <Compile Include="Surround\Query\TooManyBasicQueries.cs" />
     <Compile Include="Xml\Builders\BooleanFilterBuilder.cs" />
     <Compile Include="Xml\Builders\BooleanQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\BoostingQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\BoostingTermBuilder.cs" />
+    <Compile Include="Xml\Builders\CachedFilterBuilder.cs" />
+    <Compile Include="Xml\Builders\ConstantScoreQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\DisjunctionMaxQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\DuplicateFilterBuilder.cs" />
+    <Compile Include="Xml\Builders\FilteredQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\FuzzyLikeThisQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\ISpanQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\LikeThisQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\MatchAllDocsQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\NumericRangeFilterBuilder.cs" />
+    <Compile Include="Xml\Builders\NumericRangeQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\RangeFilterBuilder.cs" />
+    <Compile Include="Xml\Builders\SpanBuilderBase.cs" />
+    <Compile Include="Xml\Builders\SpanFirstBuilder.cs" />
+    <Compile Include="Xml\Builders\SpanNearBuilder.cs" />
+    <Compile Include="Xml\Builders\SpanNotBuilder.cs" />
+    <Compile Include="Xml\Builders\SpanOrBuilder.cs" />
+    <Compile Include="Xml\Builders\SpanOrTermsBuilder.cs" />
+    <Compile Include="Xml\Builders\SpanQueryBuilderFactory.cs" />
+    <Compile Include="Xml\Builders\SpanTermBuilder.cs" />
+    <Compile Include="Xml\Builders\TermQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\TermsFilterBuilder.cs" />
+    <Compile Include="Xml\Builders\TermsQueryBuilder.cs" />
+    <Compile Include="Xml\Builders\UserInputQueryBuilder.cs" />
     <Compile Include="Xml\CoreParser.cs" />
     <Compile Include="Xml\CorePlusExtensionsParser.cs" />
     <Compile Include="Xml\DOMUtils.cs" />
@@ -233,6 +259,10 @@
       <Project>{481cf6e3-52af-4621-9deb-022122079af6}</Project>
       <Name>Contrib.Queries</Name>
     </ProjectReference>
+    <ProjectReference Include="..\Sandbox\Contrib.Sandbox.csproj">
+      <Project>{1de43b60-4041-4a2e-9717-5b4ca891d0fd}</Project>
+      <Name>Contrib.Sandbox</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Support/StringExtensions.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Support/StringExtensions.cs b/src/contrib/QueryParsers/Support/StringExtensions.cs
index c688e67..566f2e8 100644
--- a/src/contrib/QueryParsers/Support/StringExtensions.cs
+++ b/src/contrib/QueryParsers/Support/StringExtensions.cs
@@ -12,5 +12,10 @@ namespace Lucene.Net.QueryParsers.Support
         {
             return string.Equals(value, other, StringComparison.OrdinalIgnoreCase);
         }
+
+        public static bool EqualsIgnoreCase(this object value, string other)
+        {
+            return string.Equals((value == null ? null : value.ToString()), other, StringComparison.OrdinalIgnoreCase);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/BoostingQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/BoostingQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/BoostingQueryBuilder.cs
new file mode 100644
index 0000000..2b2ebd8
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/BoostingQueryBuilder.cs
@@ -0,0 +1,35 @@
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class BoostingQueryBuilder : IQueryBuilder
+    {
+        private const float DEFAULT_BOOST = 0.01f;
+
+        private readonly IQueryBuilder factory;
+
+        public BoostingQueryBuilder(IQueryBuilder factory)
+        {
+            this.factory = factory;
+        }
+
+        public Query GetQuery(XElement e)
+        {
+            XElement mainQueryElem = DOMUtils.GetChildByTagOrFail(e, "Query");
+            mainQueryElem = DOMUtils.GetFirstChildOrFail(mainQueryElem);
+            Query mainQuery = factory.GetQuery(mainQueryElem);
+            XElement boostQueryElem = DOMUtils.GetChildByTagOrFail(e, "BoostQuery");
+            float boost = DOMUtils.GetAttribute(boostQueryElem, "boost", DEFAULT_BOOST);
+            boostQueryElem = DOMUtils.GetFirstChildOrFail(boostQueryElem);
+            Query boostQuery = factory.GetQuery(boostQueryElem);
+            BoostingQuery bq = new BoostingQuery(mainQuery, boostQuery, boost);
+            bq.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+            return bq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/BoostingTermBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/BoostingTermBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/BoostingTermBuilder.cs
new file mode 100644
index 0000000..781f2f3
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/BoostingTermBuilder.cs
@@ -0,0 +1,23 @@
+using Lucene.Net.Index;
+using Lucene.Net.Search.Payloads;
+using Lucene.Net.Search.Spans;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class BoostingTermBuilder : SpanBuilderBase
+    {
+        public override SpanQuery GetSpanQuery(XElement e)
+        {
+            string fieldName = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            string value = DOMUtils.GetNonBlankTextOrFail(e);
+            PayloadTermQuery btq = new PayloadTermQuery(new Term(fieldName, value), new AveragePayloadFunction());
+            btq.Boost = DOMUtils.GetAttribute(e, "boost", 1.0f);
+            return btq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/CachedFilterBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/CachedFilterBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/CachedFilterBuilder.cs
new file mode 100644
index 0000000..d0e83ad
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/CachedFilterBuilder.cs
@@ -0,0 +1,82 @@
+using Lucene.Net.Search;
+using Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class CachedFilterBuilder : IFilterBuilder
+    {
+        private readonly QueryBuilderFactory queryFactory;
+        private readonly FilterBuilderFactory filterFactory;
+        private LRUCache<Object, Filter> filterCache;
+        private readonly int cacheSize;
+
+        public CachedFilterBuilder(QueryBuilderFactory queryFactory, FilterBuilderFactory filterFactory, int cacheSize)
+        {
+            this.queryFactory = queryFactory;
+            this.filterFactory = filterFactory;
+            this.cacheSize = cacheSize;
+        }
+
+        public Filter GetFilter(XElement e)
+        {
+            lock (this)
+            {
+                XElement childElement = DOMUtils.GetFirstChildOrFail(e);
+                if (filterCache == null)
+                {
+                    filterCache = new LRUCache<Object, Filter>(cacheSize);
+                }
+
+                IQueryBuilder qb = queryFactory.GetQueryBuilder(childElement.Name.LocalName);
+                Object cacheKey = null;
+                Query q = null;
+                Filter f = null;
+                if (qb != null)
+                {
+                    q = qb.GetQuery(childElement);
+                    cacheKey = q;
+                }
+                else
+                {
+                    f = filterFactory.GetFilter(childElement);
+                    cacheKey = f;
+                }
+
+                Filter cachedFilter = filterCache[cacheKey];
+                if (cachedFilter != null)
+                {
+                    return cachedFilter;
+                }
+
+                if (qb != null)
+                {
+                    cachedFilter = new QueryWrapperFilter(q);
+                }
+                else
+                {
+                    cachedFilter = new CachingWrapperFilter(f);
+                }
+
+                filterCache[cacheKey] = cachedFilter;
+                return cachedFilter;
+            }
+        }
+
+        class LRUCache<K, V> : HashMap<K, V>
+        {
+            // TODO: finish impl
+
+            public LRUCache(int maxsize)
+            {
+                this.maxsize = maxsize;
+            }
+
+            protected int maxsize;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/ConstantScoreQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/ConstantScoreQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/ConstantScoreQueryBuilder.cs
new file mode 100644
index 0000000..83d059a
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/ConstantScoreQueryBuilder.cs
@@ -0,0 +1,27 @@
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class ConstantScoreQueryBuilder : IQueryBuilder
+    {
+        private readonly FilterBuilderFactory filterFactory;
+
+        public ConstantScoreQueryBuilder(FilterBuilderFactory filterFactory)
+        {
+            this.filterFactory = filterFactory;
+        }
+
+        public Query GetQuery(XElement e)
+        {
+            XElement filterElem = DOMUtils.GetFirstChildOrFail(e);
+            Query q = new ConstantScoreQuery(filterFactory.GetFilter(filterElem));
+            q.Boost = DOMUtils.GetAttribute(e, "boost", 1.0f);
+            return q;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/DisjunctionMaxQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/DisjunctionMaxQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/DisjunctionMaxQueryBuilder.cs
new file mode 100644
index 0000000..cb9f6e3
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/DisjunctionMaxQueryBuilder.cs
@@ -0,0 +1,38 @@
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class DisjunctionMaxQueryBuilder : IQueryBuilder
+    {
+        private readonly IQueryBuilder factory;
+
+        public DisjunctionMaxQueryBuilder(IQueryBuilder factory)
+        {
+            this.factory = factory;
+        }
+
+        public Query GetQuery(XElement e)
+        {
+            float tieBreaker = DOMUtils.GetAttribute(e, "tieBreaker", 0.0f);
+            DisjunctionMaxQuery dq = new DisjunctionMaxQuery(tieBreaker);
+            dq.Boost = DOMUtils.GetAttribute(e, "boost", 1.0f);
+            var nl = e.DescendantNodes();
+            foreach (XNode node in nl)
+            {
+                if (node is XElement)
+                {
+                    XElement queryElem = (XElement)node;
+                    Query q = factory.GetQuery(queryElem);
+                    dq.Add(q);
+                }
+            }
+
+            return dq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/DuplicateFilterBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/DuplicateFilterBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/DuplicateFilterBuilder.cs
new file mode 100644
index 0000000..f48a488
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/DuplicateFilterBuilder.cs
@@ -0,0 +1,49 @@
+using Lucene.Net.Sandbox.Queries;
+using Lucene.Net.Search;
+using Lucene.Net.QueryParsers.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class DuplicateFilterBuilder : IFilterBuilder
+    {
+        public Filter GetFilter(XElement e)
+        {
+            string fieldName = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            DuplicateFilter df = new DuplicateFilter(fieldName);
+            string keepMode = DOMUtils.GetAttribute(e, "keepMode", "first");
+            if (keepMode.EqualsIgnoreCase("first"))
+            {
+                df.KeepModeValue = DuplicateFilter.KeepMode.KM_USE_FIRST_OCCURRENCE;
+            }
+            else if (keepMode.EqualsIgnoreCase(@"last"))
+            {
+                df.KeepModeValue = DuplicateFilter.KeepMode.KM_USE_LAST_OCCURRENCE;
+            }
+            else
+            {
+                throw new ParserException(@"Illegal keepMode attribute in DuplicateFilter:" + keepMode);
+            }
+
+            string processingMode = DOMUtils.GetAttribute(e, "processingMode", "full");
+            if (processingMode.EqualsIgnoreCase(@"full"))
+            {
+                df.ProcessingModeValue = DuplicateFilter.ProcessingMode.PM_FULL_VALIDATION;
+            }
+            else if (processingMode.EqualsIgnoreCase(@"fast"))
+            {
+                df.ProcessingModeValue = DuplicateFilter.ProcessingMode.PM_FAST_INVALIDATION;
+            }
+            else
+            {
+                throw new ParserException(@"Illegal processingMode attribute in DuplicateFilter:" + processingMode);
+            }
+
+            return df;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/FilteredQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/FilteredQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/FilteredQueryBuilder.cs
new file mode 100644
index 0000000..8a25e92
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/FilteredQueryBuilder.cs
@@ -0,0 +1,34 @@
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class FilteredQueryBuilder : IQueryBuilder
+    {
+        private readonly IFilterBuilder filterFactory;
+        private readonly IQueryBuilder queryFactory;
+
+        public FilteredQueryBuilder(IFilterBuilder filterFactory, IQueryBuilder queryFactory)
+        {
+            this.filterFactory = filterFactory;
+            this.queryFactory = queryFactory;
+        }
+
+        public Query GetQuery(XElement e)
+        {
+            XElement filterElement = DOMUtils.GetChildByTagOrFail(e, "Filter");
+            filterElement = DOMUtils.GetFirstChildOrFail(filterElement);
+            Filter f = filterFactory.GetFilter(filterElement);
+            XElement queryElement = DOMUtils.GetChildByTagOrFail(e, "Query");
+            queryElement = DOMUtils.GetFirstChildOrFail(queryElement);
+            Query q = queryFactory.GetQuery(queryElement);
+            FilteredQuery fq = new FilteredQuery(q, f);
+            fq.Boost = DOMUtils.GetAttribute(e, "boost", 1.0f);
+            return fq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/FuzzyLikeThisQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/FuzzyLikeThisQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/FuzzyLikeThisQueryBuilder.cs
new file mode 100644
index 0000000..a16b8e5
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/FuzzyLikeThisQueryBuilder.cs
@@ -0,0 +1,45 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Sandbox.Queries;
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class FuzzyLikeThisQueryBuilder : IQueryBuilder
+    {
+        private static readonly int DEFAULT_MAX_NUM_TERMS = 50;
+        private static readonly float DEFAULT_MIN_SIMILARITY = SlowFuzzyQuery.defaultMinSimilarity;
+        private static readonly int DEFAULT_PREFIX_LENGTH = 1;
+        private static readonly bool DEFAULT_IGNORE_TF = false;
+        private readonly Analyzer analyzer;
+
+        public FuzzyLikeThisQueryBuilder(Analyzer analyzer)
+        {
+            this.analyzer = analyzer;
+        }
+
+        public Query GetQuery(XElement e)
+        {
+            var nl = e.Descendants("Field").ToList();
+            int maxNumTerms = DOMUtils.GetAttribute(e, "maxNumTerms", DEFAULT_MAX_NUM_TERMS);
+            FuzzyLikeThisQuery fbq = new FuzzyLikeThisQuery(maxNumTerms, analyzer);
+            fbq.SetIgnoreTF(DOMUtils.GetAttribute(e, @"ignoreTF", DEFAULT_IGNORE_TF));
+            for (int i = 0; i < nl.Count; i++)
+            {
+                XElement fieldElem = (XElement)nl[i];
+                float minSimilarity = DOMUtils.GetAttribute(fieldElem, "minSimilarity", DEFAULT_MIN_SIMILARITY);
+                int prefixLength = DOMUtils.GetAttribute(fieldElem, "prefixLength", DEFAULT_PREFIX_LENGTH);
+                string fieldName = DOMUtils.GetAttributeWithInheritance(fieldElem, "fieldName");
+                string value = DOMUtils.GetText(fieldElem);
+                fbq.AddTerms(value, fieldName, minSimilarity, prefixLength);
+            }
+
+            fbq.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+            return fbq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/ISpanQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/ISpanQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/ISpanQueryBuilder.cs
new file mode 100644
index 0000000..c5f846e
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/ISpanQueryBuilder.cs
@@ -0,0 +1,14 @@
+using Lucene.Net.Search.Spans;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public interface ISpanQueryBuilder : IQueryBuilder
+    {
+        SpanQuery GetSpanQuery(XElement e);
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/LikeThisQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/LikeThisQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/LikeThisQueryBuilder.cs
new file mode 100644
index 0000000..7116d48
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/LikeThisQueryBuilder.cs
@@ -0,0 +1,83 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Search;
+using Lucene.Net.Search.Mlt;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class LikeThisQueryBuilder : IQueryBuilder
+    {
+        private static readonly int DEFAULT_MAX_QUERY_TERMS = 20;
+        private static readonly int DEFAULT_MIN_TERM_FREQUENCY = 1;
+        private static readonly float DEFAULT_PERCENT_TERMS_TO_MATCH = 30;
+        private readonly Analyzer analyzer;
+        private readonly string[] defaultFieldNames;
+
+        public LikeThisQueryBuilder(Analyzer analyzer, string[] defaultFieldNames)
+        {
+            this.analyzer = analyzer;
+            this.defaultFieldNames = defaultFieldNames;
+        }
+
+        public Query GetQuery(XElement e)
+        {
+            string fieldsList = DOMUtils.GetAttribute(e, "fieldNames", "");
+            string[] fields = defaultFieldNames;
+            if ((fieldsList != null) && (fieldsList.Trim().Length > 0))
+            {
+                fields = fieldsList.Trim().Split(',');
+                for (int i = 0; i < fields.Length; i++)
+                {
+                    fields[i] = fields[i].Trim();
+                }
+            }
+
+            string stopWords = DOMUtils.GetAttribute(e, "stopWords", "");
+            ISet<String> stopWordsSet = null;
+            if ((stopWords != null) && (fields != null))
+            {
+                stopWordsSet = new HashSet<String>();
+                foreach (string field in fields)
+                {
+                    try
+                    {
+                        TokenStream ts = analyzer.TokenStream(field, new StringReader(stopWords));
+                        ICharTermAttribute termAtt = ts.AddAttribute<ICharTermAttribute>();
+                        ts.Reset();
+                        while (ts.IncrementToken())
+                        {
+                            stopWordsSet.Add(termAtt.ToString());
+                        }
+
+                        ts.End();
+                        ts.Dispose();
+                    }
+                    catch (IOException ioe)
+                    {
+                        throw new ParserException(@"IoException parsing stop words list in " + GetType().Name + @":" + ioe.Message);
+                    }
+                }
+            }
+
+            MoreLikeThisQuery mlt = new MoreLikeThisQuery(DOMUtils.GetText(e), fields, analyzer, fields[0]);
+            mlt.MaxQueryTerms = DOMUtils.GetAttribute(e, @"maxQueryTerms", DEFAULT_MAX_QUERY_TERMS);
+            mlt.MinTermFrequency = DOMUtils.GetAttribute(e, @"minTermFrequency", DEFAULT_MIN_TERM_FREQUENCY);
+            mlt.PercentTermsToMatch = DOMUtils.GetAttribute(e, @"percentTermsToMatch", DEFAULT_PERCENT_TERMS_TO_MATCH) / 100;
+            mlt.SetStopWords(stopWordsSet);
+            int minDocFreq = DOMUtils.GetAttribute(e, "minDocFreq", -1);
+            if (minDocFreq >= 0)
+            {
+                mlt.MinDocFreq = minDocFreq;
+            }
+
+            mlt.Boost = DOMUtils.GetAttribute(e, "boost", 1.0f);
+            return mlt;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/MatchAllDocsQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/MatchAllDocsQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/MatchAllDocsQueryBuilder.cs
new file mode 100644
index 0000000..ea3ea52
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/MatchAllDocsQueryBuilder.cs
@@ -0,0 +1,17 @@
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class MatchAllDocsQueryBuilder : IQueryBuilder
+    {
+        public Query GetQuery(XElement e)
+        {
+            return new MatchAllDocsQuery();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/NumericRangeFilterBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/NumericRangeFilterBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/NumericRangeFilterBuilder.cs
new file mode 100644
index 0000000..7f518b7
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/NumericRangeFilterBuilder.cs
@@ -0,0 +1,77 @@
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using Lucene.Net.QueryParsers.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+using Lucene.Net.Index;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class NumericRangeFilterBuilder : IFilterBuilder
+    {
+        private static readonly NoMatchFilter NO_MATCH_FILTER = new NoMatchFilter();
+        private bool strictMode = false;
+
+        public virtual void SetStrictMode(bool strictMode)
+        {
+            this.strictMode = strictMode;
+        }
+
+        public Filter GetFilter(XElement e)
+        {
+            string field = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            string lowerTerm = DOMUtils.GetAttributeOrFail(e, "lowerTerm");
+            string upperTerm = DOMUtils.GetAttributeOrFail(e, "upperTerm");
+            bool lowerInclusive = DOMUtils.GetAttribute(e, "includeLower", true);
+            bool upperInclusive = DOMUtils.GetAttribute(e, "includeUpper", true);
+            int precisionStep = DOMUtils.GetAttribute(e, "precisionStep", NumericUtils.PRECISION_STEP_DEFAULT);
+            string type = DOMUtils.GetAttribute(e, "type", "int");
+            try
+            {
+                Filter filter;
+                if (type.EqualsIgnoreCase(@"int"))
+                {
+                    filter = NumericRangeFilter.NewIntRange(field, precisionStep, int.Parse(lowerTerm), int.Parse(upperTerm), lowerInclusive, upperInclusive);
+                }
+                else if (type.EqualsIgnoreCase(@"long"))
+                {
+                    filter = NumericRangeFilter.NewLongRange(field, precisionStep, long.Parse(lowerTerm), long.Parse(upperTerm), lowerInclusive, upperInclusive);
+                }
+                else if (type.EqualsIgnoreCase(@"double"))
+                {
+                    filter = NumericRangeFilter.NewDoubleRange(field, precisionStep, double.Parse(lowerTerm), double.Parse(upperTerm), lowerInclusive, upperInclusive);
+                }
+                else if (type.EqualsIgnoreCase(@"float"))
+                {
+                    filter = NumericRangeFilter.NewFloatRange(field, precisionStep, float.Parse(lowerTerm), float.Parse(upperTerm), lowerInclusive, upperInclusive);
+                }
+                else
+                {
+                    throw new ParserException(@"type attribute must be one of: [long, int, double, float]");
+                }
+
+                return filter;
+            }
+            catch (FormatException nfe)
+            {
+                if (strictMode)
+                {
+                    throw new ParserException(@"Could not parse lowerTerm or upperTerm into a number", nfe);
+                }
+
+                return NO_MATCH_FILTER;
+            }
+        }
+
+        class NoMatchFilter : Filter
+        {
+            public override DocIdSet GetDocIdSet(AtomicReaderContext context, IBits acceptDocs)
+            {
+                return null;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/NumericRangeQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/NumericRangeQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/NumericRangeQueryBuilder.cs
new file mode 100644
index 0000000..248a497
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/NumericRangeQueryBuilder.cs
@@ -0,0 +1,55 @@
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using Lucene.Net.QueryParsers.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class NumericRangeQueryBuilder : IQueryBuilder
+    {
+        public Query GetQuery(XElement e)
+        {
+            string field = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            string lowerTerm = DOMUtils.GetAttributeOrFail(e, "lowerTerm");
+            string upperTerm = DOMUtils.GetAttributeOrFail(e, "upperTerm");
+            bool lowerInclusive = DOMUtils.GetAttribute(e, "includeLower", true);
+            bool upperInclusive = DOMUtils.GetAttribute(e, "includeUpper", true);
+            int precisionStep = DOMUtils.GetAttribute(e, "precisionStep", NumericUtils.PRECISION_STEP_DEFAULT);
+            string type = DOMUtils.GetAttribute(e, "type", "int");
+            try
+            {
+                Query filter;
+                if (type.EqualsIgnoreCase(@"int"))
+                {
+                    filter = NumericRangeQuery.NewIntRange(field, precisionStep, int.Parse(lowerTerm), int.Parse(upperTerm), lowerInclusive, upperInclusive);
+                }
+                else if (type.EqualsIgnoreCase(@"long"))
+                {
+                    filter = NumericRangeQuery.NewLongRange(field, precisionStep, long.Parse(lowerTerm), long.Parse(upperTerm), lowerInclusive, upperInclusive);
+                }
+                else if (type.EqualsIgnoreCase(@"double"))
+                {
+                    filter = NumericRangeQuery.NewDoubleRange(field, precisionStep, double.Parse(lowerTerm), double.Parse(upperTerm), lowerInclusive, upperInclusive);
+                }
+                else if (type.EqualsIgnoreCase(@"float"))
+                {
+                    filter = NumericRangeQuery.NewFloatRange(field, precisionStep, float.Parse(lowerTerm), float.Parse(upperTerm), lowerInclusive, upperInclusive);
+                }
+                else
+                {
+                    throw new ParserException(@"type attribute must be one of: [long, int, double, float]");
+                }
+
+                return filter;
+            }
+            catch (FormatException nfe)
+            {
+                throw new ParserException(@"Could not parse lowerTerm or upperTerm into a number", nfe);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/RangeFilterBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/RangeFilterBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/RangeFilterBuilder.cs
new file mode 100644
index 0000000..862d989
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/RangeFilterBuilder.cs
@@ -0,0 +1,22 @@
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class RangeFilterBuilder : IFilterBuilder
+    {
+        public Filter GetFilter(XElement e)
+        {
+            string fieldName = DOMUtils.GetAttributeWithInheritance(e, "fieldName");
+            string lowerTerm = DOMUtils.GetAttribute(e, "lowerTerm", "");
+            string upperTerm = DOMUtils.GetAttribute(e, "upperTerm", "");
+            bool includeLower = DOMUtils.GetAttribute(e, "includeLower", true);
+            bool includeUpper = DOMUtils.GetAttribute(e, "includeUpper", true);
+            return TermRangeFilter.NewStringRange(fieldName, lowerTerm, upperTerm, includeLower, includeUpper);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/SpanBuilderBase.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/SpanBuilderBase.cs b/src/contrib/QueryParsers/Xml/Builders/SpanBuilderBase.cs
new file mode 100644
index 0000000..d8abcbd
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/SpanBuilderBase.cs
@@ -0,0 +1,20 @@
+using Lucene.Net.Search;
+using Lucene.Net.Search.Spans;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public abstract class SpanBuilderBase : ISpanQueryBuilder
+    {
+        public Query GetQuery(XElement e)
+        {
+            return GetSpanQuery(e);
+        }
+
+        public abstract SpanQuery GetSpanQuery(XElement e);
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/SpanFirstBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/SpanFirstBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/SpanFirstBuilder.cs
new file mode 100644
index 0000000..61bcadf
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/SpanFirstBuilder.cs
@@ -0,0 +1,29 @@
+using Lucene.Net.Search.Spans;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class SpanFirstBuilder : SpanBuilderBase
+    {
+        private readonly ISpanQueryBuilder factory;
+
+        public SpanFirstBuilder(ISpanQueryBuilder factory)
+        {
+            this.factory = factory;
+        }
+
+        public override SpanQuery GetSpanQuery(XElement e)
+        {
+            int end = DOMUtils.GetAttribute(e, "end", 1);
+            XElement child = DOMUtils.GetFirstChildElement(e);
+            SpanQuery q = factory.GetSpanQuery(child);
+            SpanFirstQuery sfq = new SpanFirstQuery(q, end);
+            sfq.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+            return sfq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/SpanNearBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/SpanNearBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/SpanNearBuilder.cs
new file mode 100644
index 0000000..00b450c
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/SpanNearBuilder.cs
@@ -0,0 +1,38 @@
+using Lucene.Net.Search.Spans;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class SpanNearBuilder : SpanBuilderBase
+    {
+        private readonly ISpanQueryBuilder factory;
+
+        public SpanNearBuilder(ISpanQueryBuilder factory)
+        {
+            this.factory = factory;
+        }
+
+        public override SpanQuery GetSpanQuery(XElement e)
+        {
+            string slopString = DOMUtils.GetAttributeOrFail(e, "slop");
+            int slop = int.Parse(slopString);
+            bool inOrder = DOMUtils.GetAttribute(e, "inOrder", false);
+            IList<SpanQuery> spans = new List<SpanQuery>();
+            for (XNode kid = e.FirstNode; kid != null; kid = kid.NextNode)
+            {
+                if (kid.NodeType == XmlNodeType.Element)
+                {
+                    spans.Add(factory.GetSpanQuery((XElement)kid));
+                }
+            }
+
+            SpanQuery[] spanQueries = spans.ToArray();
+            return new SpanNearQuery(spanQueries, slop, inOrder);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/SpanNotBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/SpanNotBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/SpanNotBuilder.cs
new file mode 100644
index 0000000..4f4b74f
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/SpanNotBuilder.cs
@@ -0,0 +1,32 @@
+using Lucene.Net.Search.Spans;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class SpanNotBuilder : SpanBuilderBase
+    {
+        private readonly ISpanQueryBuilder factory;
+
+        public SpanNotBuilder(ISpanQueryBuilder factory)
+        {
+            this.factory = factory;
+        }
+
+        public override SpanQuery GetSpanQuery(XElement e)
+        {
+            XElement includeElem = DOMUtils.GetChildByTagOrFail(e, "Include");
+            includeElem = DOMUtils.GetFirstChildOrFail(includeElem);
+            XElement excludeElem = DOMUtils.GetChildByTagOrFail(e, "Exclude");
+            excludeElem = DOMUtils.GetFirstChildOrFail(excludeElem);
+            SpanQuery include = factory.GetSpanQuery(includeElem);
+            SpanQuery exclude = factory.GetSpanQuery(excludeElem);
+            SpanNotQuery snq = new SpanNotQuery(include, exclude);
+            snq.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+            return snq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/SpanOrBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/SpanOrBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/SpanOrBuilder.cs
new file mode 100644
index 0000000..e3cad3e
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/SpanOrBuilder.cs
@@ -0,0 +1,38 @@
+using Lucene.Net.Search.Spans;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class SpanOrBuilder : SpanBuilderBase
+    {
+        private readonly ISpanQueryBuilder factory;
+
+        public SpanOrBuilder(ISpanQueryBuilder factory)
+        {
+            this.factory = factory;
+        }
+
+        public override SpanQuery GetSpanQuery(XElement e)
+        {
+            List<SpanQuery> clausesList = new List<SpanQuery>();
+            for (XNode kid = e.FirstNode; kid != null; kid = kid.NextNode)
+            {
+                if (kid.NodeType == XmlNodeType.Element)
+                {
+                    SpanQuery clause = factory.GetSpanQuery((XElement)kid);
+                    clausesList.Add(clause);
+                }
+            }
+
+            SpanQuery[] clauses = clausesList.ToArray();
+            SpanOrQuery soq = new SpanOrQuery(clauses);
+            soq.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+            return soq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/SpanOrTermsBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/SpanOrTermsBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/SpanOrTermsBuilder.cs
new file mode 100644
index 0000000..bdaec24
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/SpanOrTermsBuilder.cs
@@ -0,0 +1,54 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Index;
+using Lucene.Net.Search.Spans;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class SpanOrTermsBuilder : SpanBuilderBase
+    {
+        private readonly Analyzer analyzer;
+
+        public SpanOrTermsBuilder(Analyzer analyzer)
+        {
+            this.analyzer = analyzer;
+        }
+
+        public override SpanQuery GetSpanQuery(XElement e)
+        {
+            string fieldName = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            string value = DOMUtils.GetNonBlankTextOrFail(e);
+            try
+            {
+                List<SpanQuery> clausesList = new List<SpanQuery>();
+                TokenStream ts = analyzer.TokenStream(fieldName, new StringReader(value));
+                ITermToBytesRefAttribute termAtt = ts.AddAttribute<ITermToBytesRefAttribute>();
+                BytesRef bytes = termAtt.BytesRef;
+                ts.Reset();
+                while (ts.IncrementToken())
+                {
+                    termAtt.FillBytesRef();
+                    SpanTermQuery stq = new SpanTermQuery(new Term(fieldName, BytesRef.DeepCopyOf(bytes)));
+                    clausesList.Add(stq);
+                }
+
+                ts.End();
+                ts.Dispose();
+                SpanOrQuery soq = new SpanOrQuery(clausesList.ToArray());
+                soq.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+                return soq;
+            }
+            catch (IOException)
+            {
+                throw new ParserException(@"IOException parsing value:" + value);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/SpanQueryBuilderFactory.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/SpanQueryBuilderFactory.cs b/src/contrib/QueryParsers/Xml/Builders/SpanQueryBuilderFactory.cs
new file mode 100644
index 0000000..c21087a
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/SpanQueryBuilderFactory.cs
@@ -0,0 +1,37 @@
+using Lucene.Net.Search;
+using Lucene.Net.Search.Spans;
+using Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class SpanQueryBuilderFactory : ISpanQueryBuilder
+    {
+        private readonly IDictionary<String, ISpanQueryBuilder> builders = new HashMap<String, ISpanQueryBuilder>();
+
+        public Query GetQuery(XElement e)
+        {
+            return GetSpanQuery(e);
+        }
+
+        public virtual void AddBuilder(string nodeName, ISpanQueryBuilder builder)
+        {
+            builders[nodeName] = builder;
+        }
+
+        public SpanQuery GetSpanQuery(XElement e)
+        {
+            ISpanQueryBuilder builder = builders[e.Name.LocalName];
+            if (builder == null)
+            {
+                throw new ParserException(@"No SpanQueryObjectBuilder defined for node " + e.Name.LocalName);
+            }
+
+            return builder.GetSpanQuery(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/SpanTermBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/SpanTermBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/SpanTermBuilder.cs
new file mode 100644
index 0000000..86c42ca
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/SpanTermBuilder.cs
@@ -0,0 +1,22 @@
+using Lucene.Net.Index;
+using Lucene.Net.Search.Spans;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class SpanTermBuilder : SpanBuilderBase
+    {
+        public override SpanQuery GetSpanQuery(XElement e)
+        {
+            string fieldName = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            string value = DOMUtils.GetNonBlankTextOrFail(e);
+            SpanTermQuery stq = new SpanTermQuery(new Term(fieldName, value));
+            stq.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+            return stq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/TermQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/TermQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/TermQueryBuilder.cs
new file mode 100644
index 0000000..14287f1
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/TermQueryBuilder.cs
@@ -0,0 +1,22 @@
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class TermQueryBuilder : IQueryBuilder
+    {
+        public Query GetQuery(XElement e)
+        {
+            string field = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            string value = DOMUtils.GetNonBlankTextOrFail(e);
+            TermQuery tq = new TermQuery(new Term(field, value));
+            tq.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+            return tq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/TermsFilterBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/TermsFilterBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/TermsFilterBuilder.cs
new file mode 100644
index 0000000..8117382
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/TermsFilterBuilder.cs
@@ -0,0 +1,53 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class TermsFilterBuilder : IFilterBuilder
+    {
+        private readonly Analyzer analyzer;
+
+        public TermsFilterBuilder(Analyzer analyzer)
+        {
+            this.analyzer = analyzer;
+        }
+
+        public Filter GetFilter(XElement e)
+        {
+            List<BytesRef> terms = new List<BytesRef>();
+            string text = DOMUtils.GetNonBlankTextOrFail(e);
+            string fieldName = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            try
+            {
+                TokenStream ts = analyzer.TokenStream(fieldName, new StringReader(text));
+                ITermToBytesRefAttribute termAtt = ts.AddAttribute<ITermToBytesRefAttribute>();
+                //Term term = null;
+                BytesRef bytes = termAtt.BytesRef;
+                ts.Reset();
+                while (ts.IncrementToken())
+                {
+                    termAtt.FillBytesRef();
+                    terms.Add(BytesRef.DeepCopyOf(bytes));
+                }
+
+                ts.End();
+                ts.Dispose();
+            }
+            catch (IOException ioe)
+            {
+                throw new Exception(@"Error constructing terms from index:" + ioe);
+            }
+
+            return new TermsFilter(fieldName, terms);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/TermsQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/TermsQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/TermsQueryBuilder.cs
new file mode 100644
index 0000000..753e4be
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/TermsQueryBuilder.cs
@@ -0,0 +1,56 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class TermsQueryBuilder : IQueryBuilder
+    {
+        private readonly Analyzer analyzer;
+
+        public TermsQueryBuilder(Analyzer analyzer)
+        {
+            this.analyzer = analyzer;
+        }
+
+        public Query GetQuery(XElement e)
+        {
+            string fieldName = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            string text = DOMUtils.GetNonBlankTextOrFail(e);
+            BooleanQuery bq = new BooleanQuery(DOMUtils.GetAttribute(e, "disableCoord", false));
+            bq.MinimumNumberShouldMatch = DOMUtils.GetAttribute(e, "minimumNumberShouldMatch", 0);
+            try
+            {
+                TokenStream ts = analyzer.TokenStream(fieldName, new StringReader(text));
+                ITermToBytesRefAttribute termAtt = ts.AddAttribute<ITermToBytesRefAttribute>();
+                Term term = null;
+                BytesRef bytes = termAtt.BytesRef;
+                ts.Reset();
+                while (ts.IncrementToken())
+                {
+                    termAtt.FillBytesRef();
+                    term = new Term(fieldName, BytesRef.DeepCopyOf(bytes));
+                    bq.Add(new BooleanClause(new TermQuery(term), Occur.SHOULD));
+                }
+
+                ts.End();
+                ts.Dispose();
+            }
+            catch (IOException ioe)
+            {
+                throw new Exception(@"Error constructing terms from index:" + ioe);
+            }
+
+            bq.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+            return bq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/Builders/UserInputQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/Builders/UserInputQueryBuilder.cs b/src/contrib/QueryParsers/Xml/Builders/UserInputQueryBuilder.cs
new file mode 100644
index 0000000..d27cf18
--- /dev/null
+++ b/src/contrib/QueryParsers/Xml/Builders/UserInputQueryBuilder.cs
@@ -0,0 +1,63 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.QueryParsers.Classic;
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace Lucene.Net.QueryParsers.Xml.Builders
+{
+    public class UserInputQueryBuilder : IQueryBuilder
+    {
+        private QueryParser unSafeParser;
+        private Analyzer analyzer;
+        private string defaultField;
+
+        public UserInputQueryBuilder(QueryParser parser)
+        {
+            this.unSafeParser = parser;
+        }
+
+        public UserInputQueryBuilder(string defaultField, Analyzer analyzer)
+        {
+            this.analyzer = analyzer;
+            this.defaultField = defaultField;
+        }
+
+        public Query GetQuery(XElement e)
+        {
+            string text = DOMUtils.GetText(e);
+            try
+            {
+                Query q = null;
+                if (unSafeParser != null)
+                {
+                    lock (unSafeParser)
+                    {
+                        q = unSafeParser.Parse(text);
+                    }
+                }
+                else
+                {
+                    string fieldName = DOMUtils.GetAttribute(e, "fieldName", defaultField);
+                    QueryParser parser = CreateQueryParser(fieldName, analyzer);
+                    q = parser.Parse(text);
+                }
+
+                q.Boost = DOMUtils.GetAttribute(e, @"boost", 1.0f);
+                return q;
+            }
+            catch (ParseException e1)
+            {
+                throw new ParserException(e1.Message);
+            }
+        }
+
+        protected virtual QueryParser CreateQueryParser(string fieldName, Analyzer analyzer)
+        {
+            return new QueryParser(Lucene.Net.Util.Version.LUCENE_CURRENT, fieldName, analyzer);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/CoreParser.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/CoreParser.cs b/src/contrib/QueryParsers/Xml/CoreParser.cs
index 1a5450d..fce8a22 100644
--- a/src/contrib/QueryParsers/Xml/CoreParser.cs
+++ b/src/contrib/QueryParsers/Xml/CoreParser.cs
@@ -1,5 +1,6 @@
 using Lucene.Net.Analysis;
 using Lucene.Net.QueryParsers.Classic;
+using Lucene.Net.QueryParsers.Xml.Builders;
 using Lucene.Net.Search;
 using System;
 using System.Collections.Generic;
@@ -64,31 +65,31 @@ namespace Lucene.Net.QueryParsers.Xml
             SpanQueryBuilderFactory sqof = new SpanQueryBuilderFactory();
 
             SpanNearBuilder snb = new SpanNearBuilder(sqof);
-            sqof.addBuilder("SpanNear", snb);
+            sqof.AddBuilder("SpanNear", snb);
             queryFactory.AddBuilder("SpanNear", snb);
 
             BoostingTermBuilder btb = new BoostingTermBuilder();
-            sqof.addBuilder("BoostingTermQuery", btb);
+            sqof.AddBuilder("BoostingTermQuery", btb);
             queryFactory.AddBuilder("BoostingTermQuery", btb);
 
             SpanTermBuilder snt = new SpanTermBuilder();
-            sqof.addBuilder("SpanTerm", snt);
+            sqof.AddBuilder("SpanTerm", snt);
             queryFactory.AddBuilder("SpanTerm", snt);
 
             SpanOrBuilder sot = new SpanOrBuilder(sqof);
-            sqof.addBuilder("SpanOr", sot);
+            sqof.AddBuilder("SpanOr", sot);
             queryFactory.AddBuilder("SpanOr", sot);
 
             SpanOrTermsBuilder sots = new SpanOrTermsBuilder(analyzer);
-            sqof.addBuilder("SpanOrTerms", sots);
+            sqof.AddBuilder("SpanOrTerms", sots);
             queryFactory.AddBuilder("SpanOrTerms", sots);
 
             SpanFirstBuilder sft = new SpanFirstBuilder(sqof);
-            sqof.addBuilder("SpanFirst", sft);
+            sqof.AddBuilder("SpanFirst", sft);
             queryFactory.AddBuilder("SpanFirst", sft);
 
             SpanNotBuilder snot = new SpanNotBuilder(sqof);
-            sqof.addBuilder("SpanNot", snot);
+            sqof.AddBuilder("SpanNot", snot);
             queryFactory.AddBuilder("SpanNot", snot);
         }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/DOMUtils.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/DOMUtils.cs b/src/contrib/QueryParsers/Xml/DOMUtils.cs
index d6e4496..26bab57 100644
--- a/src/contrib/QueryParsers/Xml/DOMUtils.cs
+++ b/src/contrib/QueryParsers/Xml/DOMUtils.cs
@@ -44,7 +44,7 @@ namespace Lucene.Net.QueryParsers.Xml
             return v;
         }
 
-        public static string AetAttributeWithInheritanceOrFail(XElement e, string name)
+        public static string GetAttributeWithInheritanceOrFail(XElement e, string name)
         {
             string v = GetAttributeWithInheritance(e, name);
             if (null == v)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/IFilterBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/IFilterBuilder.cs b/src/contrib/QueryParsers/Xml/IFilterBuilder.cs
index cf457d0..eca6e1d 100644
--- a/src/contrib/QueryParsers/Xml/IFilterBuilder.cs
+++ b/src/contrib/QueryParsers/Xml/IFilterBuilder.cs
@@ -10,6 +10,6 @@ namespace Lucene.Net.QueryParsers.Xml
 {
     public interface IFilterBuilder
     {
-        public Filter GetFilter(XElement e);
+        Filter GetFilter(XElement e);
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/QueryParsers/Xml/IQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/contrib/QueryParsers/Xml/IQueryBuilder.cs b/src/contrib/QueryParsers/Xml/IQueryBuilder.cs
index 1d825af..5306c97 100644
--- a/src/contrib/QueryParsers/Xml/IQueryBuilder.cs
+++ b/src/contrib/QueryParsers/Xml/IQueryBuilder.cs
@@ -10,6 +10,6 @@ namespace Lucene.Net.QueryParsers.Xml
 {
     public interface IQueryBuilder
     {
-        public Query GetQuery(XElement e);
+        Query GetQuery(XElement e);
     }
 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/Sandbox/Contrib.Sandbox.csproj
----------------------------------------------------------------------
diff --git a/src/contrib/Sandbox/Contrib.Sandbox.csproj b/src/contrib/Sandbox/Contrib.Sandbox.csproj
new file mode 100644
index 0000000..4466e7d
--- /dev/null
+++ b/src/contrib/Sandbox/Contrib.Sandbox.csproj
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{1DE43B60-4041-4A2E-9717-5B4CA891D0FD}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Lucene.Net.Sandbox</RootNamespace>
+    <AssemblyName>Contrib.Sandbox</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Queries\DuplicateFilter.cs" />
+    <Compile Include="Queries\FuzzyLikeThisQuery.cs" />
+    <Compile Include="Queries\SlowCollatedStringComparer.cs" />
+    <Compile Include="Queries\SlowCollatedTermRangeFilter.cs" />
+    <Compile Include="Queries\SlowCollatedTermRangeQuery.cs" />
+    <Compile Include="Queries\SlowCollatedTermRangeTermsEnum.cs" />
+    <Compile Include="Queries\SlowFuzzyQuery.cs" />
+    <Compile Include="Queries\SlowFuzzyTermsEnum.cs" />
+  </ItemGroup>
+  <ItemGroup />
+  <ItemGroup>
+    <ProjectReference Include="..\..\core\Lucene.Net.csproj">
+      <Project>{5d4ad9be-1ffb-41ab-9943-25737971bf57}</Project>
+      <Name>Lucene.Net</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/Sandbox/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Sandbox/Properties/AssemblyInfo.cs b/src/contrib/Sandbox/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f77fd69
--- /dev/null
+++ b/src/contrib/Sandbox/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Contrib.Sandbox")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Contrib.Sandbox")]
+[assembly: AssemblyCopyright("Copyright ©  2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6f437b14-45c7-4648-9d5b-65f86707533c")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/Sandbox/Queries/DuplicateFilter.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Sandbox/Queries/DuplicateFilter.cs b/src/contrib/Sandbox/Queries/DuplicateFilter.cs
new file mode 100644
index 0000000..4ff0a35
--- /dev/null
+++ b/src/contrib/Sandbox/Queries/DuplicateFilter.cs
@@ -0,0 +1,222 @@
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Lucene.Net.Sandbox.Queries
+{
+    public class DuplicateFilter : Filter
+    {
+        public enum KeepMode
+        {
+            KM_USE_FIRST_OCCURRENCE,
+            KM_USE_LAST_OCCURRENCE
+        }
+
+        private KeepMode keepMode;
+
+        public enum ProcessingMode
+        {
+            PM_FULL_VALIDATION,
+            PM_FAST_INVALIDATION
+        }
+
+        private ProcessingMode processingMode;
+
+        private string fieldName;
+        
+        public DuplicateFilter(string fieldName)
+            : this(fieldName, KeepMode.KM_USE_LAST_OCCURRENCE, ProcessingMode.PM_FULL_VALIDATION)
+        {
+        }
+
+        public DuplicateFilter(string fieldName, KeepMode keepMode, ProcessingMode processingMode)
+        {
+            this.fieldName = fieldName;
+            this.keepMode = keepMode;
+            this.processingMode = processingMode;
+        }
+
+        public override DocIdSet GetDocIdSet(AtomicReaderContext context, IBits acceptDocs)
+        {
+            if (processingMode == ProcessingMode.PM_FAST_INVALIDATION)
+            {
+                return FastBits(context.AtomicReader, acceptDocs);
+            }
+            else
+            {
+                return CorrectBits(context.AtomicReader, acceptDocs);
+            }
+        }
+
+        private FixedBitSet CorrectBits(AtomicReader reader, IBits acceptDocs)
+        {
+            FixedBitSet bits = new FixedBitSet(reader.MaxDoc);
+            Terms terms = reader.Fields.Terms(fieldName);
+            if (terms == null)
+            {
+                return bits;
+            }
+
+            TermsEnum termsEnum = terms.Iterator(null);
+            DocsEnum docs = null;
+            while (true)
+            {
+                BytesRef currTerm = termsEnum.Next();
+                if (currTerm == null)
+                {
+                    break;
+                }
+                else
+                {
+                    docs = termsEnum.Docs(acceptDocs, docs, DocsEnum.FLAG_NONE);
+                    int doc = docs.NextDoc();
+                    if (doc != DocIdSetIterator.NO_MORE_DOCS)
+                    {
+                        if (keepMode == KeepMode.KM_USE_FIRST_OCCURRENCE)
+                        {
+                            bits.Set(doc);
+                        }
+                        else
+                        {
+                            int lastDoc = doc;
+                            while (true)
+                            {
+                                lastDoc = doc;
+                                doc = docs.NextDoc();
+                                if (doc == DocIdSetIterator.NO_MORE_DOCS)
+                                {
+                                    break;
+                                }
+                            }
+
+                            bits.Set(lastDoc);
+                        }
+                    }
+                }
+            }
+
+            return bits;
+        }
+
+        private FixedBitSet FastBits(AtomicReader reader, IBits acceptDocs)
+        {
+            FixedBitSet bits = new FixedBitSet(reader.MaxDoc);
+            bits.Set(0, reader.MaxDoc);
+            Terms terms = reader.Fields.Terms(fieldName);
+            if (terms == null)
+            {
+                return bits;
+            }
+
+            TermsEnum termsEnum = terms.Iterator(null);
+            DocsEnum docs = null;
+            while (true)
+            {
+                BytesRef currTerm = termsEnum.Next();
+                if (currTerm == null)
+                {
+                    break;
+                }
+                else
+                {
+                    if (termsEnum.DocFreq > 1)
+                    {
+                        docs = termsEnum.Docs(acceptDocs, docs, DocsEnum.FLAG_NONE);
+                        int doc = docs.NextDoc();
+                        if (doc != DocIdSetIterator.NO_MORE_DOCS)
+                        {
+                            if (keepMode == KeepMode.KM_USE_FIRST_OCCURRENCE)
+                            {
+                                doc = docs.NextDoc();
+                            }
+                        }
+
+                        int lastDoc = -1;
+                        while (true)
+                        {
+                            lastDoc = doc;
+                            bits.Clear(lastDoc);
+                            doc = docs.NextDoc();
+                            if (doc == DocIdSetIterator.NO_MORE_DOCS)
+                            {
+                                break;
+                            }
+                        }
+
+                        if (keepMode == KeepMode.KM_USE_LAST_OCCURRENCE)
+                        {
+                            bits.Set(lastDoc);
+                        }
+                    }
+                }
+            }
+
+            return bits;
+        }
+
+        public virtual string FieldName
+        {
+            get
+            {
+                return fieldName;
+            }
+            set
+            {
+                this.fieldName = value;
+            }
+        }
+
+        public virtual KeepMode KeepModeValue
+        {
+            get
+            {
+                return keepMode;
+            }
+            set
+            {
+                this.keepMode = value;
+            }
+        }
+        
+        public override bool Equals(Object obj)
+        {
+            if (this == obj)
+            {
+                return true;
+            }
+
+            if ((obj == null) || (obj.GetType() != this.GetType()))
+            {
+                return false;
+            }
+
+            DuplicateFilter other = (DuplicateFilter)obj;
+            return keepMode == other.keepMode && processingMode == other.processingMode && fieldName != null && fieldName.Equals(other.fieldName);
+        }
+
+        public override int GetHashCode()
+        {
+            int hash = 217;
+            hash = 31 * hash + keepMode.GetHashCode();
+            hash = 31 * hash + processingMode.GetHashCode();
+            hash = 31 * hash + fieldName.GetHashCode();
+            return hash;
+        }
+
+        public virtual ProcessingMode ProcessingModeValue
+        {
+            get
+            {
+                return processingMode;
+            }
+            set
+            {
+                this.processingMode = value;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/b43f529b/src/contrib/Sandbox/Queries/FuzzyLikeThisQuery.cs
----------------------------------------------------------------------
diff --git a/src/contrib/Sandbox/Queries/FuzzyLikeThisQuery.cs b/src/contrib/Sandbox/Queries/FuzzyLikeThisQuery.cs
new file mode 100644
index 0000000..9491610
--- /dev/null
+++ b/src/contrib/Sandbox/Queries/FuzzyLikeThisQuery.cs
@@ -0,0 +1,315 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Search.Similarities;
+using Lucene.Net.Support;
+using Lucene.Net.Util;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Lucene.Net.Sandbox.Queries
+{
+    public class FuzzyLikeThisQuery : Query
+    {
+        static TFIDFSimilarity sim = new DefaultSimilarity();
+        Query rewrittenQuery = null;
+        List<FieldVals> fieldVals = new List<FieldVals>();
+        Analyzer analyzer;
+        ScoreTermQueue q;
+        int MAX_VARIANTS_PER_TERM = 50;
+        bool ignoreTF = false;
+        private int maxNumTerms;
+
+        public override int GetHashCode()
+        {
+            int prime = 31;
+            int result = base.GetHashCode();
+            result = prime * result + ((analyzer == null) ? 0 : analyzer.GetHashCode());
+            result = prime * result + ((fieldVals == null) ? 0 : fieldVals.GetHashCode());
+            result = prime * result + (ignoreTF ? 1231 : 1237);
+            result = prime * result + maxNumTerms;
+            return result;
+        }
+
+        public override bool Equals(Object obj)
+        {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (GetType() != obj.GetType())
+                return false;
+            if (!base.Equals(obj))
+            {
+                return false;
+            }
+
+            FuzzyLikeThisQuery other = (FuzzyLikeThisQuery) obj;
+            if (analyzer == null)
+            {
+                if (other.analyzer != null)
+                    return false;
+            }
+            else if (!analyzer.Equals(other.analyzer))
+                return false;
+            if (fieldVals == null)
+            {
+                if (other.fieldVals != null)
+                    return false;
+            }
+            else if (!fieldVals.Equals(other.fieldVals))
+                return false;
+            if (ignoreTF != other.ignoreTF)
+                return false;
+            if (maxNumTerms != other.maxNumTerms)
+                return false;
+            return true;
+        }
+
+        public FuzzyLikeThisQuery(int maxNumTerms, Analyzer analyzer)
+        {
+            q = new ScoreTermQueue(maxNumTerms);
+            this.analyzer = analyzer;
+            this.maxNumTerms = maxNumTerms;
+        }
+
+        class FieldVals
+        {
+            internal string queryString;
+            internal string fieldName;
+            internal float minSimilarity;
+            internal int prefixLength;
+
+            public FieldVals(string name, float similarity, int length, string queryString)
+            {
+                fieldName = name;
+                minSimilarity = similarity;
+                prefixLength = length;
+                this.queryString = queryString;
+            }
+
+            public override int GetHashCode()
+            {
+                int prime = 31;
+                int result = 1;
+                result = prime * result + ((fieldName == null) ? 0 : fieldName.GetHashCode());
+                result = prime * result + Number.FloatToIntBits(minSimilarity);
+                result = prime * result + prefixLength;
+                result = prime * result + ((queryString == null) ? 0 : queryString.GetHashCode());
+                return result;
+            }
+
+            public override bool Equals(Object obj)
+            {
+                if (this == obj)
+                    return true;
+                if (obj == null)
+                    return false;
+                if (GetType() != obj.GetType())
+                    return false;
+                FieldVals other = (FieldVals) obj;
+                if (fieldName == null)
+                {
+                    if (other.fieldName != null)
+                        return false;
+                }
+                else if (!fieldName.Equals(other.fieldName))
+                    return false;
+                if (Number.FloatToIntBits(minSimilarity) != Number.FloatToIntBits(other.minSimilarity))
+                    return false;
+                if (prefixLength != other.prefixLength)
+                    return false;
+                if (queryString == null)
+                {
+                    if (other.queryString != null)
+                        return false;
+                }
+                else if (!queryString.Equals(other.queryString))
+                    return false;
+                return true;
+            }
+        }
+
+        public virtual void AddTerms(string queryString, string fieldName, float minSimilarity, int prefixLength)
+        {
+            fieldVals.Add(new FieldVals(fieldName, minSimilarity, prefixLength, queryString));
+        }
+
+        private void AddTerms(IndexReader reader, FieldVals f)
+        {
+            if (f.queryString == null)
+                return;
+            TokenStream ts = analyzer.TokenStream(f.fieldName, new StringReader(f.queryString));
+            ICharTermAttribute termAtt = ts.AddAttribute<ICharTermAttribute>();
+            int corpusNumDocs = reader.NumDocs;
+            HashSet<String> processedTerms = new HashSet<String>();
+            ts.Reset();
+            Terms terms = MultiFields.GetTerms(reader, f.fieldName);
+            if (terms == null)
+            {
+                return;
+            }
+
+            while (ts.IncrementToken())
+            {
+                string term = termAtt.ToString();
+                if (!processedTerms.Contains(term))
+                {
+                    processedTerms.Add(term);
+                    ScoreTermQueue variantsQ = new ScoreTermQueue(MAX_VARIANTS_PER_TERM);
+                    float minScore = 0;
+                    Term startTerm = new Term(f.fieldName, term);
+                    AttributeSource atts = new AttributeSource();
+                    IMaxNonCompetitiveBoostAttribute maxBoostAtt = atts.AddAttribute<IMaxNonCompetitiveBoostAttribute>();
+                    SlowFuzzyTermsEnum fe = new SlowFuzzyTermsEnum(terms, atts, startTerm, f.minSimilarity, f.prefixLength);
+                    int df = reader.DocFreq(startTerm);
+                    int numVariants = 0;
+                    int totalVariantDocFreqs = 0;
+                    BytesRef possibleMatch;
+                    IBoostAttribute boostAtt = fe.Attributes.AddAttribute<IBoostAttribute>();
+                    while ((possibleMatch = fe.Next()) != null)
+                    {
+                        numVariants++;
+                        totalVariantDocFreqs = fe.DocFreq;
+                        float score = boostAtt.Boost;
+                        if (variantsQ.Size < MAX_VARIANTS_PER_TERM || score > minScore)
+                        {
+                            ScoreTerm st = new ScoreTerm(new Term(startTerm.Field, BytesRef.DeepCopyOf(possibleMatch)), score, startTerm);
+                            variantsQ.InsertWithOverflow(st);
+                            minScore = variantsQ.Top().score;
+                        }
+
+                        maxBoostAtt.MaxNonCompetitiveBoost = variantsQ.Size >= MAX_VARIANTS_PER_TERM ? minScore : float.NegativeInfinity;
+                    }
+
+                    if (numVariants > 0)
+                    {
+                        int avgDf = totalVariantDocFreqs / numVariants;
+                        if (df == 0)
+                        {
+                            df = avgDf;
+                        }
+
+                        int size = variantsQ.Size;
+                        for (int i = 0; i < size; i++)
+                        {
+                            ScoreTerm st = variantsQ.Pop();
+                            st.score = (st.score * st.score) * sim.Idf(df, corpusNumDocs);
+                            q.InsertWithOverflow(st);
+                        }
+                    }
+                }
+            }
+
+            ts.End();
+            ts.Dispose();
+        }
+
+        public override Query Rewrite(IndexReader reader)
+        {
+            if (rewrittenQuery != null)
+            {
+                return rewrittenQuery;
+            }
+
+            for (IEnumerator<FieldVals> iter = fieldVals.GetEnumerator(); iter.MoveNext();)
+            {
+                FieldVals f = iter.Current;
+                AddTerms(reader, f);
+            }
+
+            fieldVals.Clear();
+            BooleanQuery bq = new BooleanQuery();
+            HashMap<Term, List<ScoreTerm>> variantQueries = new HashMap<Term, List<ScoreTerm>>();
+            int size = q.Size;
+            for (int i = 0; i < size; i++)
+            {
+                ScoreTerm st = q.Pop();
+                List<ScoreTerm> l = variantQueries[st.fuzziedSourceTerm];
+                if (l == null)
+                {
+                    l = new List<ScoreTerm>();
+                    variantQueries[st.fuzziedSourceTerm] = l;
+                }
+
+                l.Add(st);
+            }
+
+            for (IEnumerator<List<ScoreTerm>> iter = variantQueries.Values.GetEnumerator(); iter.MoveNext();)
+            {
+                List<ScoreTerm> variants = iter.Current;
+                if (variants.Count == 1)
+                {
+                    ScoreTerm st = variants[0];
+                    Query tq = ignoreTF ? (Query)new ConstantScoreQuery(new TermQuery(st.term)) : new TermQuery(st.term, 1);
+                    tq.Boost = st.score;
+                    bq.Add(tq, Occur.SHOULD);
+                }
+                else
+                {
+                    BooleanQuery termVariants = new BooleanQuery(true);
+                    for (IEnumerator<ScoreTerm> iterator2 = variants.GetEnumerator(); iterator2.MoveNext();)
+                    {
+                        ScoreTerm st = iterator2.Current;
+                        Query tq = ignoreTF ? (Query)new ConstantScoreQuery(new TermQuery(st.term)) : new TermQuery(st.term, 1);
+                        tq.Boost = st.score;
+                        termVariants.Add(tq, Occur.SHOULD);
+                    }
+
+                    bq.Add(termVariants, Occur.SHOULD);
+                }
+            }
+
+            bq.Boost = Boost;
+            this.rewrittenQuery = bq;
+            return bq;
+        }
+
+        private class ScoreTerm
+        {
+            public Term term;
+            public float score;
+            internal Term fuzziedSourceTerm;
+            public ScoreTerm(Term term, float score, Term fuzziedSourceTerm)
+            {
+                this.term = term;
+                this.score = score;
+                this.fuzziedSourceTerm = fuzziedSourceTerm;
+            }
+        }
+
+        private class ScoreTermQueue : Lucene.Net.Util.PriorityQueue<ScoreTerm>
+        {
+            public ScoreTermQueue(int size): base (size)
+            {
+            }
+
+            public override bool LessThan(ScoreTerm termA, ScoreTerm termB)
+            {
+                if (termA.score == termB.score)
+                    return termA.term.CompareTo(termB.term) > 0;
+                else
+                    return termA.score < termB.score;
+            }
+        }
+
+        public override string ToString(string field)
+        {
+            return null;
+        }
+
+        public virtual bool IsIgnoreTF()
+        {
+            return ignoreTF;
+        }
+
+        public virtual void SetIgnoreTF(bool ignoreTF)
+        {
+            this.ignoreTF = ignoreTF;
+        }
+    }
+}


Mime
View raw message